Если хотите проверить, запущен ли процесс, и запустить его, если нет. Мой сценарий ниже содержит ошибки и всегда говорит, что процесс запущен. Что случилось?
$ ./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
....