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 killi 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
killjest nieco źle nazwany, ponieważ niekoniecznie zabija proces. Po prostu wysyła sygnał do procesu. kill $PIDjest równoważne z kill -15 $PIDwysył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, killczy 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?
-pjest to niepotrzebne, przynajmniej w takim przypadku. ps $PIDma 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 -ndawał poprawny wynik.
if ps -p"$PID" -o "pid=" >/dev/null 2>&1; then echo "Process is running..."; fi
psopcje i funkcje różnią się w zależności od platformy, więc wciąż nie jest w pełni przenośny.
$PIDjest 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/$PIDkatalogu. 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/exenie jest zwykłym plikiem. Tak więc [ -f /proc/$PID/exe ]zawsze zwraca falsewynik. Spróbować [ -h /proc/$PID/exe ].
Wygląda na to, że chcesz
wait $PID
który wróci po $pidzakoń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 $pidponieważ 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 killodpowiednika 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.
pidofnie 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, pidofustawia 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 Pidpóźniej nie będziesz potrzebować tej wartości ) po prostuif pidof 'process_name'; then...
pidofprzykład jest pełen nieporozumień na temat tego, jak testdział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 $?