Предотвратите дублирующееся выполнение заданий крона

Редкий, но удача;

Alt + Space + (M or Down Arrow) + Arrow Keys

сопроводительный текст http://helpmerick.com/images/wincontrolicon.gif

Когда Вы, Удаленный рабочий стол/VNC и т.д. в ПК, который имеет очень большое (или дважды/трижды) установка монитора от ПК только с единственным/маленьким экраном много окон, появится от экрана (и хуже все же может не показать на панели задач (например, Открыть диалоговое окно File из приложения),

Так как Вы не можете заставить свою мышь к приложению перемещаться, вышеупомянутое окна добивается цели.

Alt + Space

Открывает небольшое контекстное меню в строке заголовка приложения

M or Down Arrow

Переходит к опции Move

Arrow Keys

Позволяет Вам безопасно возвратить внеэкранное окно/диалоговое окно некоторой точке на экране, где можно на самом деле просмотреть его / используют его!

Править: если Вы видите панель задач, можно также просто щелкнуть правой кнопкой по приложению в панели задач и нажать "Move", то сразу (не перемещая мышь) нажимают и удерживают левую кнопку мыши, затем перетаскивают окно в представление тот путь. это - нажатие клавиши меньше способ сделать это.

93
задан 9 November 2009 в 13:32
11 ответов

Существует несколько программ, которые автоматизируют эту функцию, устраняют раздражение и потенциальные ошибки от выполнения этого самостоятельно, и избегают устаревшей проблемы блокировки при помощи скопления негласно, также (который является риском, если Вы просто используете касание). Я использовал lockrun и lckdo в прошлом, но теперь существует flock(1) (в довольно новых версиях util-linux), который является большим. Это действительно просто в использовании:

* * * * * /usr/bin/flock -n /tmp/fcj.lockfile /usr/local/bin/frequent_cron_job
120
ответ дан 28 November 2019 в 19:23

Лучший способ в оболочке состоит в том, чтобы использовать скопление (1)

(
  flock -x -w 5 99
  ## Do your stuff here
) 99>/path/to/my.lock
28
ответ дан 28 November 2019 в 19:23
  • 1
    Я can' t не upvote хитрое использование fd перенаправления. It' s просто слишком тайно потрясающий. –  womble♦ 9 November 2009 в 13:57
  • 2
    Doesn' t синтаксический анализ для меня в Bash или ZSH, должен устранить пространство между 99 и >, таким образом, это 99> /... –  Kyle Brandt 9 November 2009 в 14:36
  • 3
    @Javier: Doesn' t означают it' s не хитрый и тайный, просто это it' s зарегистрировал , хитрый, и тайный. –  womble♦ 11 November 2009 в 14:29

На самом деле, flock -n может использоваться вместо lckdo*, таким образом, Вы будете использовать код от разработчиков ядра.

Основываясь на примере womble, Вы записали бы что-то как:

* * * * * flock -n /some/lockfile command_to_run_every_minute

BTW, смотря на код, весь из flock, lockrun, и lckdo сделайте ту же самую вещь, таким образом, это - просто вопрос, которого является самым легко доступным Вам.

22
ответ дан 28 November 2019 в 19:23

Вы не указали, хотите ли Вы, чтобы сценарий ожидал предыдущего выполнения для завершения или нет. "Я не хочу, чтобы задания запустили "укладку" друг по другу", я предполагаю, что Вы подразумеваете, что хотите, чтобы сценарий вышел, уже работая,

Так, если Вы надеваете, хотят зависеть от lckdo или подобный, можно сделать это:


PIDFILE=/tmp/`basename $0`.pid

if [ -f $PIDFILE ]; then
  if ps -p `cat $PIDFILE` > /dev/null 2>&1; then
      echo "$0 already running!"
      exit
  fi
fi
echo $$ > $PIDFILE

trap 'rm -f "$PIDFILE" >/dev/null 2>&1' EXIT HUP KILL INT QUIT TERM

# do the work

3
ответ дан 28 November 2019 в 19:23
  • 1
    Спасибо Ваш пример полезен - я действительно хочу, чтобы сценарий вышел, уже работая. Спасибо за упоминание ickdo - это, кажется, добивается цели. –  Tom 11 November 2009 в 13:36

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

Lockfiles используются initscripts и многими другими приложениями и утилитами в системах Unix.

2
ответ дан 28 November 2019 в 19:23
  • 1
    это только путь I' ve, когда-либо замеченный, это реализовало, лично. Я использую на согласно maintainer' s предложение как зеркало для проекта OSS –  warren 9 November 2009 в 13:48

Это могло бы также быть знаком, что Вы делаете неправильную вещь. Если Ваши задания выполняют это тесно и что часто, возможно, необходимо считать de-cronning этим и создание его программа стиля демона.

1
ответ дан 28 November 2019 в 19:23
  • 1
    Я сердечно не соглашаюсь с этим. Если у Вас есть что-то, что должно периодически работать, делая это, демон является " кувалда для nut" решение. Используя lockfile для предотвращения несчастных случаев совершенно разумное решение I' ve никогда не имел проблему с помощью. –  womble♦ 9 November 2009 в 13:53
  • 2
    @womble я соглашаюсь; но мне нравится разбивать гайки кувалдами!:-) –  wzzrd 9 November 2009 в 17:01

