GNU/Linux >> Linux Esercitazione >  >> Linux

Come ottenere il pid del processo appena avviato

Soluzione 1:

Cosa può esserci di più semplice di echo $! ? Come una riga:

myCommand & echo $!

Soluzione 2:

Puoi usare sh -c e exec per ottenere il PID del comando anche prima funziona.

Per avviare myCommand , in modo che il suo PID venga stampato prima che inizi l'esecuzione, puoi usare:

sh -c 'echo $$; exec myCommand'

Come funziona:

Questo avvia una nuova shell, stampa il PID di quella shell e poi usa exec incorporato per sostituire la shell con il tuo comando, assicurandoti che abbia lo stesso PID. Quando la tua shell esegue un comando con exec builtin, la tua shell sta effettivamente diventando quel comando, piuttosto che il comportamento più comune di biforcare 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 delle alternative che coinvolgono l'esecuzione asincrona (con & ), controllo del lavoro o ricerca con ps . Questi approcci vanno bene, ma a meno che tu non abbia un motivo specifico per usarli, ad esempio forse il comando è già in esecuzione, nel qual caso avrebbe 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 uno script complesso o un altro programma per raggiungere questo obiettivo).

Questa risposta include un esempio di questa tecnica.

Parti di quel comando potrebbero occasionalmente essere omesse, ma non di solito.

Anche se la shell che stai usando è in stile Bourne e quindi supporta exec integrato con queste semantiche, generalmente non dovresti evitare di usare sh -c (o equivalente) per creare un nuovo separato processo di shell 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 lo esegua come ultimo comando, non puoi semplicemente usare echo $$; exec myCommand in una shell dove stai eseguendo altri comandi.
  • Non puoi usare una subshell per questo. (echo $$; exec myCommand) potrebbe essere sintatticamente migliore di sh -c 'echo $$; exec myCommand' , ma quando esegui $$ all'interno di ( ) , fornisce il PID della shell madre, non della subshell 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, cosa che potresti 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 da exec (cioè, rinunciano prima al fork) quando è noto che il guscio non avrà bisogno di fare nulla in seguito. Alcune shell provano a farlo ogni volta che è l'ultimo comando da eseguire, mentre altre lo faranno solo quando non ci sono altri comandi prima o dopo il comando, e altre non lo faranno affatto. L'effetto è che se dimentichi di scrivere exec e usa solo sh -c 'echo $$; myCommand' poi a volte darti il ​​PID corretto su alcuni sistemi con alcuni conchiglie. Raccomando di non fare mai affidamento su tale comportamento e di includere sempre exec quando è ciò di cui hai bisogno.

Soluzione 3:

Racchiudi il comando in un piccolo script

#!/bin/bash
yourcommand &
echo $! >/path/to/pid.file

Soluzione 4:

Non conosco alcuna soluzione più semplice, ma non sta usando $! abbastanza buono? Puoi sempre assegnare il valore a qualche altra variabile se ne hai bisogno in seguito, come detto da altri.

Come nota a margine, invece di eseguire il piping da ps potresti usare pgrep o pidof .

Soluzione 5:

usa exec da uno script bash dopo aver registrato il pid in un file:

esempio:

supponi di avere uno script chiamato "forever.sh" che vuoi eseguire con gli argomenti p1,p2,p3

codice sorgente forever.sh:

#!/bin/sh

while [ 1 -lt 2 ] ; do
    logger "$0 running with parameters \"[email protected]\""
    sleep 5
done

crea un mietitore.sh:

#!/bin/sh

echo $$ > /var/run/$1.pid
exec "[email protected]"

esegui forever.sh attraverso reaper.sh:

./reaper.sh ./forever.sh p1 p2 p3 p4 &

forever.sh non fa altro che registrare una riga su syslog ogni 5 secondi

ora hai il pid in /var/run/forever.sh.pid

cat /var/run/forever.sh.pid 
5780

e forever.sh funziona correttamente. syslog grep:

Nov 24 16:07:17 pinkpony cia: ./forever.sh running with parameters "p1 p2 p3 p4"

puoi vederlo nella tabella dei processi:

ps axuwww|grep 'forever.sh p1' |grep -v grep
root      5780  0.0  0.0   4148   624 pts/7    S    16:07   0:00 /bin/sh ./forever.sh p1 p2 p3 p4

Linux
  1. Ottieni in modo programmatico il pid genitore di un altro processo?

  2. Come ottenere l'ID del processo per terminare un processo nohup?

  3. Come ottenere il PID dal processo figlio biforcuto nello script della shell

  4. Come ottenere il PID in base al nome del processo?

  5. Come ottenere il pid di un processo e invocare kill -9 su di esso nello script della shell?

Come identificare un processo che non ha Pid?

Lxc e come iniziare?

Come trovare il nome del processo dal suo PID

Come iniziare con Arch Linux

Come iniziare con Midnight Commander nel 2022

Come ottenere il PID padre di un determinato processo in GNU/Linux dalla riga di comando?