Я ищу простое и универсальное решение, позволяющее выполнять любой скрипт или приложение в crontab и не запускать его дважды.
Решение должно быть независимым от выполненной команды.
Я предполагаю, что он должен выглядеть как lock && (command ; unlock), где lock вернет false, если была еще одна блокировка.
Вторая часть была бы такой, как если бы она приобрела блокировку, запустила команду и разблокировала после команды выполняется, даже если он возвращает ошибку.
Взгляните на пакет run-one. Из manpage для команды run-one:
run-one - это сценарий оболочки, который запускает не более одного уникального экземпляра некоторой команды с уникальным набором аргументов. Это часто полезно для cronjob, когда вы хотите, чтобы одновременно выполнялось не более одной копии.Как и time или sudo, вы просто добавляете его в команду. Итак, cronjob может выглядеть так:
*/60 * * * * run-one rsync -azP $HOME example.com:/srv/backup
Для получения дополнительной информации и фона посмотрите run-one Dustin Kirkland.
Взгляните на пакет run-one. Из manpage для команды run-one:
run-one - это сценарий оболочки, который запускает не более одного уникального экземпляра некоторой команды с уникальным набором аргументов. Это часто полезно для cronjob, когда вы хотите, чтобы одновременно выполнялось не более одной копии.Как и time или sudo, вы просто добавляете его в команду. Итак, cronjob может выглядеть так:
*/60 * * * * run-one rsync -azP $HOME example.com:/srv/backup
Для получения дополнительной информации и фона посмотрите run-one Dustin Kirkland.
Это решение для сценария bash, который должен проверять себя
v=$(pgrep -xf "/bin/bash $0 $@")
[ "${v/$BASHPID/}" != "" ] && exit 0
Простое решение от bash-hackers.org, которое работало для меня, использовало mkdir. Это простой способ убедиться, что работает только один экземпляр вашей программы. Создайте каталог с mkdir .lock, который возвращает
true, если создание было успешным и false, если файл блокировки существует, указывая на то, что в настоящее время работает один экземпляр.Итак, эта простая функция выполнила всю логику блокировки файлов:
if mkdir .lock; then
echo "Locking succeeded"
eval startYourProgram.sh ;
else
echo "Lock file exists. Program already running? Exit. "
exit 1
fi
echo "Program finished, Removing lock."
rm -r .lock
См. также [4] Тима Кэя, который выполняет блокировку путем привязки порта по замкнутому адресу, уникальному для пользователя:
http://timkay.com/solo/
] В случае, если его сайт не работает:
Использование:
solo -port=PORT COMMAND
where
PORT some arbitrary port number to be used for locking
COMMAND shell command to run
options
-verbose be verbose
-silent be silent
Используйте его так:
* * * * * solo -port=3801 ./job.pl blah blah
Сценарий:
#!/usr/bin/perl -s
#
# solo v1.7
# Prevents multiple cron instances from running simultaneously.
#
# Copyright 2007-2016 Timothy Kay
# http://timkay.com/solo/
#
# It is free software; you can redistribute it and/or modify it under the terms of either:
#
# a) the GNU General Public License as published by the Free Software Foundation;
# either version 1 (http://dev.perl.org/licenses/gpl1.html), or (at your option)
# any later version (http://www.fsf.org/licenses/licenses.html#GNUGPL), or
#
# b) the "Artistic License" (http://dev.perl.org/licenses/artistic.html), or
#
# c) the MIT License (http://opensource.org/licenses/MIT)
#
use Socket;
alarm $timeout if $timeout;
$port =~ /^\d+$/ or $noport or die "Usage: $0 -port=PORT COMMAND\n";
if ($port)
{
# To work with OpenBSD: change to
# $addr = pack(CnC, 127, 0, 1);
# but make sure to use different ports across different users.
# (Thanks to www.gotati.com .)
$addr = pack(CnC, 127, $<, 1);
print "solo: bind ", join(".", unpack(C4, $addr)), ":$port\n" if $verbose;
$^F = 10; # unset close-on-exec
socket(SOLO, PF_INET, SOCK_STREAM, getprotobyname('tcp')) or die "socket: $!";
bind(SOLO, sockaddr_in($port, $addr)) or $silent? exit: die "solo($port): $!\n";
}
sleep $sleep if $sleep;
exec @ARGV;
Не нужно устанавливать какой-то причудливый пакет:
#!/bin/bash
pgrep -xf "$*" > /dev/null || "$@"
Быстрее писать сам скрипт, чем запускать «apt-get install», не так ли? Вы можете добавить «-u & nbsp; $ (id -u)» в pgrep для проверки экземпляров, выполняемых только текущим пользователем.
Очень простой способ установки блокировки:
if mkdir /var/lock/mylock; then
echo "Locking succeeded" >&2
else
echo "Lock failed - exit" >&2
exit 1
fi
Скрипты, которые нужно запустить, требуют создания блокировки. Если блокировка существует, другой скрипт занят, поэтому первый скрипт не может работать. Если файл не существует, ни один скрипт не приобрел блокировку. Таким образом, текущий скрипт получает блокировку.
Для получения дополнительной информации о блокировке bash, проверьте эту страницу
.Вам нужен замок. run-one выполняет задание, но вы также можете просмотреть flock из пакета util-linux.
Это стандартный пакет, предоставляемый разработчиками ядра, позволяет настраивать больше, чем run-one и все еще очень просто.
Это решение для сценария bash, который должен проверять себя
v=$(pgrep -xf "/bin/bash $0 $@")
[ "${v/$BASHPID/}" != "" ] && exit 0
Простое решение от bash-hackers.org, которое работало для меня, использовало mkdir. Это простой способ убедиться, что работает только один экземпляр вашей программы. Создайте каталог с mkdir .lock, который возвращает
true, если создание было успешным и false, если файл блокировки существует, указывая на то, что в настоящее время работает один экземпляр.Итак, эта простая функция выполнила всю логику блокировки файлов:
if mkdir .lock; then
echo "Locking succeeded"
eval startYourProgram.sh ;
else
echo "Lock file exists. Program already running? Exit. "
exit 1
fi
echo "Program finished, Removing lock."
rm -r .lock
См. также [4] Тима Кэя, который выполняет блокировку путем привязки порта по замкнутому адресу, уникальному для пользователя:
http://timkay.com/solo/
] В случае, если его сайт не работает:
Использование:
solo -port=PORT COMMAND
where
PORT some arbitrary port number to be used for locking
COMMAND shell command to run
options
-verbose be verbose
-silent be silent
Используйте его так:
* * * * * solo -port=3801 ./job.pl blah blah
Сценарий:
#!/usr/bin/perl -s
#
# solo v1.7
# Prevents multiple cron instances from running simultaneously.
#
# Copyright 2007-2016 Timothy Kay
# http://timkay.com/solo/
#
# It is free software; you can redistribute it and/or modify it under the terms of either:
#
# a) the GNU General Public License as published by the Free Software Foundation;
# either version 1 (http://dev.perl.org/licenses/gpl1.html), or (at your option)
# any later version (http://www.fsf.org/licenses/licenses.html#GNUGPL), or
#
# b) the "Artistic License" (http://dev.perl.org/licenses/artistic.html), or
#
# c) the MIT License (http://opensource.org/licenses/MIT)
#
use Socket;
alarm $timeout if $timeout;
$port =~ /^\d+$/ or $noport or die "Usage: $0 -port=PORT COMMAND\n";
if ($port)
{
# To work with OpenBSD: change to
# $addr = pack(CnC, 127, 0, 1);
# but make sure to use different ports across different users.
# (Thanks to www.gotati.com .)
$addr = pack(CnC, 127, $<, 1);
print "solo: bind ", join(".", unpack(C4, $addr)), ":$port\n" if $verbose;
$^F = 10; # unset close-on-exec
socket(SOLO, PF_INET, SOCK_STREAM, getprotobyname('tcp')) or die "socket: $!";
bind(SOLO, sockaddr_in($port, $addr)) or $silent? exit: die "solo($port): $!\n";
}
sleep $sleep if $sleep;
exec @ARGV;
Не нужно устанавливать какой-то причудливый пакет:
#!/bin/bash
pgrep -xf "$*" > /dev/null || "$@"
Быстрее писать сам скрипт, чем запускать «apt-get install», не так ли? Вы можете добавить «-u & nbsp; $ (id -u)» в pgrep для проверки экземпляров, выполняемых только текущим пользователем.
Очень простой способ установки блокировки:
if mkdir /var/lock/mylock; then
echo "Locking succeeded" >&2
else
echo "Lock failed - exit" >&2
exit 1
fi
Скрипты, которые нужно запустить, требуют создания блокировки. Если блокировка существует, другой скрипт занят, поэтому первый скрипт не может работать. Если файл не существует, ни один скрипт не приобрел блокировку. Таким образом, текущий скрипт получает блокировку.
Для получения дополнительной информации о блокировке bash, проверьте эту страницу
.Вам нужен замок. run-one выполняет задание, но вы также можете просмотреть flock из пакета util-linux.
Это стандартный пакет, предоставляемый разработчиками ядра, позволяет настраивать больше, чем run-one и все еще очень просто.