Modo bash per verificare se un processo è già in esecuzione in background (e saltare la riesecuzione basata su quello)?


11

Posso creare una riga di comando bash che esegue un determinato comando solo se il processo non è già in esecuzione (in background)?

Come posso controllare *, se un comando è già in esecuzione?

(così posso aggiungere il prossimo comando &&tra di loro in modo che il successivo venga eseguito solo se il primo è vero).

*: prova, determina, scopri, scopri


3
ps -ef | grep -v grep | grep "process_name" || run_command_here
Rahul Patil,

1
@RahulPatil puoi usare solo pgrep "process_name"invece dips | grep | grep
precipita il

hmm, dimentico che ..: D
Rahul Patil,

1
Perché non usi un file "lock" e quando lo avvii la seconda volta, si avvierà solo quando il file lock scompare.
BitsOfNix

modo migliore per verificare l'esistenza di un processo: stackoverflow.com/questions/3043978/…
Trevor Boyd Smith

Risposte:



3

Ho usato questa tecnica di volta in volta:

$ pgrep <process name> || <process name>

Prima pgrepera usato in questo modo:

$ ps -eaf | grep -q <[p]rocess name> || <process name>

esempio

Il bit con il [p]rende in modo che il grepnon si troverà di conseguenza.

$ ps -eaf | grep -q [s]leep || sleep 10

2

Questo può essere difficile, perché puoi avere istanze separate dello stesso processo che vivono in modo indipendente. Ad esempio, server in ascolto su porte diverse o servizi in esecuzione come utenti diversi. Per distinguere tra queste istanze, è necessario assegnare a ciascuna di esse un tag univoco. Il tag è spesso un file, ma può essere un socket locale nello spazio dei nomi astratto, una porta TCP, ecc. - Qualsiasi identificatore univoco lo farà. Quando il tag è un file, può essere un normale file contenente un ID processo (un pidfile) o una pipe o socket con nome su cui il file è in ascolto, ecc. Idealmente, il tag è un endpoint di comunicazione che consente ai client di connettersi a quel processo.

Ognuno di questi diversi tipi di tag comporta un modo diverso di verificare se l'istanza che stai cercando è attiva e funzionante. Ad esempio, con un socket di file locale, provare a connettersi ad esso e avviare il processo se non esiste alcun processo in ascolto su quel socket. Se il tag è un file pid, controlla se esiste un processo con quell'ID processo, ma fai attenzione che sia fragile, poiché se il processo è morto, potrebbe esserci un processo non correlato che ha riutilizzato il suo ID. Attenzione che se due client tentano di raggiungere il processo in un breve lasso di tempo, entrambi potrebbero scoprire che il processo non esiste ed entrambi tentano di avviarlo; proteggere adeguatamente da questa condizione di gara può essere complicato.

È più semplice gestire le istanze quando sono tutte avviate dallo stesso processo di supervisione e quel processo di supervisione rileva quando le istanze muoiono e reagisce di conseguenza. Molti programmi di monitoraggio del servizio che possono farlo.

Se il programma non risponde su un endpoint di comunicazione noto e non è gestito da un programma di supervisione, il tag del povero è un pidfile: un file contenente l'ID del processo. Quando si avvia il processo, scrivere il pid in un file con un nome predefinito. Quando è necessario che il processo esista, leggere il file pid e vedere se esiste un processo con quel pid. Quando si termina il processo, cancellare il file pid. Il problema più saliente con un pidfile non supervisionato è che se il processo muore, il suo pid può essere riutilizzato da un processo non correlato. Dovresti almeno controllare il nome del processo o l'eseguibile del processo per assicurarti di parlare con il processo giusto. Molte varianti di unix hanno un comando pgrep :pgrep SOMENAME elenca i processi il cui nome contiene SOMENAME come sottostringa, con opzioni aggiuntive da limitare a un determinato utente, per richiedere una corrispondenza esatta, per cambiare quale delle diverse possibili nozioni di "nome processo" viene utilizzata, ecc.


1

È possibile utilizzare questo approccio:

if [[ -z $(ps -C appname -opid=) ]]; then
    appname && secondapp
fi

1

