Назад | Перейти на главную страницу

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

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

$ ./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

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

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

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

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

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

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

./check_n_run thisisnotrunning

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

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

ps -C thisisnotrunning

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

Пока 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
....