Ваш демон крона не должен вызывать задания, если предыдущие экземпляры их все еще работают. Я - разработчик одного демона крона dcron, и мы конкретно пытаемся предотвратить это. Я не знаю, как крон Vixie или другие демоны обрабатывают это.

1
ответ дан 28 November 2019 в 19:23

Я создал одну банку для решения такой проблемы, как запуск дублирующих крон может быть java или shell cron. Просто передайте имя cron в Duplicates.CloseSessions ("Demo.jar"), который будет искать и убивать existng pid для этого cron, кроме текущего. Я реализовал метод для этого. Строка proname=ManagementFactory.getRuntimeMXBean().getName(); Строка pid=proname.split("@")[0]; System.out.println("Current PID: "+pid);

            Process proc = Runtime.getRuntime().exec(new String[]{"bash","-c"," ps aux | grep "+cronname+" | awk '{print $2}' "});

            BufferedReader stdInput = new BufferedReader(new InputStreamReader(proc.getInputStream()));
            String s = null;
            String killid="";

            while ((s = stdInput.readLine()) != null ) {                                        
                if(s.equals(pid)==false)
                {
                    killid=killid+s+" ";    
                }
            }

А затем снова убить строку killid командой shell

.
0
ответ дан 28 November 2019 в 19:23

Я бы рекомендовал использовать команду run-one - это намного проще, чем иметь дело с блокировками. Из документации:

run-one - это сценарий-оболочка, который запускает не более одного уникального экземпляра некоторой команды с уникальным набором аргументов. Это часто бывает полезно с cronjobs, когда вы хотите, чтобы одновременно выполнялось не более одной копии.

run-this-one точно такой же, как run-one, за исключением того, что он будет использовать pgrep и kill для поиска и уничтожения любые запущенные процессы, принадлежащие пользователю и сопоставление целевых команд и аргументов. Обратите внимание, что run-this-one будет блокироваться при попытке убить соответствующие процессы, пока все соответствующие процессы не работают.

run-one-always работает точно так же, как run-one, за исключением того, что возрождает "COMMAND [ARGS]" каждый раз, когда COMMAND завершается (ноль или ненулевое значение).

keep-one-running - это псевдоним для run-one-always.

run-one-until-success работает точно так же, как и запускать один постоянно, за исключением что он возрождает "COMMAND [ARGS]", пока COMMAND не завершится успешно (т. е. выходит из нуля).

run-one-until-failure работает точно так же, как run-one-always, за исключением что он воспроизводит "КОМАНДА [ARGS]" до тех пор, пока КОМАНДА не завершится с ошибкой (т. е. выход ненулевой).

1
ответ дан 28 November 2019 в 19:23

Ответ @Philip Reynolds в любом случае начнет выполнение кода после 5 секунд ожидания без получения блокировки. После Flock, похоже, не работает , я изменил ответ @Philip Reynolds на

(
  flock -w 5 -x 99 || exit 1
  ## Do your stuff here
) 99>/path/to/my.lock

, чтобы код никогда не выполнялся одновременно. Вместо этого после 5 секунд ожидания процесс завершится с 1, если к тому времени он не получит блокировку.

0
ответ дан 28 November 2019 в 19:23

Теперь, когда systemd отсутствует, есть еще один механизм планирования в системах Linux:

A systemd.timer

В /etc/systemd/system/myjob.service или ~ / .config / systemd / user / myjob.service :

[Service]
ExecStart=/usr/local/bin/myjob

В /etc/systemd/system/myjob.timer или ~ / .config / systemd / user /myjob.timer:

[Timer]
OnCalendar=minutely

[Install]
WantedBy=timers.target

Если сервисный модуль уже активирован, когда таймер в следующий раз активируется, то другой экземпляр сервиса будет , а не запущен.

Альтернатива, которая запускает задание один раз при загрузке и через одну минуту после завершения каждого запуска:

[Timer]
OnBootSec=1m
OnUnitInactiveSec=1m 

[Install]
WantedBy=timers.target
1
ответ дан 28 November 2019 в 19:23

Теги

Похожие вопросы