Altre opzioni:

  • pgrep -xq processname
    • Corrisponde solo ai primi 15 caratteri in GNU / Linux
    • Non include gli antenati su OS X
  • ps -eo comm= | sed 's|.*/||' | grep -xq processname
    • Corrisponde solo ai primi 15 caratteri in GNU / Linux
    • sed 's|.*/||' rimuove le parti di dirname su OS X

In GNU / Linux ps -o commtronca comando nomi di 15 caratteri ed pgrepe ps -Ccorrispondono solo i primi 15 caratteri.

ps -C (abbina i nomi dei comandi) non è supportato su OS X.

In OS X ps -o commstampa i percorsi assoluti dei comandi e ps -co commstampa solo i nomi dei comandi. In GNU ps -o commstampa solo i nomi dei comandi e -cha un significato diverso.

Pgrep di OS X non include i processi antenati (come bash, Terminal o launchd) senza -a. Pgrep di GNU li include di default e non supporta -a.

grep -xe pgrep -xnon implicare -F, quindi utilizzare -Fxse il nome del processo può contenere caratteri regex.


-C non è disponibile nemmeno nel mio cygwin :)
n611x007

1

Mi dispiace ma tutte queste soluzioni non supportano contab poiché la stessa riga di comando apparirà due volte nel risultato 'ps'.

Quindi ecco il mio:

## Test pour voir si le même script tourne déjà
## Un fichier .pid est utilisé pour stocké le numéro de process
## Si le pid est en train de tourner alors on sort.
lock_file=$0".pid"
[ -r $lock_file ] && read pid <$lock_file
if [ "$pid" -gt 1 ] && [ `ps --no-headers -p "$pid" | wc -l` -gt 0 ] ; then
    echo "WARNING : le process $pid tourne deja : $0"
    ps -edf | grep `basename $0` | grep -v grep
    echo "WARNING : Arrêt de cette instance ($$)."
    exit 7
fi
echo $$ >$lock_file

Di cosa ti dispiace? Che cos'è contab? Vuoi dire controllare all'interno di un cronlavoro?
Anthon,

0

Con Bash

#!/usr/bin/env bash

[[ $# -eq 0 ]] && { echo -e "Usage:\t\t $0 <Process_name>  <Command here>"; exit 1;  }

ifnotrun(){
        local p=$1
        if ! ps -C "$1" -opid=
        then
                cmd=($@)
                echo ${cmd[@]:1}
        else
                echo "Process \"$p\" Already Running.."
                exit 1
        fi

}

ifnotrun $*

Nota: - rimuovere echose l'output sembra OK.


0

Spiegherò il caso in cui esegui il comando in beckgreoud. I "$!" salva il PID dell'ultimo processo in background. Quindi, puoi usarlo per trovarlo nelle tabelle di processo seguendo le risposte sopra:

sleep 4 &
ps -ef | grep -w  $!  ...

Il comando incorporato "jobs" - prova questo:

sleep 4&
J=`jobs`
while [ "$J" ]; do
        sleep 1
        jobs # This line flush the jobs' bufer.
        J=`jobs`
done

Per quanto riguarda l'opzione "&&"

Invece di && usa il comando wait. Nel seguente esempio myproc2 non verrà eseguito fino al completamento di myproc1:

myproc1 &
wait
myproc2

0

Ottieni lo stato del tuo processo:

ps -lp $(pgrep <YOUR_PROCESS_NAME>) | tail -1 | awk '{print $11}'

Riferimento:

D    uninterruptible sleep (usually IO)
R    running or runnable (on run queue)
S    interruptible sleep (waiting for an event to complete)
T    stopped, either by a job control signal or because it is being traced
W    paging (not valid since the 2.6.xx kernel)
X    dead (should never be seen)
Z    defunct ("zombie") process, terminated but not reaped by its parent

Ad esempio, l'ho usato per giocare condizionalmente o mettere in pausa il mio processo Sox in una sessione di tmux:

/usr/local/bin/tmux if-shell -t sox "[ $(ps -lp $(pgrep sox) | tail -1 | awk '{print $11}') == 'T' ]" \
  'send -t sox "fg" Enter' \
  'send -t sox C-z'

-1

Puoi usarlo all'interno di uno script:

if [ `ps -ef | grep "script.sh" | grep -v grep | wc -l` -gt 1 ] ; then
echo "RUNNING...."
else
echo "NOT RUNNING..."
fi
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.