Come determinare se un processo è in esecuzione o meno e usarlo per creare uno script di shell condizionale?

90

Come posso determinare se un processo è in esecuzione o meno e poi fare in modo che uno script di bash esegua alcune cose in base a quella condizione?

Ad esempio:

  • se process abc è in esecuzione, fai questo

  • se non è in esecuzione, fallo.

posta Nirmik 29.06.2012 - 23:53

12 risposte

148

Uno script bash per fare qualcosa del genere sarebbe simile a questo:

#!/bin/bash

# Check if gedit is running
# -x flag only match processes whose name (or command line if -f is
# specified) exactly match the pattern. 

if pgrep -x "gedit" > /dev/null
then
    echo "Running"
else
    echo "Stopped"
fi

Questo script sta solo controllando se il programma "gedit" è in esecuzione.

Oppure puoi controllare solo se il programma non è in esecuzione in questo modo:

if ! pgrep -x "gedit" > /dev/null
then
    echo "Stopped"
fi
    
risposta data John Vrbanac 30.06.2012 - 00:08
33

Qualsiasi soluzione che utilizza qualcosa come ps aux | grep abc o pgrep abc è difettosa.

Perché?

Poiché non stai controllando se un processo specifico è in esecuzione, stai controllando se ci sono processi in esecuzione che corrispondono a abc . Qualsiasi utente può facilmente creare ed eseguire un eseguibile denominato abc (o che contiene abc da qualche parte nel suo nome o argomenti), causando un falso positivo per il test. Ci sono varie opzioni che puoi applicare a ps , grep e pgrep per restringere la ricerca, ma non otterrai un test affidabile.

Quindi, come posso testare in modo affidabile un determinato processo in esecuzione?

Dipende da cosa ti serve il test.

Voglio assicurarmi che il servizio abc sia in esecuzione e, in caso contrario, avviarlo

Questo è ciò a cui servono init e upstart. Avvieranno il servizio e assicureranno che il suo pid venga archiviato in un file pid. Prova ad avviare nuovamente il servizio (tramite init o upstart) e controllerà il file pid e lo avvierà se non è presente, oppure interromperà se è già in esecuzione. Questo non è ancora affidabile al 100%, ma è il più vicino possibile.

Vedi Come posso verificare se il mio server di gioco è ancora in esecuzione ... per altre soluzioni.

abc è il mio script. Devo assicurarmi che sia in esecuzione una sola istanza del mio script.

In questo caso, usa un lockfir o un lockdir. Per es.

#!/usr/bin/env bash

if ! mkdir /tmp/abc.lock; then
    printf "Failed to acquire lock.\n" >&2
    exit 1
fi
trap 'rm -rf /tmp/abc.lock' EXIT  # remove the lockdir on exit

# rest of script ...

Vedi Domande frequenti Bash 45 per altri modi di bloccare.

    
risposta data geirha 30.06.2012 - 09:29
17

Questo è quello che uso:

#!/bin/bash

#check if abc is running
if pgrep abc >/dev/null 2>&1
  then
     # abc is running
  else
     # abc is not running
fi

In parole semplici: se 'pgrep' restituisce 0, il processo è in esecuzione, altrimenti non lo è.

Lettura correlata:

Bash Scripting :: Confronto tra stringhe

Manuali di Ubuntu pgrep

    
risposta data Zuul 30.06.2012 - 00:15
5

Di solito ho un pidof -x $(basename $0) sui miei script per verificare se è già in esecuzione.

    
risposta data Rommel Cid 14.01.2014 - 10:42
1

Riffing sull'idea di @ rommel-cid, puoi usare pidof con || (||) per eseguire un comando se il processo non esiste e & amp; & amp; per eseguire qualcosa se il processo esiste, creando quindi un condizionale if / then / else. Ad esempio, ecco uno con un processo in esecuzione (il mio browser Chrome, il cui nome processo è "chrome") e un test per un processo che non esiste. Ho soppresso lo standard output usando 1 & gt; / dev / null in modo che non stampi:

