¿Cómo ejecutar un proceso a largo plazo en un evento Udev?

11

Quiero ejecutar una conexión ppp cuando mi módem USB está conectado, así que uso esta udevregla:

ACTION=="add", SUBSYSTEM=="tty", ATTRS{idVendor}=="16d8",\
    RUN+="/usr/local/bin/newPPP.sh $env{DEVNAME}"

(Mi módem aparece /devcomo ttyACM0)

newPPP.sh:

#!/bin/bash
/usr/bin/pon prov $1 >/dev/null 2>&1 &

Problema:

El udevevento se dispara y newPPP.sh se está ejecutando, pero el newPPP.shproceso finaliza después de ~ 4-5s. pppno tiene tiempo para conectarse (su tiempo de espera es de 10 segundos para acceso telefónico).

¿Cómo puedo ejecutar un proceso a largo plazo que no se eliminará?

Intenté usarlo nohup, pero tampoco funcionó.

Sistema: Arch Linux

Actualizar

Encontré una solución aquí , gracias a maxschlepzig .

Solía at nowejecutar mi trabajo separado del proceso udev.

Pero la única pregunta sigue sin respuesta: ¿Por qué trabajar nohupy &no trabajar?

Comunidad
fuente

Respuestas:

11

Si ejecuta una distribución decente con soporte systemd, la forma más fácil y técnicamente más segura es utilizar una unidad de dispositivo .

De esta manera, systemd tendrá el control total de la secuencia de comandos de larga ejecución e incluso podrá finalizar correctamente el proceso una vez que el dispositivo se apaga / retira: al desconectar el proceso significa que está renunciando a tener el control total del estado del proceso y su historia

Además de eso, podrá inspeccionar el estado del dispositivo y su servicio adjunto mediante la ejecución systemctl status my-ppp-thing.device.

Consulte también esta publicación de blog para obtener más ejemplos y detalles.

Elias Probst
fuente
6

Hoy en día, udev usa cgroups para buscar y destruir tareas generadas. Una solución es usar "en este momento" o "lote". Otra solución es hacer doble fork y "reubicar" el proceso a otro cgroup. Este es un código de python de ejemplo (se puede escribir un código similar en cualquier idioma):

os.closerange(0, 65535)  # just in case
pid = os.fork()
if not pid:
  pid = os.fork()  # fork again so the child would adopted by init
  if not pid:
    # relocate this process to another cgroup
    with open("/sys/fs/cgroup/cpu/tasks", "a+") as fd:
      fd.write(str(os.getpid()))
    sleep(3)  # defer execution by XX seconds
    # YOUR CODE GOES HERE
sleep(0.1)  # get forked process chance to change cgroup

La salida de depuración se puede enviar, por ejemplo, a syslog.

Alexandre Kandalintsev
fuente
1
¿Por qué udev iría tan lejos para destruir los procesos generados?
user30747
Supongo que es porque los programas iniciados por udev bloquean el demonio (por ejemplo, con una regla de udev conectada para enchufar una pantalla externa, un programa de larga duración evitará que la nueva pantalla se use realmente). Estoy seguro de que tiene su propio razonamiento técnico, pero significa que los procesos generados pueden retener partes importantes del sistema y deben ser eliminados.
tobek
2

Shell tiene la capacidad de ejecutar comandos en segundo plano:

(

lots of code

) &

Los comandos agrupados por las llaves con ampersand después de ellos se ejecutarán de forma asíncrona en una subshell. Lo uso para conectarme automáticamente cuando se inserta y se conmuta un módem USB. Tarda unos 20 segundos y funciona bien bajo udev.

usuario42295
fuente
Es posible que desee redirigir stderr, stdout y stderr en tal situación.
mdpc
@mdpc hmm ... ¿por qué? Vi usb_modeswitch cierra transmisiones en este escenario: exec 1 <& - 2 <& - 5 <& - 7 <& -
user42295
1

Lo tengo para trabajar con setsid. Mi RUN parte de la regla udev:

RUN+="/bin/bash script.sh"

luego en el guión:

#!/bin/bash
if [ "$1" != "fo_real" ]; then
  /usr/bin/setsid $(/usr/bin/dirname $0)/$(/usr/bin/basename $0) fo_real &
  exit
fi

Rest of script is here....

La primera llamada al script regresa con el estado de salida 0, pero la segunda llamada al script continúa ejecutándose con PPID = 1.

Vivo
fuente
0

Probablemente porque su proceso padre finaliza y la señal de terminación se propaga a sus hijos, que no lo bloquean (y en caso de SIGKILLque ni siquiera puedan).

Peterph
fuente