Pagina 1 di 1

uscita da script con processi in background

Inviato: mar 11 gen 2011, 16:57
da ZeroUno
In alcuni script mi ritrovo a dover avviare dei comandi in backgroud, a volte anche più di uno in contemporanea. Molti di questi poi (che possono essere binari o altri scr bash, perl, pyton...) lanciano a volte altri comandi/script o forkano.

Io voglio assicurarmi che quando esco dal mio script, che sia per uscita naturale (fine script o exit), o uscita per errore (se c'è set -e) o CTRL+C o kill (il kill semplice... so che il -9 non lo puoi controllare un granchè), i programmi rimasti in backgroud muoiano tutti, compresi i loro figli.

Io invece mi ritrovo che che morto lo script principale, in linea di massima gli altri continuano ad esistere, con parent pid=1, e sono costretto a fare kill manuale di tutti, uno ad uno (o almeno quasi tutti... solitamente per i binari che forkano, morto il padre muore anche il figlio, anche se non sempre)

il caso più semplice:

Codice: Seleziona tutto

#!/bin/bash
./programma & PID=$!
..altro..
questo non lo faccio mai (a meno che non sia voluto); solitamente faccio sempre in modo che tutto abbia una fine

Codice: Seleziona tutto

#!/bin/bash
./programma & PID=$!
..altro..
wait $PID
questi li faccio spesso:

Codice: Seleziona tutto

#!/bin/bash
./programma1 > /tmp/log & PID1=$!
tail -f /tmp/log & PID2=$!
wait $PID1
kill $PID2

Codice: Seleziona tutto

#!/bin/bash
./programma1 & PID1=$!
while ps $PID1 >/dev/null;do
  echo -n .
  sleep 1
done
wait $PID1
ma al ctrl+c non muoiono i processi, tanto meno i figli

Ho anche provato ad usare le trap

Codice: Seleziona tutto

#!/bin/bash
trap 'kill $PID' SIGINT # SIGINT corrisponde a ctrl+c
...
ma sembra che non ce la faccia, o almeno sicuramente non uccide i figli.



Idee?

Ciao
01

Re: uscita da script con processi in background

Inviato: mar 11 gen 2011, 22:15
da sixjan
Qui ci sono alcune soluzioni interessanti:

http://stackoverflow.com/questions/3920 ... -processes

Ciao

Re: uscita da script con processi in background

Inviato: mer 12 gen 2011, 0:46
da ZeroUno
Questo non risolve il problema...
un qualcosa che mi killa i processi ricorsivamente lo so fare pure io.
Quello che voglio è che questo venga fatto PRIMA della chiusura dello script in caso quest'ultimo venga fermato con kill o ctrl+c. Quello che non ho capito è perche questo non avviene in automatico.

per lo script che sto facendo ora ho trovato un work around.
Il programma1 che solitamente metto in background ma che mi interessa che muoia insieme allo script l'ho messo in foreground, e il programma2 ovvero quello che sarebbe stato da mettere dopo non mi interessava in foreground, l'ho messo prima, in una shell separata, facendogli credere che stia dopo.

Codice: Seleziona tutto

#!/bin/bash
(
  while ! ps -ef |grep -q programma1;do echo "wait for programma1"; sleep 1;done
  programma2
) & PID=$!
programma1
kill $PID
se muore lo script sinceramente non sono riuscito a capire se muore anche la subshell e quindi programma2, ma non mi interessa un granchè e nel caso specifico funziona.

Ciao
01

Re: uscita da script con processi in background

Inviato: mer 12 gen 2011, 20:52
da Mario Vanoni
Esperimento:

Codice: Seleziona tutto

root@va2:~# ls >/dev/null & PID=$! ; echo $PID
[1] 28019
28019
root@va2:~# ls >/dev/null & PID=$$ ; echo $PID
[2] 5030
8872
[1]   Done                    ls >/dev/null
root@va2:~# ls >/dev/null & PID=$! ; echo $PID $PPID
[3] 20159
20159 8797
[2]   Done                    ls >/dev/null
root@va2:~# ls >/dev/null & PID=$$ ; echo $PID $PPID
[4] 29657
8872 8797
[3]   Done                    ls >/dev/null
a te le conclusioni.

Re: uscita da script con processi in background

Inviato: gio 13 gen 2011, 0:27
da ZeroUno
sisi, conosco questa roba, ma le cose non mi cambiano; il problema non è sulla conoscenza dei pid ma della loro uccisione.
se ho una alberatura del genere:

Codice: Seleziona tutto

bash
\-- script.sh
    |-- child.sh &
    |   \-- childofchild.sh
    |       \-- lastcommand.sh
    \-- program
child.sh è lanciato da script.sh in background (e quindi in foreground c'è 'program', lanciato sempre da script.sh)
in caso 'program' termina in modo naturale (con successo o senza successo, ma termina), alla riga successiva ci posso mettere un kill di child.sh che ucciderà tutta l'alberatura di child.sh.
In caso do un kill di script.sh o do un ctrl+c, il comando kill che si trova dopo program non viene eseguito e child diventa figlio di init, e l'unica soluzione che sono riuscito a trovare è utilizzare le trap in modo da forzare l'esecuzione del kill di child.sh anche in caso di ctrl+c.
Peggio ancora se anche childofchild.sh è avviato in background

In pratica sembra che si comporti come se fosse stato lanciato con il nohup.

Io ricordo che in passato se facevo qualcosa tipo

Codice: Seleziona tutto

# sleep 100 &
#exit
Ottenevo un messaggio del tipo "you have running jobs" (o simile) e restituiva il prompt e se da un'altra shell davo kill della prima allora i processi in background morivano, a meno che questi non fossero stati lanciati con nohup.
E così, anche, se lanciavo un programma grafico in background, alla chiusura della shell questo moriva. Ora no.
Ed anche, se mi collegavo in ssh ad una macchina remota e lanciavo un comando in background, se davo un exit mi rimaneva la connessione ssh appesa fino a che non premevo ctrl+c con conseguente uccisione dei processi lanciati in background sulla macchina remota o fino alla loro naturale chiusura.

Ciao
01