Это небезопасно.
Предположим, что три копии вашего сценария (A, B и C) запускаются одновременно, а /tmp/test.pid
изначально не существует.
Пусть A и B завершатначальные операторы скрипта:
PIDFILE=/tmp/test.pid
flag=$PIDFILE.flag
touch $flag
if [ -f $PIDFILE ]; then
ps | grep -qE '^\s*'$(cat $PIDFILE) && exit
fi
Переключитесь на A и дайте ему выполнить еще два оператора:
echo $$ > $PIDFILE
rm $flag || exit
Это успешно;$PIDFILE
теперь содержит PID A.
Переключитесь на B и позвольте ему выполнять те же операторы.rm
не удается, и поэтому B завершается, но $PIDFILE
теперь содержит PID B.
Переключение на C. C только что начал работать, поэтому первое, что он делает, это воссоздает $flag
:
PIDFILE=/tmp/test.pid
flag=$PIDFILE.flag
touch $flag
Теперь идет проверка PID:
if [ -f $PIDFILE ]; then
ps | grep -qE '^\s*'$(cat $PIDFILE) && exit
fi
Это проходит, потому что $PIDFILE
содержит PID B, но B. больше не работает.
Теперь мы переходим к
echo $$ > $PIDFILE
rm $flag || exit
Это также проходит, потому что C только что воссоздал файл $flag
.
Теперь у нас есть и A, и C, бегущие друг с другом, чтобы снова перезаписать $PIDFILE
.
Кроме того, существует также проблема "ложного срабатывания":
if [ -f $PIDFILE ]; then
ps | grep -qE '^\s*'$(cat $PIDFILE) && exit
fi
Возможно, у вас устаревший $PIDFILE
, но содержащийся в нем PID был повторно использован для другого процесса.В этом случае вы получаете не гонку (и слишком много экземпляров вашего скрипта), а отказ в обслуживании (слишком мало экземпляров вашего скрипта: 0).Ваш скрипт увидит запущенный процесс, который, как оказалось, имеет «неправильный» PID, и завершится.