Come aspetto un programma avviato in un'altra shell?


20

Ho un programma che fa una grande quantità di lavoro (impiega circa 4-5 ore) che viene avviato da cron quando diventano disponibili tutti i dati con cui lavora. A volte, quando aspetto che finisca, vorrei poter avviare un altro programma (interattivo) al termine. la chiamata di attesa sembra promettente, ma attenderà solo i bambini.


L'unico altro metodo che posso immaginare è quello di creare un file da cronjob e quindi utilizzare inotifywait su quel processo, quando i file eliminati, il tuo secondo processo (eseguendo inotifywait) può iniziare.
slm

Penso che potresti fare qualcosa di simile usando ipcanche la comunicazione tra processi. man ipc.
slm

Anche se non stai guardando un servizio per riavviarlo, Dio, Monit o uno degli altri pacchetti citati in queste domande e risposte farebbero anche il lavoro: unix.stackexchange.com/questions/75785/…
slm

@slm può non essere utilizzato su qualsiasi filesystem, ad esempio attendere close_write su / proc / _pid_ / fd / 1?
hildred

Non del tutto sicuro, ma potrebbe essere un altro modo di farlo Cool. C'era qualche Q che ricordo dove c'erano alcune nuove funzionalità del kernel relative al monitoraggio dei processi simili a inotifywait (per i file). Questa nuova funzionalità era per gli eventi in corso, ho pensato, ma molte domande e risposte iniziano a correre insieme nella mia mente Cool. Penso che la A sia stata fornita da me o da Gilles.
slm

Risposte:


13

Preferisco decisamente la soluzione EDIT # 3 (vedi sotto).

se non è nella stessa shell usa un ciclo while con condizione su ps -p che ritorna vero. Metti uno sleep in loop per ridurre l'utilizzo del processore.

while ps -p <pid> >/dev/null 2>&1
do
   sleep 10
done 

o se UNIX supporta / proc (ad esempio HP-UX non lo supporta ancora).

while [[ -d /proc/<pid> ]]
do 
    sleep 10
done

Se vuoi un timeout

timeout=6  # timeout after 1mn  
while ((timeout > 0)) && ps -p <pid> >/dev/null 2>&1
do
   sleep 10
   ((timeout -= 1))
done 

EDIT # 1

C'è un altro modo: non usare cron . Utilizzare il comando batch per impilare i lavori.

Ad esempio, è possibile impilare quotidianamente tutti i lavori. Il batch può essere ottimizzato per consentire un po 'di parallelismo in modo che un lavoro bloccato non arresti l'intero stack (dipende dal sistema operativo).

EDIT # 2

Crea un fifo nella tua home directory:

$ mkfifo ~/tata

alla fine del tuo lavoro:

echo "it's done" > ~/tata

all'inizio dell'altro lavoro (quello che sta aspettando):

cat ~/tata 

Non è polling, è un buon vecchio blocco IO.

EDIT # 3

Utilizzando i segnali:

All'inizio degli script che stanno aspettando:

echo $$ >>~/WeAreStopped
kill -STOP $$

alla fine del tuo lungo lavoro:

if [[ -f ~/WeAreStopped ]] ; then
    xargs kill -CONT < ~/WeAreStopped
    rm ~/WeAreStopped
fi

Polling, schifo! Bella decisione: sprecare il tempo del processore o il mio tempo per ottimizzare il sonno. Deve esserci una risposta migliore.
hildred

:) Il polling fa bene, il polling è apolide, il polling è affidabile.
Emmanuel,

il polling è lento, il poling fa perdere tempo al processore.
hildred

Con un tempo di esecuzione di 0,01 secondi, i 1440 ps eseguiti durante le 4 ore avrebbero consumato 14,4 secondi. Molto meno di uno schedulatore che gestisce le dipendenze dei lavori: D
Emmanuel,

Penso che questa sia probabilmente l'opzione migliore: stackoverflow.com/questions/1058047/… , anche se è confusa.
slm

5

Puoi modificare il tuo cron job per usare qualche flag.

Invece di

2  2 * * *           /path/my_binary

Puoi usare

2  2 * * *           touch /tmp/i_m_running; /path/my_binary; rm /tmp/i_m_running

E basta monitorare questo file in script o anche manualmente. Se esiste, il programma è in esecuzione; altrimenti sentiti libero di fare quello che vuoi.

L'esempio di script:

while [[ -f /tmp/i_m_running ]] ; do
   sleep 10 ;
done
launch_whatever_you_want

Nel caso in cui non ti piace usare sleep, puoi modificare lo script ed eseguirlo tramite cron una volta ogni X minuti.

In tal caso, lo script script sarà:

[[ -f /tmp/i_m_running ]] && { echo "Too early" ; exit ; }
launch_whatever_you_want

In questo modo è un po 'più semplice, poiché non è necessario trovare il PID del processo cron.


4

Non esiste alcuna possibilità per un processo di attendere il completamento di un altro processo, ad eccezione del fatto che un genitore attenda il completamento di uno dei processi figlio. Se puoi, avvia il programma tramite uno script:

do_large_amount_of_work
start_interactive_program

Se non riesci a farlo, ad esempio prima di voler iniziare una grande quantità di lavoro da un cron job ma dal programma interattivo dal contesto della tua sessione, allora fai questo

do_large_amount_of_work
notify_completion

Esistono diversi modi per implementare notify_completion. Alcuni ambienti desktop forniscono un meccanismo di notifica ( aprire una finestra su un display X remoto (perché "Impossibile aprire il display") può essere utile). Puoi anche fare uno usando le notifiche di modifica dei file. Su Linux, la funzione di notifica di modifica dei file non è attiva .

do_large_amount_of_work
echo $? >/path/to/finished.stamp

Per reagire alla creazione di /path/to/finished.stamp:

inotifywait -e close_write -q /path/to/finished.stamp
start_interactive_program

Se non è possibile modificare il modo in cui do_large_amount_of_workviene invocato, ma si conosce quale file viene modificato per ultimo, è possibile utilizzare lo stesso meccanismo per reagire alla chiusura del file. Puoi anche reagire ad altri eventi come la ridenominazione di un file (vedi il inotifywaitmanuale per un elenco di possibilità).


0

Chiedi allo script di essere attivato da cronjob invocare uno script shell vuoto in cui puoi inserire attività di follow-up se ne hai bisogno.

È molto simile all'approccio di Gilles.

cronjob-task.sh contiene:

# do_large_amount_of_work

./post-execute.sh

dove di post-execute.shsolito è vuoto, a meno che tu non veda che devi attivare un'attività di follow-up.

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.