Odpowiedzi:
Aby sprawdzić istnienie procesu, użyj
kill -0 $pid
Ale tak jak powiedział @unwind, jeśli i tak chcesz go zabić, po prostu
kill $pid
lub będziesz mieć stan wyścigu.
Jeśli chcesz zignorować tekst kill
i zrobić coś na podstawie kodu wyjścia, możesz to zrobić
if ! kill $pid > /dev/null 2>&1; then
echo "Could not send SIGTERM to process $pid" >&2
fi
kill
jest nieco źle nazwany, ponieważ niekoniecznie zabija proces. Po prostu wysyła sygnał do procesu. kill $PID
jest równoważne z kill -15 $PID
wysyłaniem sygnału 15 SIGTERM do procesu, który jest instrukcją kończącą. Nie ma sygnału 0, jest to specjalna wartość informująca, kill
czy po prostu można wysłać sygnał do procesu, co w większości przypadków jest mniej więcej równoznaczne ze sprawdzeniem, czy istnieje. Zobacz linux.die.net/man/2/kill i linux.die.net/man/7/signal
kill -0
, w rzeczywistości muszę to zrobić: kill -0 25667 ; echo $?
- a następnie, jeśli otrzymam zwrot 0
, wówczas proces z tym PID może zostać zabity; a jeśli proces PID (powiedzmy) nie istnieje, $?
będzie 1
, co oznacza awarię. Czy to jest poprawne?
Najlepszym sposobem jest:
if ps -p $PID > /dev/null
then
echo "$PID is running"
# Do something knowing the pid exists, i.e. the process with $PID is running
fi
Problem z:
kill -0 $PID
oznacza, że kod wyjścia będzie różny od zera, nawet jeśli pid jest uruchomiony i nie masz uprawnień, aby go zabić. Na przykład:
kill -0 1
i
kill -0 $non-running-pid
mają nie dający się odróżnić (niezerowy) kod wyjścia dla zwykłego użytkownika, ale proces inicjowania (PID 1) na pewno działa.
Odpowiedzi omawiające zabójstwo i warunki wyścigu są dokładnie właściwe, jeśli testem jest „zabójstwo”. Przyszedłem szukać ogólnego „ jak testujesz istnienie PID w bash ”.
Metoda / proc jest interesująca, ale w pewnym sensie łamie ducha abstrakcji polecenia „ps”, tzn. Nie musisz szukać w / proc, ponieważ co, jeśli Linus zdecyduje się nazwać plik „exe” czymś innym?
-p
jest to niepotrzebne, przynajmniej w takim przypadku. ps $PID
ma dokładnie taki sam wynik.
if [ -n "$PID" -a -e /proc/$PID ]; then
echo "process exists"
fi
lub
if [ -n "$(ps -p $PID -o pid=)" ]
W tej ostatniej formie -o pid=
format wyjściowy wyświetla tylko kolumnę ID procesu bez nagłówka. Cudzysłowy są niezbędne, aby niepusty operator łańcuchowy -n
dawał poprawny wynik.
if ps -p"$PID" -o "pid=" >/dev/null 2>&1; then echo "Process is running..."; fi
ps
opcje i funkcje różnią się w zależności od platformy, więc wciąż nie jest w pełni przenośny.
$PID
jest pusty, to [ -e /proc/$PID ]
nadal zwróci true, ponieważ /proc/
katalog nadal istnieje.
Masz dwa sposoby:
Zacznijmy od szukania konkretnej aplikacji na moim laptopie:
[root@pinky:~]# ps fax | grep mozilla
3358 ? S 0:00 \_ /bin/sh /usr/lib/firefox-3.5/run-mozilla.sh /usr/lib/firefox-3.5/firefox
16198 pts/2 S+ 0:00 \_ grep mozilla
Wszystkie przykłady będą teraz szukać PID 3358.
Pierwszy sposób : uruchom „ps aux” i grep dla PID w drugiej kolumnie. W tym przykładzie szukam firefox, a następnie PID:
[root@pinky:~]# ps aux | awk '{print $2 }' | grep 3358
3358
Twój kod będzie więc:
if [ ps aux | awk '{print $2 }' | grep -q $PID 2> /dev/null ]; then
kill $PID
fi
Drugi sposób : poszukaj czegoś w /proc/$PID
katalogu. W tym przykładzie używam „exe”, ale możesz użyć wszystkiego innego.
[root@pinky:~]# ls -l /proc/3358/exe
lrwxrwxrwx. 1 elcuco elcuco 0 2010-06-15 12:33 /proc/3358/exe -> /bin/bash
Twój kod będzie więc:
if [ -f /proc/$PID/exe ]; then
kill $PID
fi
BTW: co jest nie tak kill -9 $PID || true
?
EDYTOWAĆ:
Po przemyśleniu tego przez kilka miesięcy .. (około 24 ...) oryginalny pomysł, który tu podałem, to niezły hack, ale wysoce niemożliwy do przeniesienia. Chociaż uczy kilku szczegółów implementacji systemu Linux, nie będzie działać na komputerach Mac, Solaris lub * BSD. Może nawet zawieść w przyszłych jądrach Linuksa. Proszę - użyj „ps” jak opisano w innych odpowiedziach.
/proc/$PID/exe
nie jest zwykłym plikiem. Tak więc [ -f /proc/$PID/exe ]
zawsze zwraca false
wynik. Spróbować [ -h /proc/$PID/exe ]
.
Wygląda na to, że chcesz
wait $PID
który wróci po $pid
zakończeniu.
W przeciwnym razie możesz użyć
ps -p $PID
aby sprawdzić, czy proces jest nadal aktywny (jest to bardziej skuteczne niż kill -0 $pid
ponieważ będzie działać, nawet jeśli nie jesteś właścicielem pid).
pid 123 is not a child of this shell
Myślę, że to złe rozwiązanie, które otwiera się na warunki wyścigowe. Co się stanie, jeśli proces umrze między testem a wezwaniem do zabicia? Wtedy zabicie się nie powiedzie. Dlaczego więc nie spróbować zabić we wszystkich przypadkach i sprawdzić jego wartość zwracaną, aby dowiedzieć się, jak poszło?
kill -9
. To natychmiast zabija proces, nie dając mu szansy na posprzątanie po sobie. Zamiast tego użyj kill
odpowiednika kill -15
. Jeśli to nie zadziała, powinieneś dowiedzieć się, dlaczego i tylko w ostateczności kill -9
.
tutaj przechowuję PID w pliku o nazwie .pid (który jest podobny do / run / ...) i wykonuję skrypt tylko wtedy, gdy jeszcze nie jest wykonywany.
#!/bin/bash
if [ -f .pid ]; then
read pid < .pid
echo $pid
ps -p $pid > /dev/null
r=$?
if [ $r -eq 0 ]; then
echo "$pid is currently running, not executing $0 twice, exiting now..."
exit 1
fi
fi
echo $$ > .pid
# do things here
rm .pid
Uwaga: istnieje warunek wyścigu, ponieważ nie sprawdza on, jak nazywany jest ten pid. jeśli system zostanie zrestartowany, a plik pid istnieje, ale jest używany przez inną aplikację, może to prowadzić do „nieprzewidzianych konsekwencji”.
Na przykład w GNU / Linux możesz użyć:
Pid=$(pidof `process_name`)
if [ $Pid > 0 ]; then
do something
else
do something
fi
Lub coś w tym rodzaju
Pin=$(ps -A | grep name | awk 'print $4}')
echo $PIN
i to pokazuje nazwę aplikacji, tylko nazwę bez identyfikatora.
pidof
nie zwraca liczby ujemnej, ponieważ ujemny PID nie ma sensu i nie możesz zabić init
, więc twoje warunkowe nie ma sensu (a poza tym musisz uciec przed, >
aby uniemożliwić przekierowanie). Chcesz sprawdzić pusty wynik, ale oczywiście, jak każde przyzwoite narzędzie, pidof
ustawia kod wyjścia informujący, czy zadziałał, więc właściwym rozwiązaniem jest if Pid=$(pidof 'process_name'); then ...
lub (jeśli Pid
później nie będziesz potrzebować tej wartości ) po prostuif pidof 'process_name'; then...
pidof
przykład jest pełen nieporozumień na temat tego, jak test
działa bash . gnu.org/software/bash/manual/html_node/…
poniższy kod sprawdza, czy mój proces jest uruchomiony, jeśli tak, nic nie rób.
sprawdzajmy nowe wiadomości z Amazon SQS co godzinę i tylko wtedy, gdy proces nie jest uruchomiony.
#!/bin/bash
PID=$(ps aux | grep '/usr/bin/python2.7 manage.py SES__boto3_sqs_read' | grep -v grep | awk '{print $2}')
if [[ -z $PID ]]; then
/usr/bin/python2.7 /home/brian/djcode/proyectoONE/manage.py SES__boto3_sqs_read
else
echo "do nothing, just smile =)"
fi
exit $?