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ż pidofi pgrepsą ś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 axco 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 whichz pełnej ścieżki, jeśli to możliwe.
Bibliografia:
grepbędzie również znaleźć się pracuje (np ps cax | grep randomnamezawsze zwraca 0, ponieważ grepznaleziska 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' ' | revpokaże tylko kolumnę z nazwą, aby ułatwić analizowanie.
ps caxmoż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 pspolecenia. Powinno wynosić zero, jeśli proces jest uruchomiony i niezerowe, jeśli nie. Specyfikacja POSIX mówi, że psmusi 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 bashi jedną remminauruchomioną):
$ pidof bash remmina
6148 6147 6144 5603 21598
Na innych Unikach pgreplub połączenie psi greposiągnie to samo, jak słusznie wskazali inni.
pidof httpddziała dobrze na Red Hat 5. Ale na moim Red Hat 4 pidofnie 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 caxeliminuje 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 -cflagę 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). -uJeśli potrzebujesz mniej informacji, możesz zostawić go daleko.
W systemie, w którym genetyka natywnego pspolecenia 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 httpdale 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|grepmoż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 $PIDinstrukcji.
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 gwakjako awkalternatywę 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 psopcji 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]”.