Diferencia entre systemd y programa de inicio de terminal

9

Tengo curiosidad por saber cuál es esta diferencia entre los programas que existen; comenzó con systemd cuando se habilitó a través de systemctl, frente a los que se iniciaron a /etc/rc.localtravés de la CLI.

Por ejemplo, recientemente estaba usando shairport-sync para la frambuesa pi. Inicialmente, configuré shairport-sync para que se inicie mediante sudo systemctl shairport-sync habilitado.

Más adelante, utilicé una funcionalidad shairport-syncpara ejecutar scripts antes y publicar en dispositivos que se conectan.

Para mi sorpresa, los scripts cuando fueron ejecutados por shairport-syncno lo hicieron kill arecordoaplay

Sin embargo, cuando ejecutaba el script a través del terminal, el script se ejecutaba y mataba arecordy aplay.

Para confundirme aún más, lo maté shairport-syncy lo inicié a través de la terminal para ver la salida de lo que estaba sucediendo. Cuando lo hice, los scripts funcionaron como esperaba cuando el dispositivo se conectó y se apagó arecordy aplay. Por lo tanto, como una solución He desactivado shairport-syncen sysmtectly configurarlo para que se ejecute en /etc/rc.localcomo una solución rápida. Después de un rebootfuncionó como esperaba.

Esto me lleva a creer que hay alguna diferencia entre un programa que se ejecuta por separado systemdy un programa que se ejecuta cuando se inicia a través de /etc/rc.localla CLI.

¿Por qué pasó esto? ¿Esto se debe a los diferentes niveles de ejecución? ¿Un poco de magia oscura?

El script que se ejecuta cuando un dispositivo se conecta shairport-synces el siguiente:shairportstart.sh

#!/bin/sh
/usr/bin/sudo /bin/pkill arecord
if [ $(date +%H) -ge "18" -o $(date +%H) -le "7" ]; then
        /usr/bin/amixer set Speaker 40%
else
        /usr/bin/amixer set Speaker 100%
fi
/home/pi/shScripts/shairportfade.sh&

exit 0

Aquí está el script de desvanecimiento: shairportfade.sh

#!/bin/sh
/usr/bin/amixer set Speaker 30-
for (( i=0; i<30; i++))
do  
    /usr/bin/amixer set Speaker 1+
done
exit 0

El script que se ejecuta cuando un dispositivo se desconecta shairport-synces el siguiente:shairportend.sh

#!/bin/sh
/usr/bin/amixer set Speaker 70%
/usr/bin/arecord -D plughw:1 -f dat | /usr/bin/aplay -D plughw:1 -f dat&
exit 0

Encontré el siguiente error en el /var/log/syslogúnico cuando shairport-sync se ejecutó inicialmente como parte de systemd. Cuando shairport-syncse ejecutó desde la CLI o /etc/rc.localno hubo errores presentes.

Jan 24 00:38:45 raspberrypi shairport-sync[617]: sudo: no tty present and no askpass program specified

Tenga en cuenta que la única diferencia es cómo shairport-syncse inicia inicialmente, cuando los dispositivos conectados o desconectados shairport-synccontinúan ejecutándose.

Brett Reinhard
fuente
1
Ese ps ... awk ... grep ...material podría ser reemplazada por una simplepkill
thrig
@thrig originalmente la línea era mucho más simple, pero como no funcionaba, pensé que intenté usar otros métodos para eliminar la instancia que todavía no funcionaba. Matar el proceso no era el problema per se, ya que funcionaba, pero solo cuando se ejecutaba desde el inicio de sesión de un usuario
Brett Reinhard el
¿Puedes mostrar el listado de /home/pi/shScripts/shairportfade.sh?
Michael D.
@MichaelD. He agregado el script de desvanecimiento, así como el script que se ejecuta cuando un dispositivo se desconecta a shairport-sync
Brett Reinhard
@BrettReinhard cuál es el problema con la ejecución del scriptrc.local
Michael D.

Respuestas:

18

Variaciones de "¿Por qué las cosas se comportan de manera diferente bajo systemd?" son una pregunta frecuente

