Potrzebuję niezależnego od platformy polecenia powłoki / bash (Linux / Unix | OSX), które określi, czy jest uruchomiony określony proces. na przykład mysqld
, httpd
... Co to jest najprostszym sposobem / command to zrobić?
Potrzebuję niezależnego od platformy polecenia powłoki / bash (Linux / Unix | OSX), które określi, czy jest uruchomiony określony proces. na przykład mysqld
, httpd
... Co to jest najprostszym sposobem / command to zrobić?
Odpowiedzi:
Chociaż pidof
i pgrep
są świetnymi narzędziami do określania, co jest uruchomione, oba są niestety niedostępne w niektórych systemach operacyjnych. Zdecydowanym zabezpieczeniem przed awarią byłoby użycie następującego:ps cax | grep command
Dane wyjściowe w Gentoo Linux:
14484? S 0:00 apache2 14667? S 0:00 apache2 19620? Sl 0:00 apache2 21132? Ss 0:04 apache2
Wyjście na OS X:
42582 ?? Z 0: 00.00 (smbclient) 46529 ?? Z 0: 00.00 (smbclient) 46539 ?? Z 0: 00.00 (smbclient) 46547 ?? Z 0: 00.00 (smbclient) 46586 ?? Z 0: 00.00 (smbclient) 46594 ?? Z 0: 00.00 (smbclient)
Zarówno w systemie Linux, jak i OS X, grep zwraca kod zakończenia, więc łatwo jest sprawdzić, czy proces został znaleziony, czy nie:
#!/bin/bash
ps cax | grep httpd > /dev/null
if [ $? -eq 0 ]; then
echo "Process is running."
else
echo "Process is not running."
fi
Ponadto, jeśli chciałbyś zobaczyć listę PIDów, możesz łatwo grepować również dla nich:
ps cax | grep httpd | grep -o '^ [] * [0-9] *'
Czyje dane wyjściowe są takie same w systemie Linux i OS X:
3519 3521 3523 3524
Dane wyjściowe to pusty ciąg, dzięki czemu to podejście jest bezpieczne dla procesów, które nie są uruchomione:
Echo ps cax | grep aasdfasdf | grep -o '^[ ]*[0-9]*'
To podejście jest odpowiednie do napisania prostego testu pustego łańcucha, a następnie nawet iteracji przez odkryte PIDy.
#!/bin/bash
PROCESS=$1
PIDS=`ps cax | grep $PROCESS | grep -o '^[ ]*[0-9]*'`
if [ -z "$PIDS" ]; then
echo "Process not running." 1>&2
exit 1
else
for PID in $PIDS; do
echo $PID
done
fi
Możesz to przetestować zapisując go do pliku (o nazwie „działa”) z uprawnieniami do wykonywania (chmod + x działa) i uruchamiając go z parametrem: ./running "httpd"
#!/bin/bash
ps cax | grep httpd
if [ $? -eq 0 ]; then
echo "Process is running."
else
echo "Process is not running."
fi
OSTRZEŻENIE!!!
Należy pamiętać, że po prostu analizujesz dane wyjściowe, ps ax
co oznacza, że, jak widać na wyjściu Linuksa, nie jest ono po prostu dopasowywane do procesów, ale także do argumentów przekazanych do tego programu. Zdecydowanie zalecam bycie jak najbardziej szczegółowym podczas korzystania z tej metody (np. ./running "mysql"
Dopasuje również procesy 'mysqld'). Gorąco polecam korzystanie which
z pełnej ścieżki, jeśli to możliwe.
Bibliografia:
grep
będzie również znaleźć się pracuje (np ps cax | grep randomname
zawsze zwraca 0, ponieważ grep
znaleziska grep randomname
(nadzieję, że to jest jasne ...) Jedna poprawka jest dodanie nawiasów kwadratowych wokół pierwszej litery nazwy procesów, np. ps cax | grep [r]andomname
.
ps cax | rev | cut -f1 -d' ' | rev
pokaże tylko kolumnę z nazwą, aby ułatwić analizowanie.
ps cax
może nie wyświetlać całej nazwy polecenia. Np. Drukuje "przeglądarka chromu" zamiast "przeglądarka chromu".
Znalezienie procesu poprzez próbę rozpoznania wzorców w argumentach procesu (takich jak pgrep "mysqld"
) to strategia, która prędzej czy później jest skazana na niepowodzenie. A co jeśli masz dwa uruchomione mysqld? Zapomnij o takim podejściu. MOŻESZ to naprawić chwilowo i MOŻE działać przez rok lub dwa, ale potem dzieje się coś, o czym nie myślałeś.
Jedynie identyfikator procesu (pid) jest naprawdę wyjątkowy.
Zawsze przechowuj pid, gdy uruchamiasz coś w tle. W Bash można to zrobić za pomocą $!
zmiennej Bash. Oszczędzisz sobie w ten sposób TAKI kłopotów.
Teraz pojawia się pytanie, jak sprawdzić, czy pid jest uruchomiony.
Po prostu zrób:
ps -o pid = -p <pid>
To jest POSIX i stąd przenośne. Zwróci sam pid, jeśli proces jest uruchomiony, lub nic nie zwróci, jeśli proces nie jest uruchomiony. Ściśle mówiąc, polecenie zwróci pojedynczą kolumnę, the pid
, ale ponieważ podaliśmy pusty nagłówek tytułu (element bezpośrednio poprzedzający znak równości) i jest to jedyna żądana kolumna, polecenie ps w ogóle nie użyje nagłówka. Właśnie tego chcemy, ponieważ ułatwia to analizowanie.
To zadziała na Linuksie, BSD, Solarisie itp.
Inną strategią byłoby przetestowanie wartości wyjścia z powyższego ps
polecenia. Powinno wynosić zero, jeśli proces jest uruchomiony i niezerowe, jeśli nie. Specyfikacja POSIX mówi, że ps
musi zakończyć się> 0, jeśli wystąpił błąd, ale nie jest dla mnie jasne, co stanowi „błąd”. Dlatego osobiście nie używam tej strategii, chociaż jestem prawie pewien, że zadziała ona również na wszystkich platformach Unix / Linux.
grep <sometext>
aby znaleźć dany proces, to zrobiłeś coś złego, kiedy zacząłeś proces, IMHO. Wychodzę z pytania PO, że rzeczywiście ma kontrolę nad tym, jak rozpoczyna się ten proces.
W większości dystrybucji Linuksa możesz użyć pidof
(8).
Wyświetli identyfikatory procesów wszystkich uruchomionych instancji określonych procesów lub nic, jeśli nie ma uruchomionych instancji.
Na przykład w moim systemie (mam cztery wystąpienia bash
i jedną remmina
uruchomioną):
$ pidof bash remmina
6148 6147 6144 5603 21598
Na innych Unikach pgrep
lub połączenie ps
i grep
osiągnie to samo, jak słusznie wskazali inni.
pidof httpd
działa dobrze na Red Hat 5. Ale na moim Red Hat 4 pidof
nie jest obecny :-(
Powinno to działać na większości odmian Uniksa, BSD i Linuksa:
PATH=/usr/ucb:${PATH} ps aux | grep httpd | grep -v grep
Przetestowano na:
PATH=...
]ps
. Aby uniknąć drugiego grep
, proponuję:ps aux | grep [h]ttpd
grep
.
Najprostszym sposobem jest użycie ps i grep:
command="httpd"
running=`ps ax | grep -v grep | grep $command | wc -l`
if [ running -gt 0 ]; then
echo "Command is running"
else
echo "Command is not running"
fi
Jeśli twoje polecenie ma jakieś argumenty poleceń, możesz również wstawić więcej „grep cmd_arg1” po „grep $ command”, aby odfiltrować inne możliwe procesy, którymi nie jesteś zainteresowany.
Przykład: pokaż mi, czy jakikolwiek proces java z podanym argumentem:
-Djava.util.logging.config.file = logging.properties
biegnie
ps ax | grep -v grep | grep java | grep java.util.logging.config.file=logging.properties | wc -l
ps cax
eliminuje potrzebę używania grep -v
. Tak na przykład, można użyć: ps cax | grep java > /dev/null || echo "Java not running"
.
Tylko drobny dodatek: jeśli dodasz -c
flagę do ps, nie musisz później usuwać wiersza zawierającego proces grep grep -v
. To znaczy
ps acux | grep cron
to wszystko, czego potrzebujesz w systemie bsd-ish (w tym MacOSX). -u
Jeśli potrzebujesz mniej informacji, możesz zostawić go daleko.
W systemie, w którym genetyka natywnego ps
polecenia wskazuje na SysV, użyłbyś
ps -e |grep cron
lub
ps -el |grep cron
dla listy zawierającej więcej niż tylko pid i nazwę procesu. Oczywiście możesz wybrać określone pola do wydrukowania za pomocą -o <field,field,...>
opcji.
Łącząc różne sugestie, najczystsza wersja, jaką udało mi się wymyślić (bez niewiarygodnego grepa, który uruchamia części słów) to:
kill -0 $(pidof mysql) 2> /dev/null || echo "Mysql ain't runnin' message/actions"
kill -0 nie zabija procesu, ale sprawdza, czy istnieje, a następnie zwraca prawdę, jeśli nie masz pidof w systemie, zapisz pid podczas uruchamiania procesu:
$ mysql &
$ echo $! > pid_stored
następnie w skrypcie:
kill -0 $(cat pid_stored) 2> /dev/null || echo "Mysql ain't runnin' message/actions"
Używam, pgrep -l httpd
ale nie jestem pewien, czy jest obecny na dowolnej platformie ...
Kto może potwierdzić na OSX?
pidof
? OK, zrobiłeś. Dziękuję Ci. Powinniśmy więc znaleźć coś innego działającego na OSX ... Twoim podstawowym rozwiązaniem ps|grep
może być jedno rozwiązanie ;-)
Kiedy go uruchomisz, jego PID zostanie zapisany w $!
zmiennej. Zapisz ten PID do pliku.
Następnie musisz sprawdzić, czy ten PID odpowiada działającemu procesowi. Oto kompletny szkielet skryptu:
FILE="/tmp/myapp.pid"
if [ -f $FILE ];
then
PID=$(cat $FILE)
else
PID=1
fi
ps -o pid= -p $PID
if [ $? -eq 0 ]; then
echo "Process already running."
else
echo "Starting process."
run_my_app &
echo $! > $FILE
fi
W oparciu o odpowiedzi na peterh
. Sztuczka pozwalająca dowiedzieć się, czy dany PID działa, znajduje się w ps -o pid= -p $PID
instrukcji.
To podejście można zastosować w przypadku, gdy polecenia „ps”, „pidof” i rest nie są dostępne. Osobiście bardzo często używam procfs w moich narzędziach / skryptach / programach.
egrep -m1 "mysqld$|httpd$" /proc/[0-9]*/status | cut -d'/' -f3
Małe wyjaśnienie, co się dzieje:
Wypisuje liczbę procesów, których podstawową nazwą jest „chromium-browser”:
ps -e -o args= | awk 'BEGIN{c=0}{
if(!match($1,/^\[.*\]$/)){sub(".*/","",$1)} # Do not strip process names enclosed by square brackets.
if($1==cmd){c++}
}END{print c}' cmd="chromium-browser"
Jeśli wypisze "0", proces nie jest uruchomiony. Polecenie zakłada, że ścieżka procesu nie zawiera spacji. Nie testowałem tego z zawieszonymi procesami lub procesami zombie.
Przetestowano gwak
jako awk
alternatywę w systemie Linux.
Oto bardziej wszechstronne rozwiązanie z przykładowym zastosowaniem:
#!/bin/sh
isProcessRunning() {
if [ "${1-}" = "-q" ]; then
local quiet=1;
shift
else
local quiet=0;
fi
ps -e -o pid,args= | awk 'BEGIN{status=1}{
name=$2
if(name !~ /^\[.*\]$/){sub(".*/","",name)} # strip dirname, if process name is not enclosed by square brackets.
if(name==cmd){status=0; if(q){exit}else{print $0}}
}END{exit status}' cmd="$1" q=$quiet
}
process='chromium-browser'
printf "Process \"${process}\" is "
if isProcessRunning -q "$process"
then printf "running.\n"
else printf "not running.\n"; fi
printf "Listing of matching processes (PID and process name with command line arguments):\n"
isProcessRunning "$process"
Oto moja wersja. Cechy:
scenariusz:
#!/bin/bash
# $1 - cmd
# $2 - args
# return: 0 - no error, running; 1 - error, not running
function isRunning() {
for i in $(pidof $1); do
cat /proc/$i/cmdline | tr '\000' ' ' | grep -F -e "$2" 1>&2> /dev/null
if [ $? -eq 0 ]; then
return 0
fi
done
return 1
}
isRunning java "-Djava.util.logging.config.file=logging.properties"
if [ $? -ne 0 ]; then
echo "not running, starting..."
fi
Żadna z odpowiedzi nie zadziałała dla mnie, więc oto moja:
process="$(pidof YOURPROCESSHERE|tr -d '\n')"
if [[ -z "${process// }" ]]; then
echo "Process is not running."
else
echo "Process is running."
fi
Wyjaśnienie:
|tr -d '\n'
To usuwa znak powrotu karetki utworzony przez terminal. Resztę można wyjaśnić w tym poście.
Następująca funkcja powłoki, oparta tylko na standardowych poleceniach i opcjach POSIX, powinna działać w większości (jeśli nie na żadnym) systemach Unix i Linux. :
isPidRunning() {
cmd=`
PATH=\`getconf PATH\` export PATH
ps -e -o pid= -o comm= |
awk '$2 ~ "^.*/'"$1"'$" || $2 ~ "^'"$1"'$" {print $1,$2}'
`
[ -n "$cmd" ] &&
printf "%s is running\n%s\n\n" "$1" "$cmd" ||
printf "%s is not running\n\n" $1
[ -n "$cmd" ]
}
$ isPidRunning httpd
httpd is running
586 /usr/apache/bin/httpd
588 /usr/apache/bin/httpd
$ isPidRunning ksh
ksh is running
5230 ksh
$ isPidRunning bash
bash is not running
Zauważ, że dusi się po przekazaniu wątpliwej nazwy polecenia „0]”, a także nie będzie w stanie zidentyfikować procesów mających w nazwie spację.
Zauważ również, że najbardziej popularne i akceptowane rozwiązanie wymaga ps
opcji nieprzenośnych i nieodpłatnie korzysta z powłoki, która pomimo swojej popularności nie ma gwarancji, że będzie obecna na każdej maszynie z systemem Unix / Linux ( bash
)
$ isPidRunning 0]
wyświetla np. „0] działa 3 [ksoftirqd / 0] 8 [rcuop / 0] 17 [rcuos / 0] 26 [rcuob / 0] 34 [migracja / 0] 35 [watchdog / 0]”.