È possibile utilizzare sh -c
e exec
per ottenere il PID del comando anche prima che venga eseguito.
Per iniziare myCommand
, in modo che il suo PID venga stampato prima che inizi l'esecuzione, è possibile utilizzare:
sh -c 'echo $$; exec myCommand'
Come funziona:
Questo avvia una nuova shell, stampa il PID di quella shell e quindi utilizza l' exec
integrato per sostituire la shell con il tuo comando, assicurandoti che abbia lo stesso PID. Quando la shell esegue un comando con il comando exec
incorporato, la shell in realtà sta diventando quel comando , piuttosto che il comportamento più comune di creare una nuova copia di se stesso, che ha il proprio PID separato e che quindi diventa il comando.
Trovo che questo sia molto più semplice rispetto alle alternative che coinvolgono l'esecuzione asincrona (con &
), il controllo del lavoro o la ricerca con ps
. Questi approcci vanno bene, ma a meno che tu non abbia un motivo specifico per usarli - per esempio, forse il comando è già in esecuzione, nel qual caso ha senso cercare il suo PID o usare il controllo del lavoro - suggerisco di considerare prima questo modo. (E certamente non prenderei in considerazione la possibilità di scrivere una sceneggiatura complessa o un altro programma per raggiungere questo obiettivo).
Questa risposta include un esempio di questa tecnica.
Alcune parti di quel comando potevano essere occasionalmente omesse, ma di solito non.
Anche se la shell che stai usando è in stile Bourne e quindi supporta il exec
builtin con queste semantiche, generalmente non dovresti cercare di evitare di usare sh -c
(o equivalente) per creare un nuovo processo di shell separato per questo scopo, perché:
- Una volta che la shell è diventata
myCommand
, non c'è nessuna shell in attesa di eseguire i comandi successivi. sh -c 'echo $$; exec myCommand; foo
non sarebbe in grado di tentare di eseguire foo
dopo aver sostituito se stesso con myCommand
. A meno che tu non stia scrivendo uno script che esegue questo come ultimo comando, non puoi semplicemente usarlo echo $$; exec myCommand
in una shell in cui stai eseguendo altri comandi.
- Non è possibile utilizzare una subshell per questo.
(echo $$; exec myCommand)
può essere sintatticamente più bello di sh -c 'echo $$; exec myCommand'
, ma quando si esegue $$
all'interno (
)
, fornisce il PID della shell genitore, non della sottoshell stessa. Ma è il PID della subshell che sarà il PID del nuovo comando. Alcune shell forniscono i propri meccanismi non portatili per trovare il PID della subshell, che è possibile utilizzare per questo. In particolare, in Bash 4 , (echo $BASHPID; exec myCommand)
funziona.
Infine, nota che alcune shell eseguiranno un'ottimizzazione in cui eseguono un comando come se exec
(per esempio, rinunciano prima a biforcarsi) quando è noto che la shell non dovrà fare nulla in seguito. Alcune shell provano a farlo ogni volta che è l'ultimo comando da eseguire, mentre altri lo faranno solo quando non ci sono altri comandi prima o dopo il comando, e altri non lo faranno affatto. L'effetto è che se ti dimentichi di scrivere exec
e utilizzarlo sh -c 'echo $$; myCommand'
, a volte ti darà il PID giusto su alcuni sistemi con alcune shell. Consiglio di non fare affidamento su tale comportamento e di includere sempre exec
quando è quello che ti serve.