$ (pidof chrome 1>/dev/null && echo "its running? ok, so am i then" ) || echo "it's not running? ok i'll run instea\
d"
its running? ok, so am i then
$ (pidof nosuchprocess 1>/dev/null && echo "its running? ok, so am i then" ) || echo "it's not running? ok i'll run\
 instead"
it's not running? ok i'll run instead
$
    
risposta data yuvilio 02.03.2014 - 00:08
0

La prima cosa che mi è venuta in mente per il tuo problema:
ps aux | grep -i abc mostrerà i dettagli del processo se è in esecuzione. È possibile abbinare il numero di linee o il tempo per cui è in esecuzione e confrontare con zero o qualsiasi altra manipolazione. Quando esegui il comando precedente, mostrerai almeno una riga di output, ad esempio i dettagli sul processo creato dal comando thi grep. Quindi prenditi cura di questo.
Questo dovrebbe essere un semplice trucco. Inseriscilo nello script di bash e verifica se è utile.

    
risposta data drake01 30.06.2012 - 00:03
0

Uso di start-stop-daemon :

/sbin/start-stop-daemon --background --make-pidfile --pidfile /tmp/foo.pid -S --startas /usr/bin/program -- arg1 arg2

Funziona come un utente normale.

    
risposta data Martin Monperrus 19.06.2015 - 19:55
0

Ho scoperto che la risposta accettata pubblicata da @John Vrbanac non ha funzionato per me e che la risposta inviata da @geirha non risponde alla domanda originale.

La soluzione di John Vrbanac non funzionava per verificare se un processo PHP era in esecuzione o meno per me, sto utilizzando CentOS 7.

@ la risposta di geirha fa in modo che un'istanza non sia già in esecuzione prima di iniziarne un'altra. Questa non era la domanda originale, la domanda iniziale era di verificare se un processo è in esecuzione o meno.

Ecco cosa ha funzionato per me:

Supponiamo che il mio processo abbia la stringa "Jane" nel suo nome di processo. Questo troverà se è in esecuzione o no. Questo funziona per gli script BASH e PHP.

ps -aux | grep "[J]ane" > /dev/null 2>&1
if [[ "$?" == "0" ]]; then
    echo "It's running"
else
    echo "It's not running"
fi
    
risposta data Wayne Workman 11.11.2016 - 20:12
0
## bash

## function to check if a process is alive and running:

_isRunning() {
    ps -o comm= -C "$1" 2>/dev/null | grep -x "$1" >/dev/null 2>&1
}

## example 1: checking if "gedit" is running

if _isRunning gedit; then
    echo "gedit is running"
else
    echo "gedit is not running"
fi

## example 2: start lxpanel if it is not there

if ! _isRunning lxpanel; then
    lxpanel &
fi

## or

_isRunning lxpanel || (lxpanel &)

Nota : pgrep -x lxpanel o pidof lxpanel riporta ancora che lxpanel è in esecuzione anche quando è defunct (zombie); quindi, per ottenere un processo in corso, dobbiamo utilizzare ps e grep

    
risposta data Bach Lien 23.12.2017 - 19:01
-1

A partire dal 23 settembre 2016, pgrep sembra richiedere l'opzione "-x" perché lo script di muru funzioni.

#!/bin/bash

if pgrep -x "conky" > /dev/null 2>&1
then
  echo "conky running already"
else
  echo "now starting conky"
  conky
fi
exit 0

Ho provato e testato lo script sopra su una macchina Ubuntu 16.04.1. Buon divertimento!

    
risposta data dzmanto 23.09.2016 - 20:39
-1
#!/bin/bash
while [ true ]; do     # Endless loop.
  pid='pgrep -x ${1}'  # Get a pid.
  if [ -z $pid ]; then # If there is none,
    ${1} &             # Start Param to background.
  else
    sleep 60           # Else wait.
  fi
done
    
risposta data user7449824 28.01.2017 - 19:36
-3

isProcessRunning () {if [$ (pidof $ 1) & gt; / dev / null]; quindi retval = 'true'; else retval = 'false'; fi; echo $ retval; }

isProcessRunning geany

true

    
risposta data Dominic 19.01.2016 - 20:37

Leggi altre domande sui tag