У нас есть сценарий, который используется для синхронизации некоторых каталогов с USB-накопителем. Он настроен на запуск один раз в день, но часто занимает больше времени.
Чтобы убедиться, что несколько копий сценария не запускаются одновременно, мы проверяем список процессов и, если наш сценарий присутствует, немедленно выходим.
#!/bin/bash
#check if we are already running
running=$(ps aux | /usr/bin/grep -i "usb_sync" | /usr/bin/grep -v grep | /usr/bin/grep -c bash)
echo "usb_sync $running" >/opt/local/backup/usb_sync_log
#If we are, the quit
if [ $running -gt 1 ] ; then
exit 0
fi
Проблема в том, что эта проверка работает нормально при запуске через sudo и ручном вызове через интерфейс командной строки. Однако, когда он запускается через cron, он запускается независимо. Я пробовал несколько разных вариантов, но все они работают.
Это на FreeNAS 11.2.
Можно сделать намного проще. Создайте файл флага. В начале вашего скрипта можно использовать:
## Basic config
SCRIPTNAME=$(basename "$0")
RUNFILE="${SCRIPTNAME}.run"
# 25h in seconds adjust to your needs.
MAX_AGE=90000
# check for running process
if [ -f "$RUNFILE" ]; then
echo "process still running - exit"
if [ $(( $(date +%s) - $(date +%s --reference $RUNFILE) )) -gt ${MAX_AGE} ]; then
rm $RUNFILE;
else
exit
fi
fi
touch $RUNFILE
<your code>
rm ${RUNFILE}
Содержимое исполняемого файла может быть PID запущенного процесса. Было бы легче проанализировать, есть ли запущенный процесс.
Вместо того
touch ${RUNFILE}
использовать
echo $$ >${RUNFILE}
А pid
file - это общий подход к предотвращению многократного выполнения сценария. Его можно использовать так:
#!/bin/bash
PIDFILE=/home/vagrant/forever.pid
if [ -f $PIDFILE ]
then
PID=$(cat $PIDFILE)
ps -p $PID > /dev/null 2>&1
if [ $? -eq 0 ]
then
echo "Process already running"
exit 1
else
## Process not found assume not running
echo $$ > $PIDFILE
if [ $? -ne 0 ]
then
echo "Could not create PID file"
exit 1
fi
fi
else
echo $$ > $PIDFILE
if [ $? -ne 0 ]
then
echo "Could not create PID file"
exit 1
fi
fi
sleep 25d
rm $PIDFILE
куда sleep 25d
это фактическая команда, которая должна быть выполнена. Рекомендую прочитать это Сообщение блога для подробного объяснения различных методов решения этой проблемы. Скрипт выше взят оттуда.
Следует проверить права доступа пользователя для выполнения сценария, указанные в файле cron. Текущий сценарий также может просто не определить, запущен ли сценарий уже из-за недостаточности прав доступа. В любом случае использование файла pid кажется лучшим и менее подверженным ошибкам решением этой проблемы.