Come eseguire un processo a lungo sull'evento Udev?


11

Voglio eseguire una connessione ppp quando il mio modem USB è collegato, quindi uso questa udevregola:

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

(Il mio modem appare /devcome ttyACM0)

newPPP.sh:

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

Problema:

L' udevevento viene generato e newPPP.sh è in esecuzione, ma il newPPP.shprocesso viene interrotto dopo ~ 4-5 secondi. pppnon ha tempo di connettersi (il timeout è di 10 secondi per la connessione remota).

Come posso eseguire un processo a lungo, che non verrà ucciso?

Ho provato a usare nohup, ma non ha funzionato neanche.

Sistema: Arch Linux

Aggiornare

Ho trovato una soluzione qui , grazie a maxschlepzig .

Uso at nowper eseguire il mio lavoro distaccato dal processo udev.

Ma l'unica domanda rimane senza risposta: perché fare nohupe &non funziona?

Risposte:


11

Se si esegue una distribuzione decente con il supporto di systemd, il modo più semplice e tecnicamente più sicuro è utilizzare un'unità dispositivo .

In questo modo, systemd avrà il pieno controllo dello script di lunga durata e sarà anche in grado di terminare correttamente il processo una volta che il dispositivo è spento / rimosso - staccare il processo significa che stai rinunciando ad avere il pieno controllo dello stato del processo e la sua storia.

Oltre a ciò, sarai in grado di ispezionare lo stato del dispositivo e il servizio collegato eseguendo systemctl status my-ppp-thing.device.

Vedi anche questo post sul blog per alcuni altri esempi e dettagli.


6

Oggi udev utilizza i cgroup per cercare le attività generate. Una soluzione è utilizzare "at now" o "batch". Un'altra soluzione è eseguire il doppio fork e "riposizionare" il processo in un altro cgroup. Questo è un esempio di codice Python (un codice simile può essere scritto in qualsiasi lingua):

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

L'output di debug può essere inviato, ad esempio, a syslog.


1
Perché udev dovrebbe fare di tutto per distruggere i processi generati?
user30747,

Immagino sia perché i programmi avviati da udev bloccano il demone (ad es. Con una regola udev collegata al collegamento del display esterno, un programma di lunga durata impedirà che il nuovo display venga effettivamente utilizzato). Sono sicuro che ha un suo ragionamento tecnico dietro, ma significa che i processi generati possono contenere parti importanti del sistema e devono essere uccisi.
tobek,

2

Shell ha la capacità di eseguire comandi in background:

(

lots of code

) &

I comandi raggruppati dalle parentesi graffe con la e commerciale dopo di essi verranno eseguiti in modo asincrono in una subshell. Lo uso per connettersi automaticamente quando un modem USB viene inserito e cambiato. Ci vogliono circa 20 secondi e funziona bene sotto udev.


Potresti voler reindirizzare stderr, stdout e stderr in una situazione del genere.
mdpc,

@mdpc hmm ... perché? Ho visto usb_modeswitch chiudere i flussi in questo scenario: exec 1 <& - 2 <& - 5 <& - 7 <& -
user42295

1

Ho capito che funziona con setsid. La mia parte RUN della regola udev:

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

quindi nella sceneggiatura:

#!/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 prima chiamata allo script ritorna con lo stato di uscita 0, ma la seconda chiamata allo script continua a essere eseguita con PPID = 1.


0

Probabilmente perché il suo processo genitore è terminato e il segnale di terminazione si propaga ai suoi figli, il che non lo blocca (e nel caso in cui SIGKILLnon riescano nemmeno).

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.