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


108

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

Per esempio:

  • se il processo abcè in esecuzione, farlo

  • se non è in esecuzione, farlo.


1
Sento importante notare che nessuna delle soluzioni seguenti tiene conto dello stato del processo. Un commento su una delle mie domande mi ha portato qui, ma una risposta su di esso mi ha indicato in diversi stati di un programma, come il zombieprocesso '(Non quello che descriverei come un processo "in esecuzione"). Un elenco completo di ciò che i STATvalori di colonna, nell'output di ps, indica è qui per coloro che sono inclini a scrivere una risposta che lo accolga o a modificare la propria.
user66001,


esiste il modo migliore per verificare il processo: stackoverflow.com/questions/3043978/…
Trevor Boyd Smith

Risposte:


166

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 verificando se il programma "gedit" è in esecuzione.

Oppure puoi solo verificare se il programma non funziona in questo modo:

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

@DreadPirateShawn puoi dirmi perché usare / dev / null e non semplicemente uno 0? L'uso del numero rende il codice molto più leggibile, almeno per un noob (come me). Nessun reindirizzamento, niente di niente
Silviu,

2
@Silviu eh? Googling /dev/null: "/ dev / null reindirizza l'output standard del comando sul dispositivo null, che è un dispositivo speciale che scarta le informazioni scritte su di esso" ... usando 0reindirizzerebbe l'output del comando su un file chiamato 0. In questo caso, consiglierei di sentirti più a tuo agio > /dev/null: lo vedrai ovunque, poiché è il modo standard / corretto di scartare l'output.
DreadPirateShawn del

Grazie, l'ho usato per un piccolo script che controlla se un programma è in esecuzione prima che venga eseguito. (Anche se ho dovuto estenderlo un po 'poiché l'eseguibile di Google Chrome non ha lo stesso nome del comando run, il nome exec è solo Chrome.)
Cestarian

3
Aggiungi il -xparametro in pgrepmodo che stia cercando l'applicazione esatta, altrimenti otterrà un falso corretto se trova la stessa stringa all'interno del nome di un'altra app. Ho appena trascorso 1 ora per scoprirlo.
Thanos Apostolou,

1
Per verificare se il programma non è in esecuzione, utilizzare! pgrep
Mohammed Noureldin,

36

Qualsiasi soluzione che utilizza qualcosa di simile ps aux | grep abco pgrep abcdifettosa.

Perché?

Poiché non si sta verificando se un processo specifico è in esecuzione, si sta verificando se esistono processi in esecuzione che corrispondono abc. Qualsiasi utente può facilmente creare ed eseguire un eseguibile chiamato abc(o che contiene abcda qualche parte nel suo nome o argomenti), causando un falso positivo per il test. Ci sono varie opzioni che si possono applicare a ps, grepe pgrepper restringere la ricerca, ma ancora non sarà possibile ottenere un test affidabile.

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

Dipende da cosa è necessario il test.

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

Ecco a cosa servono init e upstart. Inizieranno il servizio e si assicureranno che il suo pid venga archiviato in un pidfile. Prova a riavviare il servizio (tramite init o upstart) e controllerà il file pid, o lo avvierà se non è lì, o 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 è la mia sceneggiatura. Devo assicurarmi che sia in esecuzione solo un'istanza del mio script.

In questo caso, utilizzare un file di blocco o un lockdir. Per esempio

#!/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 FAQ Bash 45 per altri modi di blocco.


3
Anche se questo è tecnicamente vero, non ho mai riscontrato un simile problema nella vita reale. La maggior parte dei programmi non cambia il proprio nome in modo da spezzare gli script. Pertanto, per semplici script qualcosa di simile pgrepo psè perfettamente adeguato e il tuo approccio sembra eccessivo. Se stai scrivendo uno script per la distribuzione pubblica, tuttavia, dovresti scriverlo nel modo più sicuro possibile.
Scott Severance,

2
I programmi @ScottSeverance che cambiano nome non sono il problema; ciò richiederebbe l'intervento a prescindere. Sono altri utenti che eseguono lo stesso programma o altri programmi con nomi simili che improvvisamente causeranno falsi positivi allo script e quindi fare la cosa sbagliata. Preferisco solo "opere" piuttosto che "per lo più opere".
geirha,

2
Ho sbagliato. Ma molti di noi utilizzano sistemi a utente singolo. E in una situazione con più utenti, è facile richiedere anche il nome utente.
Scott Severance,

