Как проверить / запустить процесс | ошибка в скрипте

Если хотите проверить, запущен ли процесс, и запустите его, если нет. Мой скрипт ниже глючит и всегда говорит, что процесс запущен. Что случилось?

$ ./check_n_run thisisnotrunning
./check_n_run: thisisnotrunning is already running

Вот сценарий:

$ cat check_n_run

#!/bin/sh

USAGE="usage: $0 processname"
if [ $# -ne 1 ] ; then
        echo "$USAGE" >&2
        exit 1
fi

ps ax | grep -v grep | grep $1> /dev/null
if [ $? -eq 1 ]
then
  echo "$1 not running"
  # start here      
else
  echo "$0: $1 is already running" >&2
fi

exit 0

4 ответа

Решение

Проблема в вашем сценарии заключается в том, что (с используемой оболочкой) в конвейере каждая команда выполняется в отдельной подоболочке, и ни один из их статусов не передается в родительский процесс. Так после command1 | command2, $? всегда 0.

Даже если вы исправили это, ваш сценарий крайне ненадежен: он будет сопоставлять процессы с именем, которое содержит ваш процесс в качестве подстроки. Linux предоставляет pidof Команда, которая делает именно то, что вы пытаетесь сделать.

Однако это все еще не идеально, потому что может быть другой процесс с тем же именем. Было бы лучше использовать надлежащий супервизор службы, такой как Debian/Ubuntu start-stop-daemonили выскочка службы. lockfile (из procmail), упомянутый Wrikken, также возможен.

Я думаю, что вы попробовали трудный путь. Я не знаю, какой дистрибутив вы используете, но постараюсь увидеть путь /var/run, Это каталог, включающий pid каждого процесса.

Просто попробуй ls *something*, Если что-то возвращается, значит, ваш процесс запущен. В противном случае это не так.

Пока ps / grep не выдает ошибку, $? должно быть 0.


редактировать: в соответствии с Жилем (у меня нет ни одной доступной оболочки):

в кш / зш, $? будет 1, если grep не найдет совпадения или не допустит ошибку


Я обычно склонен использовать lockfile в запуске этих процессов...

lockfile /path/to/lockfile && (do_something; rm -f /path/to/lockfile)

Хотя ваш сценарий может быть изменен на:

procs=`ps ax | grep -v grep | grep -c $1`
if [ $procs -lt 1 ]
then
....

Проблема: если ваша система похожа на мою, вывод ps ax включает не только имя процесса, но и всю командную строку, используемую для его запуска. Поэтому, когда вы бежите

./check_n_run thisisnotrunning

выход ps ax будет буквально включать эту строку, так grep всегда найдет результат для thisisnotrunning, Это объясняет, почему ваш скрипт всегда сообщает, что программа запущена.

Чтобы обойти это, есть несколько вариантов. Как отметил Жиль, лучше всего использовать start-stop-daemon запустить и остановить ваш скрипт. Если это не возможно, вы можете использовать pidof определить, запущен ли данный исполняемый файл. И если по какой-то причине это было недоступно, вы можете использовать

ps -C thisisnotrunning

который печатает только процессы с заданным именем команды.

Другие вопросы по тегам