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

Как я могу запустить скрипт из cron только один раз?

Я хочу запустить cron. Планирование легко и работает.

Моя проблема в том, что я не знаю, как запустить только одну версию за раз.

Любые идеи?

G-Man

Приношу свои извинения Embobo, но я скопировал его сценарий и изменил его, чтобы исключить состояние гонки, которое я отметил в своем комментарии к его ответу:

#!/bin/sh
LOCKDIR=/var/run/myprog.lock
mkdir --mode=700 $LOCKDIR || exit 0
trap "{ rm -rf $LOCKDIR ; exit 0; }" EXIT
# do stuff

По сути, мы рассчитываем на то, что создание каталога является атомарным, так что только одна копия этого скрипта, запущенная одновременно, может успешно создать $LOCKDIR. Наверное, лучше убедиться, что $LOCKDIR находится на локальном диске, а не на диске NFS, монтировании Samba и т. д.

Вы можете использовать файл блокировки. Пример кода оболочки:

#!/bin/sh
LOCKFILE=/var/run/myprog.pid
[ -f $LOCKFILE ] && exit 0
trap "{ rm -f $LOCKFILE ; exit 0; }" EXIT
echo "$$" > $LOCKFILE
# do stuff

Важно убедиться, что файл блокировки удаляется при любом выходе (нормальном или ненормальном). Вот что trap команда делает.

Вы можете сделать его более сложным, сделав больше, если файл блокировки существует. Например, получите pid из файла и посмотрите, действительно ли он запущен.

Просто пусть ваш скрипт касается файла при его запуске и удаляет этот файл, когда он завершается. Затем в сценарии вы можете проверить наличие этого файла, прежде чем что-либо делать.

В псевдокоде:

if (!exists(/var/run/filename))
{
    touch /var/run/filename;
    do stuff;
    rm /var/run/filename;
}

Вы можете сделать это, создав файл или каталог блокировки. Я лично открываю соединение сокета к какому-то высокому порту. Это гарантирует, что даже в случае сбоя приложения сокет будет закрыт. С файлом блокировки файл может продолжаться, и ваш сценарий не будет работать, пока вы не удалите его вручную.

По моему опыту, это оказалось более надежным.

В большинстве систем установлен бинарный файл "lockfile", который можно использовать, чтобы не попасть в игру, в которой нужно создавать сценарии bash. В RHEL / CentOS / Fedora это часть пакета procmail.

Итак, вы можете написать что-то вроде:
lockfile /var/lock/mycron.lock && /usr/local/bin/mycron && rm -f /var/lock/mycron.lock

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

Кажется, мне удалось выполнить следующий сценарий вызова:

#!/bin/zsh
RED_="\033[31m"
BLUE_="\033[34m"
BLACK_="\033[0m"
if [ $# -lt 1 ]; then
 echo "$0: Invoke a program/script only once at a time"
 echo "Syntax: $0 <program/script with parameters>"
else
 if ps -Alf | grep "$*" | grep -v grep | grep -v $0 >/dev/null; then
  echo "$BLUE_\"$@\"$RED_ runs already. I don't invoke it.$BLACK_"
 else
  echo "${RED_}I invoke: $BLUE_$@$BLACK_"
  $@
 fi
fi