Translate

viernes, 22 de junio de 2018

Configuración de systemd para arranque/paro de scripts


  • Nota: systemd NO está bien hecho, además tiene muchos bugs. Desafortunadamente muchos distribuidores de Linux decidieron meter este sistema de arranque por lo que a veces se hace necesario usarlo al igual Microsoft. Una de las muchas falacias que esgrimen sus creadores es que se usa en los principales sistemas operativos modernos ya que además levanta muy rápido. Android, que son la mayoría de los dispositivos con Linux, no lo emplea y SÍ he visto teléfonos con Android de hace más de 5 años que levantan en menos de 10 segundos. Ver: adopción de systemd.
A lo que te truje chencha: Este es un ejemplo de montaje/desmontaje de un filesystem, con arranque/paro, probado en Debian 4.9.65 , kernel 4.9.0-4-amd64. El script es de un usuario que necesita montar una carpeta remota de un servidor (por sshfs) cuando arranca el sistema.

El script de ejemplo se llama monta.sh, el servicio se llama monta.service
  1. Creamos el script de montaje/desmontaje. Este irá en la carpeta bin del directorio de inicio ($HOME) del usuario . El usuario en este ejemplo (username) sera 'usuario':
  2. mkdir bin; cd bin
vi monta.sh
_____________
#!/bin/bash

uso(){
   echo "Uso: $0 start|stop|status";
   exit 1
}
status () { 
   mount | grep /home/usuario/servidor
}

start () { 
#Este es un montaje por sshfs, pero se puede usar un simple mount
#En este ejemplo se monta la carpeta del servidor /home/usuario en la carpeta local /home/usuario/servidor
#Esta carpeta local deberá haber sido creada

   ret=$( sshfs usuario@servidor.com:/home/usuario /home/usurario/servidor );
   status;
   return $ret
}
stop () { 
  #en este ejemplo concreto estamos desmontando con umount que requiere permisos de root
  #El comando umount /home/usuario/servidor se tendrá que poner el archivo /etc/sudoers
  #para el usuario correspondiente
   sudo umount /home/usuario/servidor;
   return $?
}

case $1 in
   start|stop|status) "$1"
   ;;
   *)   uso
   ;;
esac

_____________

Le ponemos permisos de ejecución:
chmod a+x monta.sh



  1. Ahora como root, creamos el archivo monta.service:

vi /lib/systemd/system/monta.service
________________________
[Unit]
Description=Monta una carpeta de un servidor remoto del usuario
#After=network.target 
After=network-online.target

[Service]
Type=simple
User=usuario
WorkingDirectory=/home/usuario
ExecStart=/home/usuario/bin/monta.sh start
ExecStop=/home/usuario/bin/monta.sh stop
RemainAfterExit=yes


[Install]
WantedBy=multi-user.target

________________________

Le ponemos sus permisos por si no los tiene correctos (no es ejecutable):

chmod 644 /lib/systemd/system/monta.service

Habilitamos el servicio con:

systemctl enable monta.service

Debe salir un mensaje similar a :

Created symlink /etc/systemd/system/multi-user.target.wants/monta.service → /lib/systemd/system/monta.service.


Recargamos el systemd:

systemctl daemon-reload


Probamos el servicio:


systemctl start monta.service
systemctl status monta.service

systemctl stop monta.service
systemctl status monta.service


Problemas:

Desafortunadamente pueden ser muchos por parte del systemd. Pero si el script funciona correctamente y ya se hicieron pruebas pero el sistemd se niega a trabajar, intente:




systemctl disable monta.service; systemctl daemon-reload; systemctl enable monta.service; systemctl start monta.service; systemctl status monta.service


systemctl restart monta.service . (En mi caso, solo así logré que reaccionara )


Otro problema es la secuencia de arranque los procesos que para poder ver que servicio o 'target' empezó o ha sido levantado se le puede dar el comando para analizar la secuencia de arranque:

systemd-analyze plot > output.svg

Y luego verlo con algún visor de imágenes como el eog:

eog output.svg

Un truco que puede funcionar, si no está claro en que momento debe de ejecutarse el proceso, es meter un retardo en el script, en mi caso fue suficiente con un retardo de 10 segs:


start () { 
   sleep 10
   ret=$( sshfs usuario@servidor.com:/home/usuario /home/usurario/servidor );
   status;
   return $ret
}



Pero me di cuenta que existe otro 'target' aparte de network.target que se llama 'network-online.target' y aparentemente con eso ya no hubo problemas.  La terminología de systemd es realmente ambigua y confusa. Quedaría ver si al levantar el usuario de manera automátcia, se monta el filesystem.

Actualización:
Efectivamente, al realizarse un login automático ya no aparece el icono de filesystem montado ya que el ambiente gráfico levanta antes que lo que el servicio monta.service logre montar el filesystem. Eso significa que se tuvo que modificar el target graphical.target para que esperara al serivio monta.service

vi /lib/systemd/system/graphical.target

________________________

[Unit]
Description=Graphical Interface
Documentation=man:systemd.special(7)
Requires=multi-user.target monta.service
Wants=display-manager.service monta.service
Conflicts=rescue.service rescue.target
After=multi-user.target rescue.service rescue.target display-manager.service monta.service
AllowIsolate=yes
_________________________


Es probable que sobre algún monta.service, pero solo me funcionó poniéndolo en las tres lineas mostradas ( Requires, Wants, After ). Otra confusión y ambigüedad de definiciones en el systemd, ya que el texto no es autoexplicativo. Además que hay que ver que otros 'services' o 'targets' purieran quedar afectados como es este caso. En resumen, no es un sistema que te haga ganar tiempo en la configuración del sistema operativo,es demasiado complejo en la cantidad de componentes y tiene muchas ambigüedades. El lado bueno: es que ambigüedad va con diérisis y no siempre pones palabras con diéresis en español.

Actualización 2:

Tampoco sirve graphical.taget, no parece ser el target correcto. Aparentemente con systemd-user-sessions.service si funciona:

vi /lib/systemd/system/systemd-user-sessions.service
_____________________________
[Unit]
Description=Permit User Sessions
Documentation=man:systemd-user-sessions.service(8)
After=remote-fs.target nss-user-lookup.target network.target monta.service

[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/lib/systemd/systemd-user-sessions start
ExecStop=/lib/systemd/systemd-user-sessions stop
___________________________


Referencia: systemd.unit

No hay comentarios: