Come verificare se un’altra istanza del mio script di shell è in esecuzione

GNU bash, versione 1.14.7 (1)

Ho uno script si chiama ” abc.sh ” Devo controllare questo da script abc.sh solo … al suo interno ho scritto la seguente dichiarazione

 status=`ps -efww | grep -w "abc.sh" | grep -v grep | grep -v $$ | awk '{ print $2 }'` if [ ! -z "$status" ]; then echo "[`date`] : abc.sh : Process is already running" exit 1; fi 

So che è sbagliato perché ogni volta che esce ha trovato il proprio processo in “ps” come risolverlo? come posso verificare che lo script sia già in esecuzione o meno from that script ?

Un modo più semplice per verificare la presenza di un processo già in esecuzione è il comando pidof .

 if pidof -x "abc.sh" >/dev/null; then echo "Process already running" fi 

In alternativa, fare in modo che lo script crei un file PID quando viene eseguito. È quindi un semplice esercizio di verifica della presenza del file PID per determinare se il processo è già in esecuzione.

 #!/bin/bash # abc.sh mypidfile=/var/run/abc.sh.pid # Could add check for existence of mypidfile here if interlock is # needed in the shell script itself. # Ensure PID file is removed on program exit. trap "rm -f -- '$mypidfile'" EXIT # Create a file with current PID to indicate that process is running. echo $$ > "$mypidfile" ... 

Aggiornamento: la domanda è ora cambiata per controllare dallo script stesso. In questo caso, ci aspetteremmo di vedere sempre almeno un abc.sh esecuzione. Se c’è più di un abc.sh , allora sappiamo che il processo è ancora in esecuzione. Suggerirei comunque l’uso del comando pidof che restituirebbe 2 PID se il processo era già in esecuzione. È ansible utilizzare grep per filtrare il PID corrente, eseguire il ciclo nella shell o persino ripristinare il conteggio dei PID con wc per rilevare più processi.

Ecco un esempio:

 #!/bin/bash for pid in $(pidof -x abc.sh); do if [ $pid != $$ ]; then echo "[$(date)] : abc.sh : Process is already running with PID $pid" exit 1 fi done 

Io voglio il metodo “pidof”, ecco il trucco:

  if pidof -o %PPID -x "abc.sh">/dev/null; then echo "Process already running" fi 

Dove il parametro -o %PPID dice di omettere il pid della shell chiamante o dello shell. Maggiori informazioni nella pagina man pidof .

Ecco un trucco che vedrai in vari luoghi:

 status=`ps -efww | grep -w "[a]bc.sh" | awk -vpid=$$ '$2 != pid { print $2 }'` if [ ! -z "$status" ]; then echo "[`date`] : abc.sh : Process is already running" exit 1; fi 

Le parentesi attorno a [a] (o scegli una lettera diversa) impediscono a grep di trovarsi. Ciò rende superfluo il grep -v grep bit. Ho anche rimosso grep -v $$ e risolto la parte di awk per ottenere la stessa cosa.

Qualcuno, per favore, abbattimi se sbaglio qui

Comprendo che l’operazione mkdir è atomica, quindi è ansible creare una directory di blocco

 #!/bin/sh lockdir=/tmp/AXgqg0lsoeykp9L9NZjIuaqvu7ANILL4foeqzpJcTs3YkwtiJ0 mkdir $lockdir || { echo "lock directory exists. exiting" exit 1 } # take pains to remove lock directory when script terminates trap "rmdir $lockdir" EXIT INT KILL TERM # rest of script here 

Usa il comando PS in un modo leggermente diverso per ignorare anche il processo figlio:

 ps -eaf | grep -v grep | grep $PROCESS | grep -v $$ 

Creo un file temporaneo durante l’esecuzione.

Ecco come lo faccio:

 #!/bin/sh # check if lock file exists if [ -e /tmp/script.lock ]; then echo "script is already running" else # create a lock file touch /tmp/script.lock echo "run script..." #remove lock file rm /tmp/script.lock fi 

Ecco come lo faccio in uno script bash:

 if ps ax | grep $0 | grep -v $$ | grep bash | grep -v grep then echo "The script is already running." exit 1 fi 

Questo mi permette di usare questo snippet per qualsiasi script bash. Avevo bisogno di grep bash perché quando si usa con cron, crea un altro processo che lo esegue usando / bin / sh.

Ho scoperto che usando i backtick per catturare l’output del comando in una variabile, adversamente, si ottengono troppi risultati aux , ad esempio per una singola istanza in esecuzione di abc.sh :

 ps aux | grep -w "abc.sh" | grep -v grep | wc -l 

restituisce “1”. Però,

 count=`ps aux | grep -w "abc.sh" | grep -v grep | wc -l` echo $count 

restituisce “2”

Sembra che l’utilizzo della costruzione del backtick crei temporaneamente un altro processo. Potrebbe essere la ragione per cui l’topicstarter non ha potuto farlo funzionare. Ho solo bisogno di decrementare il valore $ var.

pidof non funzionava per me, quindi ho cercato un po ‘di più e mi sono imbattuto in pgrep

 for pid in $(pgrep -f my_script.sh); do if [ $pid != $$ ]; then echo "[$(date)] : my_script.sh : Process is already running with PID $pid" exit 1 else echo "Running with PID $pid" fi done 

Preso in parte dalle risposte sopra e https://askubuntu.com/a/803106/802276

Non volevo hardcode abc.sh nel controllo, così ho usato il seguente:

 MY_SCRIPT_NAME=`basename "$0"` if pidof -o %PPID -x $MY_SCRIPT_NAME > /dev/null; then echo "$MY_SCRIPT_NAME already running; exiting" exit 1 fi 

Trovo che la risposta di @Austin Phillips sia giusta. Un piccolo miglioramento che vorrei fare è aggiungere -o (per ignorare il pid dello script stesso) e abbinare lo script con basename (cioè lo stesso codice può essere inserito in qualsiasi script):

 if pidof -x "`basename $0`" -o $$ >/dev/null; then echo "Process already running" fi