1
cosa succede se il tuo script fallisce durante il runtime e muore prima di sbloccare il file?
jp093121,

2
@ jp093121 Il trap EXIT viene attivato alla chiusura dello script. Se esce perché raggiunge la fine dello script, un comando di uscita o riceve un segnale (che può essere gestito), il rmcomando viene eseguito. Quindi, fintanto che termina dopo che è stata impostata la trappola, il blocco dovrebbe essere disattivato.
geirha,

18

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 povere : se 'pgrep' restituisce 0, il processo è in esecuzione, altrimenti non lo è.


Lettura correlata:

Bash Scripting :: Confronti di stringhe

Ubuntu Manuals pgrep


Grazie! ho provato anche questo n funziona perfettamente anche :)
Nirmik,

pgrepha lo stesso limite di 15 caratteri "caratteristica" precedentemente menzionato, quindi per esempio pgrep gnome-power-managerfallirebbe
Thorsen,

1
Assicurati di usare l' -xopzione di pgrep : " Abbina solo i processi il cui nome (o riga di comando se -f è specificato) corrisponde esattamente al modello."
Alastair Irvine,

5

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


2

Riffing sull'idea di @ rommel-cid, puoi usarlo pidofcon il || (||) per eseguire un comando se il processo non esiste e && per eseguire qualcosa se il processo esiste, creando così un condizionale rapido if / then / else. Ad esempio, eccone uno con un processo in esecuzione (il mio browser Chrome, il cui nome del processo è "chrome") e un test per un processo che non esiste. Ho soppresso l'output standard usando 1> / dev / null in modo che non venga stampato:

$ (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
$

1

Nessuna delle soluzioni "semplici" ha funzionato per me perché il binario che devo controllare non è installato a livello di sistema, quindi devo controllare con il percorso, che a sua volta richiede l'uso ps -ef | grepdell'approccio:

app="$_sdir/Logic 1.2.18 (64-bit)/Logic"

app_pid=`ps -ef | grep "$app" | awk '{print $2}'`

if `ps -p $app_pid > /dev/null`; then
    echo "An instance of logic analyzer is appear to be running."
    echo "Not starting another instance."
    exit 5
else
    nohup "$app" &> /dev/null &
fi

0

La prima cosa che mi è venuta in mente per il tuo problema:
ps aux | grep -i abcmostrerà i dettagli del processo se è in esecuzione. È possibile abbinare il numero di righe o il tempo per cui è in esecuzione e confrontare con zero o qualsiasi altra manipolazione. Quando esegui il comando sopra ti mostrerà almeno una riga di output, ovvero i dettagli sul processo creato dal comando grep .. Quindi prenditi cura di quello.
Questo dovrebbe fare come un semplice trucco. Inseriscilo nello script bash e vedi se è utile.


0

Utilizzando start-stop-daemon:

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

Funziona come un normale utente.


0

Ho scoperto che la risposta accettata inviata 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 ha funzionato per verificare se un processo PHP era in esecuzione o meno per me, sto eseguendo CentOS 7.

La risposta di @ geirha si assicura solo che un'istanza non sia già in esecuzione prima di avviarne un'altra. Questa non era la domanda originale, la domanda originale era verificare se un processo è in esecuzione o meno.

Ecco cosa ha funzionato per me:

Supponiamo che il mio processo abbia la stringa "Jane" nel nome del processo. Questo troverà se è in esecuzione o meno. Funziona con 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

1
Ah, anche se questo è un sito di domande e risposte di Ubuntu non è sorprendente che alcune delle risposte qui non funzionino su CentOS 7 poiché Linux è fuori tema qui. Altre versioni di Linux sono supportate su unix.stackexchange.com
Elder Geek

sebbene l'autore della risposta usi CentOS, questa risposta è ancora valida per Ubuntu.
Phillip -Zyan K Lee- Stockmann,

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 lxpanelo pidof lxpanelsegnala comunque che lxpanelè in esecuzione anche quando è defunto (zombi); quindi per ottenere un processo attivo, dobbiamo usare psegrep


-1

A partire dal 23 settembre 2016, pgrep sembra richiedere un'opzione "-x" affinché la sceneggiatura 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. Godere!


-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

1
Benvenuti in Ask Ubuntu! Raccomando di modificare questa risposta per espanderla con dettagli specifici su ciò che fa. (Vedi anche Come posso scrivere una buona risposta? Per consigli generali su quali tipi di risposte sono considerate più preziose su AskUbuntu.)
David Foerster,

-3

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

isProcessRunning geany

vero

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.