Ascolta l'uscita dal processo dato pid $$


16

Di 'che ho un pid in mano, mypid=$$

c'è qualche comando bash / system che posso usare per ascoltare l'uscita di quel processo con il pid dato?

Se non esiste un processo con mypid, immagino che il comando non debba semplicemente fallire.


Non uso C #, ma a quanto pare deve esserci un modo: msdn.microsoft.com/en-us/library/fb4aw7b8(v=vs.110).aspx
Alexander Mills,

In Unix, è comune attendere i processi figlio utilizzando waitnella funzione shell o wait()C library. Non esiste AFAIK un modo standard di attendere un processo non figlio. Non è ancora chiaro se la funzione C # può farlo (dipende da cosa sia un "processo associato").
Kusalananda

Potrei farlo con il sondaggio, ma sarebbe terribile
Alexander Mills,

Potrebbe anche dare risultati errati. Il riutilizzo del PID può teoricamente significare che un processo potrebbe prendere vita con lo stesso PID del processo che stai aspettando. Su Linux (con PID sequenziali) questo sarebbe improbabile , ma su sistemi come OpenBSD (allocazione PID randomizzata), sarebbe un problema.
Kusalananda

Risposte:


21

Ho ottenuto ciò di cui avevo bisogno da questa risposta: https://stackoverflow.com/a/41613532/1223975

... si scopre che wait <pid> funzionerà solo se quel pid è un processo figlio del processo corrente .

Tuttavia, per qualsiasi processo funzionerà quanto segue:

Attendere il completamento di qualsiasi processo

Linux:

tail --pid=$pid -f /dev/null

Darwin (richiede che $pidabbia file aperti):

lsof -p $pid +r 1 &>/dev/null

Con timeout (secondi)

Linux:

timeout $timeout tail --pid=$pid -f /dev/null

Darwin (richiede che $pidabbia file aperti):

lsof -p $pid +r 1m%s -t | grep -qm1 $(date -v+${timeout}S +%s 2>/dev/null || echo INF)

Non è legato a Linux, è una caratteristica della coda GNU. Quindi funzionerà su qualsiasi sistema con coda GNU come quelli GNU / Linux e non funzionerebbe su sistemi basati su Linux non GNU.
Stéphane Chazelas,

Temo che tail / lsof userà il polling in questo caso, almeno date le prove empiriche che appare così su MacOS.
Alexander Mills,

lsof + r lo mette in modalità ripetizione, quindi quel comando si ripete ogni secondo, quindi usa il polling, accidenti
Alexander Mills,

3

Puoi usare il comando incorporato bash wait:

$ sleep 10 &
[2] 28751
$ wait 28751
[2]-  Done                    sleep 10
$ help wait
wait: wait [-n] [id ...]
    Wait for job completion and return exit status.

    Waits for each process identified by an ID, which may be a process ID or a
    job specification, and reports its termination status.  If ID is not
    given, waits for all currently active child processes, and the return
    status is zero.  If ID is a a job specification, waits for all processes
    in that job's pipeline.

    If the -n option is supplied, waits for the next job to terminate and
    returns its exit status.

    Exit Status:
    Returns the status of the last ID; fails if ID is invalid or an invalid
    option is given.

Utilizza la chiamata di sistema waitpid()..

$ whatis waitpid
waitpid (2)          - wait for process to change state

bello che funziona per me, speriamo non usi il polling sotto il cofano, grazie!
Alexander Mills,

1
sì, non funzionerà per il mio caso d'uso, ricevo questo errore: bash: wait: pid 47760 is not a child of this shell... torna al tavolo da disegno lol
Alexander Mills,

Ho una risposta, l'ho appena pubblicato grazie
Alexander Mills,

2
Ciò attenderà solo i processi figlio, non un processo non associato al processo corrente.
Kusalananda

1

Per quanto riguarda la soluzione https://stackoverflow.com/a/41613532/1223975 che Alexander Mills ha ripubblicato, Timeout in Seconds Darwinè una soluzione alternativa per un sistema operativo simile a UNIX che non ha GNU tail. Non è specifico Darwin, ma, a seconda dell'età del sistema operativo simile a UNIX, la riga di comando offerta è più complessa del necessario e può non riuscire:

lsof -p $pid +r 1m%s -t | grep -qm1 $(date -v+${timeout}S +%s 2>/dev/null || echo INF)

Su almeno un vecchio UNIX, l' lsofargomento +r 1m%snon riesce (anche per un superutente):

lsof: can't read kernel name list.

La m%sè una specifica formato di uscita. Un post-processore più semplice non lo richiede. Ad esempio, il comando seguente attende sul PID 5959 per un massimo di cinque secondi:

lsof -p 5959 +r 1 | awk '/^=/ { if (T++ >= 5) { exit 1 } }'

In questo esempio, se PID 5959 esce da solo prima che siano trascorsi i cinque secondi, lo ${?}è 0. Altrimenti ${?}ritorna 1dopo cinque secondi.

Potrebbe anche valere la pena notare che in +r 1, 1è l'intervallo di polling (in secondi), quindi può essere modificato in base alla situazione.

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.