Ответы:
Чтобы проверить наличие процесса, используйте
kill -0 $pid
Но, как сказал @unwind, если вы все равно собираетесь его убить, просто
kill $pid
или у вас будет состояние гонки.
Если вы хотите игнорировать вывод текста kill
и делать что-то на основе кода выхода, вы можете
if ! kill $pid > /dev/null 2>&1; then
echo "Could not send SIGTERM to process $pid" >&2
fi
kill
несколько неверно назван тем, что он не обязательно убивает процесс. Он просто отправляет процессу сигнал. kill $PID
эквивалентно тому kill -15 $PID
, что посылает сигнал 15, SIGTERM процессу, который является инструкцией для завершения. Сигнала 0 нет, это специальное значение, kill
указывающее просто проверить, может ли сигнал быть отправлен процессу, что для большинства целей более или менее эквивалентно проверке, существует ли он. См. Linux.die.net/man/2/kill и linux.die.net/man/7/signal
kill -0
, я, фактически, должен сделать это: kill -0 25667 ; echo $?
- и тогда, если я получу 0
возвращенный, тогда процесс с этим PID может быть остановлен; и если PID процесса (скажем) не существует, $?
будет 1
указывать сбой. Это правильно?
Лучший способ это:
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
Проблема с:
kill -0 $PID
код выхода будет ненулевым, даже если pid запущен и у вас нет разрешения на его уничтожение. Например:
kill -0 1
и
kill -0 $non-running-pid
иметь обычный неотличимый (ненулевой) код завершения для обычного пользователя, но процесс init (PID 1), безусловно, выполняется.
Ответы, обсуждающие условия убийства и расы, являются абсолютно правильными, если тело теста является «убийством». Я пришел в поисках общего " как вы проверяете наличие PID в Bash ".
Метод / proc интересен, но в некотором смысле нарушает дух абстракции команды «ps», т. Е. Вам не нужно искать в / proc, что, если Линус решит назвать файл «exe» чем-то другим?
-p
этом нет необходимости, по крайней мере, в этом случае. ps $PID
имеет точно такой же результат.
if [ -n "$PID" -a -e /proc/$PID ]; then
echo "process exists"
fi
или
if [ -n "$(ps -p $PID -o pid=)" ]
В последней форме -o pid=
- выходной формат для отображения только столбца идентификатора процесса без заголовка. Кавычки необходимы для оператора непустой строки, -n
чтобы дать правильный результат.
if ps -p"$PID" -o "pid=" >/dev/null 2>&1; then echo "Process is running..."; fi
ps
параметры и функции, как правило, различаются для разных платформ, поэтому они все еще не полностью переносимы.
$PID
пуст, то [ -e /proc/$PID ]
все равно вернет истину, так как /proc/
каталог все еще существует.
У вас есть два пути:
Начнем с поиска конкретного приложения на моем ноутбуке:
[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
Все примеры сейчас будут искать PID 3358.
Первый способ : Запустите «ps aux» и grep для PID во втором столбце. В этом примере я ищу Firefox, а затем его PID:
[root@pinky:~]# ps aux | awk '{print $2 }' | grep 3358
3358
Итак, ваш код будет:
if [ ps aux | awk '{print $2 }' | grep -q $PID 2> /dev/null ]; then
kill $PID
fi
Второй способ : просто поищите что-нибудь в /proc/$PID
каталоге. Я использую «exe» в этом примере, но вы можете использовать что-нибудь еще.
[root@pinky:~]# ls -l /proc/3358/exe
lrwxrwxrwx. 1 elcuco elcuco 0 2010-06-15 12:33 /proc/3358/exe -> /bin/bash
Итак, ваш код будет:
if [ -f /proc/$PID/exe ]; then
kill $PID
fi
Кстати, что не так с kill -9 $PID || true
?
РЕДАКТИРОВАТЬ:
Подумав об этом в течение нескольких месяцев ... (около 24 ...) оригинальная идея, которую я привел здесь, - хороший хак, но крайне непереносимый. Хотя он учит некоторые детали реализации Linux, он не сможет работать на Mac, Solaris или * BSD. Это может даже не сработать в будущих ядрах Linux. Пожалуйста, используйте «ps», как описано в других ответах.
/proc/$PID/exe
это не обычный файл. Таким образом, [ -f /proc/$PID/exe ]
всегда возвращает false
результат. Попробуй [ -h /proc/$PID/exe ]
.
Кажется, ты хочешь
wait $PID
который вернется, когда $pid
закончит.
В противном случае вы можете использовать
ps -p $PID
проверить, если процесс еще жив (это более эффективно, чем kill -0 $pid
потому, что он будет работать, даже если у вас нет pid).
pid 123 is not a child of this shell
Я думаю, что это плохое решение, которое открывается для условий гонки. Что если процесс умирает между вашим тестом и вашим призывом убить? Тогда убить не удастся. Так почему бы просто не попробовать kill во всех случаях и проверить ее возвращаемое значение, чтобы выяснить, как все прошло?
kill -9
. Это просто мгновенно убивает процесс, не давая ему возможности убирать за собой. Вместо этого используйте kill
что эквивалентно kill -15
. Если это не сработает, вы должны выяснить, почему, и только в крайнем случае kill -9
.
здесь я сохраняю PID в файле с именем .pid (что-то вроде / run / ...) и выполняю сценарий, только если он еще не выполняется.
#!/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
примечание: есть состояние гонки, поскольку оно не проверяет, как называется этот pid. если система перезагружена и .pid существует, но используется другим приложением, это может привести к «непредвиденным последствиям».
Например, в GNU / Linux вы можете использовать:
Pid=$(pidof `process_name`)
if [ $Pid > 0 ]; then
do something
else
do something
fi
Или что-то вроде
Pin=$(ps -A | grep name | awk 'print $4}')
echo $PIN
и это показывает вам имя приложения, просто имя без идентификатора.
pidof
не возвращает отрицательное число, так как отрицательный PID не имеет никакого смысла, и вы не можете убить init
, поэтому ваше условное выражение не имеет смысла (и, кроме того, вам нужно будет экранировать, >
чтобы предотвратить перенаправление). Вы хотите проверить наличие пустого результата, но, конечно, как и любой приличный инструмент, pidof
устанавливает код выхода, чтобы сообщить вам, сработал ли он, поэтому правильное решение - if Pid=$(pidof 'process_name'); then ...
или (если вам не понадобится значение в Pid
дальнейшем) простоif pidof 'process_name'; then...
pidof
пример полон недоразумений о том, как test
работает bash . gnu.org/software/bash/manual/html_node/…
Приведенный ниже код проверяет, работает ли мой процесс, если это не так, ничего не делайте.
давайте проверять новые сообщения от Amazon SQS только каждый час и только если процесс не запущен.
#!/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 $?