¿Cómo ejecuto un solo comando al inicio usando systemd?

113

Me gustaría iniciar un clúster Apache Spark después del arranque con el siguiente comando:

sudo ./path/to/spark/sbin/start-all.sh

Luego ejecute este comando cuando el sistema se prepare para reiniciar / apagar:

sudo ./path/to/spark/sbin/stop-all.sh

¿Cómo puedo comenzar? ¿Hay una plantilla básica sobre la que pueda construir?

He intentado usar un extremadamente simple (file:) /lib/systemd/system/spark.service:

[Unit]
Description=Spark service

[Service]
ExecStart=sudo ./path/to/spark/sbin/start-all.sh

Lo que no funciona.

macourtney7
fuente
Hola @WillemK, ya había visto esta página. Este problema que he encontrado es que no puedo simplemente reemplazar execcon ExecStart=. Además, no he usado advenedizos antes.
macourtney7
1
El punto antes de la ruta de su script parece extremadamente sospechoso.
Andrea Lazzarotto
@AndreaLazzarotto Creo que OP está tratando de ejecutar el script como OP lo haría en la terminal, por lo tanto, el ....
George Udosen
Hola @AndreaLazzarotto, esto es correcto. Disculpas por cualquier confusión causada.
macourtney7

Respuestas:

144

Su .servicearchivo debería verse así:

[Unit]
Description=Spark service

[Service]
ExecStart=/path/to/spark/sbin/start-all.sh

[Install]
WantedBy=multi-user.target

Ahora realice algunos pasos más para habilitar y usar el .servicearchivo:

  1. Colóquelo en la /lib/systemd/systemcarpeta con decir un nombre demyfirst.service

  2. Haga que su script sea ejecutable con:

    chmod u+x /path/to/spark/sbin/start-all.sh
    
  3. Iniciarlo:

    sudo systemctl start myfirst
    
  4. Permitir que se ejecute en el arranque:

    sudo systemctl enable myfirst
    
  5. Para:

    sudo systemctl stop myfirst
    

Notas:

  1. No necesita iniciar Spark con sudo en su servicio, ya que el usuario predeterminado del servicio ya es root.

  2. Mira los enlaces a continuación para obtener más systemdopciones.

ACTUALIZAR

Ahora lo que tenemos arriba es simplemente rudimentario, aquí hay una configuración completa para spark:

[Unit]
Description=Apache Spark Master and Slave Servers
After=network.target
After=systemd-user-sessions.service
After=network-online.target

[Service]
User=spark
Type=forking
ExecStart=/opt/spark-1.6.1-bin-hadoop2.6/sbin/start-all.sh
ExecStop=/opt/spark-1.6.1-bin-hadoop2.6/sbin/stop-all.sh
TimeoutSec=30
Restart=on-failure
RestartSec=30
StartLimitInterval=350
StartLimitBurst=10

[Install]
WantedBy=multi-user.target

Para configurar el servicio:

sudo systemctl start spark.service
sudo systemctl stop spark.service
sudo systemctl enable spark.service

Otras lecturas

Por favor, lea los siguientes enlaces. Spark es una configuración compleja, por lo que debe comprender cómo se integra con el servicio de inicio de Ubuntu.

https://datasciencenovice.wordpress.com/2016/11/30/spark-stand-alone-cluster-as-a-systemd-service-ubuntu-16-04centos-7/

https://www.digitalocean.com/community/tutorials/understanding-systemd-units-and-unit-files

https://www.freedesktop.org/software/systemd/man/systemd.unit.html

George Udosen
fuente
Notado y actualizado
George Udosen,
1
Gracias por esto, he creado un archivo basado en lo que sugirió. Al correr sudo systemctl start sparkse recibe el siguiente error:Failed to start spark.service: Unit spark.service is not loaded properly: Invalid argument. See system logs and 'systemctl status spark.service' for details.
macourtney7
La parte principal de systemctl status spark.servicees la siguiente: Executable path is not absoluteyspark.service: Service lacks both ExecStart= and ExecStop= setting. Refusing.
macourtney7
Los problemas son 1) Se necesita la ruta binaria de Spark (debe reemplazar lo que tenemos en el archivo de servicio), 2) Spark tiene un comando de apagado. 3) Revisaste los enlaces que te di. No uso chispa, así que
ofrézcalos
@GeorgeUdosen Gracias por su respuesta, mi pregunta es ¿cómo puedo ejecutar la chispa bajo un comando específico después de reiniciar? La pregunta está aquí askubuntu.com/questions/979498/…
Soheil Pourbafrani
2

Esto crea y se ejecuta /root/boot.shen el arranque (como root) usando un archivo de servicio mínimo:

bootscript=/root/boot.sh
servicename=customboot

cat > $bootscript <<EOF
#!/usr/bin/env bash
echo "$bootscript ran at $(date)!" > /tmp/it-works
EOF

chmod +x $bootscript

cat > /etc/systemd/system/$servicename.service <<EOF
[Service]
ExecStart=$bootscript
[Install]
WantedBy=default.target
EOF

systemctl enable $servicename

Puede Ctrl+ Cesto en una terminal raíz.

Para modificar los parámetros, por ejemplo, para usar una diferente $bootscript, configure esa variable manualmente y simplemente omita esa línea al copiar los comandos.

Después de ejecutar los comandos, puede editar el script de arranque utilizando su editor favorito, y se ejecutará en el próximo arranque. También puede ejecutarlo inmediatamente usando:

systemctl start $servicename

Cada paso podría hacerse con sudo, pero es un poco más complicado, y algunos sistemas no tienen sudo instalado, por lo que algunas personas tendrían que modificar el ejemplo antes de usarlo. Por lo tanto, elegí no incluir sudo en el ejemplo.

Luc
fuente
Estoy un poco confundido por los documentos de systemd, pero no debería serlo Type=oneshot RemainAfterExit=yeso systemd considerará la tarea inactiva a menos que el script personalizado deje algunos procesos en ejecución.
Peter Lamberg
@PeterLamberg También intenté leer los documentos de systemd y, sin embargo, aquí estamos los dos;). Recuerdo que no estaban muy claros, pero la respuesta que publiqué funciona para mí en múltiples sistemas (reviso esta página de vez en cuando cuando la necesito nuevamente). ¿Quiere decir que, dado que se considera 'inactivo', cada llamada sucesiva de 'inicio' volverá a ejecutar el script? Porque lo consideraría como se esperaba para un script de shell. Me resultaría extraño si tuviera que 'detener' algo que en realidad no se está ejecutando antes de poder comenzar de nuevo.
Luc