Cada vez que algo se ejecuta desde la CLI y no desde systemd, hay algunas categorías amplias de posibilidades para explicar las diferencias.

  1. Diferentes variables de entorno . systemddocumenta las variables de entorno que pasa man systemd.execen la sección Variables de entorno en procesos generados . Si desea inspeccionar la diferencia usted mismo, puede usarlo systemd-run /path/to/binary, ejecutará su aplicación en un ámbito transitorio, como lo haría un servicio systemd. Usted obtendrá una salida como: Running as unit: run-u160.service. Luego puede journalctl -u run-u160.servicerevisar la salida. Modifique su aplicación para volcar las variables de entorno que recibe y compare la ejecución de CLI con la ejecución de systemd. Si la aplicación no se modifica convenientemente, puede usarla systemd-run envpara ver las variables de entorno que se pasarían y revisar el registro de diario resultante. Si está intentando iniciar una aplicación X11 GUI, se debe establecer la DISPLAYvariable de entorno. En ese caso, considere usar la función de "inicio automático" de su entorno de escritorio en lugar de systemd.
  2. Restricciones de recursos . Consulte man systemd.resource-controllos valores de configuración que podrían restringir el consumo de recursos. Utilícelo systemctl show your-unit-unit.servicepara verificar los valores de configuración completos que afectan el servicio que intenta iniciar.
  3. Shell no interactivo . Su bashentorno CLI es un shell de inicio de sesión interactivo . Ha originado archivos como .bashrcese systemdno. Además de establecer variables de entorno, estos scripts pueden hacer muchas otras cosas, como conectar un agente SSH para que las acciones SSH no requieran un inicio de sesión. Consulte también ¿ Diferencia entre Shell de inicio de sesión y Shell sin inicio de sesión?
  4. Sin TTY . Su sesión interactiva está conectada a un TTY que a algunos programas les gusta sudoy sshesperan al solicitar contraseñas. Ver también sudo: no hay tty presente y no se especificó el programa askpass
  5. Caminos relativos versus absolutos . El trabajo binario relativo en el shell, pero como se documenta enman systemd.service , el primer argumento ExecStart=debe ser una ruta absoluta a un binario.
  6. Sintaxis de línea de comando restringida . Las CLI de Shell admiten muchos metacaracteres, mientras que systemdtienen una sintaxis de línea de comandos muy restringida . Dependiendo de sus necesidades, puede replicar la sintaxis de Shell systemdejecutando explícitamente su comando a través de un shell:ExecStart=/bin/bash -c '/my/bash $(syntax) >/goes-here.txt'

Es una característica que el sistema ejecuta su código en un entorno consistente con controles de recursos. Esto ayuda con resultados reproducibles y estables a largo plazo sin abrumar al hardware.

Mark Stosberg
fuente
También es necesario tener en cuenta el contexto MAC (SELinux, ...), las capacidades, los espacios de nombres ...
Bigon
2
@BrettReinhard No invoque sudoun script de shell que se ejecute mejor sudo shairportstart.shdesde la terminal, ya que systemd ejecuta el script como root, no es necesario sudo como root.
Michael D.
1
Resolví mi problema de varias maneras en mi intento de entender lo que estaba sucediendo. Finalmente, lo que terminé haciendo fue cambiar mi comando de matar a /usr/bin/echo "mypassword" | /usr/bin/sudo /bin/pkill arecord. Más tarde hoy, intentaré eliminar los comandos sudoy echode mi comando kill y ver si eso arroja los mismos resultados. Supongo que funcionará, ya que parece que el error fue causado por el envío de una contraseña con el sudocomando. Gracias por la ayuda para comprender por qué hay una diferencia entre systemdy la CLI
Brett Reinhard
1
Otra diferencia, que puede ser obvia pero que me mordió hoy, es que systemd intenta rastrear el estado de un servicio y no lo iniciará si cree que ya está activo, por lo que es posible que ni siquiera inicie un script init.d si piensa que el servicio se está ejecutando. Por el contrario, los scripts init.d generalmente se escriben para verificar siempre e intentar iniciar el servicio según corresponda.
Josh Kelley
1
@JoshKelley Gracias por la sugerencia. Esa no es una diferencia entre systemd y la CLI, sino entre systemd y sysVinit init.d scripts.
Mark Stosberg