Linux 如何确保一次只运行一个Bash脚本实例?
我想制作一个sh脚本,它在任何时候最多只能运行一次 比方说,如果我执行了脚本,那么我将再次执行脚本,我如何使脚本的第一个执行器仍在工作,那么第二个执行器将因错误而失败。也就是说,在执行任何操作之前,我需要检查脚本是否在其他地方运行。我该怎么做呢Linux 如何确保一次只运行一个Bash脚本实例?,linux,bash,concurrency,scheduled-tasks,Linux,Bash,Concurrency,Scheduled Tasks,我想制作一个sh脚本,它在任何时候最多只能运行一次 比方说,如果我执行了脚本,那么我将再次执行脚本,我如何使脚本的第一个执行器仍在工作,那么第二个执行器将因错误而失败。也就是说,在执行任何操作之前,我需要检查脚本是否在其他地方运行。我该怎么做呢 我的脚本运行了一个长时间运行的过程(即永远运行)。我想使用cron之类的东西每隔15分钟调用一次脚本,这样万一进程失败,它将由下一个cron运行脚本重新启动 将进程id写入文件,然后在新实例启动时,检查该文件以查看旧实例是否仍在运行 您想要一个pid文件
我的脚本运行了一个长时间运行的过程(即永远运行)。我想使用cron之类的东西每隔15分钟调用一次脚本,这样万一进程失败,它将由下一个cron运行脚本重新启动 将进程id写入文件,然后在新实例启动时,检查该文件以查看旧实例是否仍在运行 您想要一个pid文件,可能是这样的:
pidfile=/path/to/pidfile
if [ -f "$pidfile" ] && kill -0 `cat $pidfile` 2>/dev/null; then
echo still running
exit 1
fi
echo $$ > $pidfile
$ ql_acquire_lock
我认为您需要使用lockfile命令。看到或看到 第二篇文章使用“手工制作的锁文件”,展示了如何捕获脚本终止和释放锁;尽管在大多数情况下,使用
lockfile-l
可能是一个足够好的选择
无超时的使用示例:
lockfile script.lock
<do some stuff>
rm -f script.lock
由于
lockfile
可以创建多个锁文件,因此有一个参数可以指导它在重试获取所需的下一个文件之前应该等待多长时间(-
和-r
)。还有一个参数-s
用于强制解除锁时的等待时间(这是对强制解除锁前等待超时的补充)。您可以使用运行一个包,该包提供运行一个,运行这个和保持一个运行
一揽子计划:
介绍它的博客:
来自flock(1)手册页中的示例。在shell脚本中使用非常实用。我刚刚编写了一个工具,可以实现以下功能:
编写一个好的脚本大约需要15个loc,所以不是每个shell脚本都要包含的东西
基本上是这样工作的:
pidfile=/path/to/pidfile
if [ -f "$pidfile" ] && kill -0 `cat $pidfile` 2>/dev/null; then
echo still running
exit 1
fi
echo $$ > $pidfile
$ ql_acquire_lock
上面调用此bash函数:
function ql_acquire_lock {
set -e;
name="${1:-$PWD}" # the lock name is the first argument, if that is empty, then set the lockname to $PWD
mkdir -p "$HOME/.quicklock/locks"
fle=$(echo "${name}" | tr "/" _)
qln="$HOME/.quicklock/locks/${fle}.lock"
mkdir "${qln}" &> /dev/null || { echo "${ql_magenta}quicklock: could not acquire lock with name '${qln}'${ql_no_color}."; exit 1; }
export quicklock_name="${qln}"; # export the var *only if* above mkdir command succeeds
trap on_ql_trap EXIT;
}
当脚本退出时,它会使用陷阱自动释放锁
function on_ql_trap {
echo "quicklock: process with pid $$ was trapped.";
ql_release_lock
}
要随意手动释放锁,请使用ql\u release\u lock
:
function ql_maybe_fail {
if [[ "$1" == "true" ]]; then
echo -e "${ql_magenta}quicklock: exiting with 1 since fail flag was set for your 'ql_release_lock' command.${ql_no_color}"
exit 1;
fi
}
function ql_release_lock () {
if [[ -z "${quicklock_name}" ]]; then
echo -e "quicklock: no lockname was defined. (\$quicklock_name was not set).";
ql_maybe_fail "$1";
return 0;
fi
if [[ "$HOME" == "${quicklock_name}" ]]; then
echo -e "quicklock: dangerous value set for \$quicklock_name variable..was equal to user home directory, not good.";
ql_maybe_fail "$1"
return 0;
fi
rm -r "${quicklock_name}" &> /dev/null &&
{ echo -e "quicklock: lock with name '${quicklock_name}' was released."; } ||
{ echo -e "quicklock: no lock existed for lockname '${quicklock_name}'."; ql_maybe_fail "$1"; }
trap - EXIT # clear/unset trap
}
很好的链接,我发誓“set-x”和“set-e”。很有趣,以前从未尝试过。谢谢愚蠢的问题。。。我假设,如果持有锁的进程被杀死/死掉,锁就会被释放,而不需要进行任何黑客攻击等等。在这种情况下,锁文件看起来会保留。但是,有一个参数(-s XX)用于指定一个超时,在该超时之后,无论进程是否执行该操作,锁都将被删除。确定,该参数可能是错误的。在我的盒子上是-l。我想使用超时是一个设计问题——您的脚本/进程是否能够处理错误而不会意外死亡。您还可以让另一个进程监视主进程并管理锁文件。=)虽然此链接可以回答问题,但最好在此处包含答案的基本部分,并提供链接供参考。如果链接页面发生更改,仅链接的答案可能无效。-如果您的意思是在kill命令中,-0表示进程仍在运行,但如果进程正在运行,则不接触它。如果进程实际上没有运行,2>/dev/null将丢弃任何不需要的噪声。我已经读到PID文件不是解决此问题的好方法。。。如果某些进程可以采用相同的PID等,则可以重用进程ID,这是正确的。如果您真的担心这一点,您可能会使用Peter Anvin的flock(1)程序,该程序随util linux发行版一起提供。只需检查pid是否有效就很容易出错,因为可能有一个不相关的进程正在使用该pid运行。使用ps
检查流程是否实际相关可能会变得混乱。如果同一个脚本的两个实例可以运行,但参数不同呢?这绝对不是万无一失的。