确保Linux上只有一个Bash脚本的实例在运行
介绍
在Linux上运行bash脚本时,必须确保每次只有一个脚本实例在运行。这对于执行关键任务的脚本尤其重要,比如更新数据库的脚本或发送电子邮件的脚本。同时运行同一个脚本的多个实例会导致冲突、数据丢失和其他错误。在这篇文章中,我们将讨论不同的方法,以确保在Linux上只运行一个bash脚本的实例。
使用Flock
在Linux上确保只有一个bash脚本的实例运行的方法是使用 “flock “命令。flock命令用于在文件上建立一个锁,是大多数shells(如Bash、Zsh等)内置的一个命令。这是一个简单而有效的方法,可以确保一次只运行一个脚本的实例。
我们可以相信这种方法,因为不会有竞赛条件。而且,当进程完成时,文件上的所有锁都被释放。这些好处使得成群结队成为一种安全的方式,以确保只有一个实例在运行。另一个好处是,植群程序是植群系统调用的一个实现。
flock 参数以非阻塞的方式使用flock。这将导致flock在文件上有另一个锁时立即退出并出现错误。
我们可以用flock来运行一个外部脚本,也可以在脚本中使用它。
运行一个外部脚本
我们可以在这样的脚本中使用flock —
$ flock -n /var/lock/dobackup.lock ./dobackup.sh
现在我们假设我们的脚本目前正在运行。让我们看看如果我们再次执行前一行会发生什么 —
$ flock --verbose -n /var/lock/dobackup.lock ./dobackup.sh
flock: failed to get lock
$ echo $?
1
我们可以看到,flock通知我们它无法获得锁,并以值1(错误)退出。这意味着另一个实例拥有这个锁。
当flock失败时,它不会运行脚本参数,这可以防止 “dobackup.sh “的多个实例运行。
在脚本中使用Flock
我们可以在脚本中使用flock,就像这样—-。
#!/bin/bash
another_instance()
{
echo "There is another instance running, exiting"
exit 1
}
( flock -n 100 || another_instance DEST=/home/backup/`date +%s` mkdir -p "DEST" rsync -avz root@host:/home/web "DEST/." ) 100>/var/lock/dobackup.lock
在这种情况下,我们用一个文件描述符来调用flock,并将我们需要保护的所有内容放在方括号里(子壳),并将其重定向到我们用作锁的文件。我们在开始时用重定向中使用的文件描述符调用flock。所以如果flock退出时出现错误,我们就知道有另一个实例在运行。
一旦子级别完成,锁文件就会被关闭,锁也会自动释放。
使用Pid文件
另一个确保在Linux上只有一个bash脚本实例运行的方法是使用pid文件。pid文件是一个特殊的文件,它包含了运行中的脚本的进程ID(PID)。通过检查pid文件,我们可以确定该脚本是否已经在运行,如果是,则以错误信息退出该脚本。
为了实现这个方法,我们可以在脚本的开头添加以下代码—-。
if [ -f /path/to/pidfile ]; then
pid=(cat /path/to/pidfile)
if kill -0pid 2>/dev/null; then
echo "Script is already running"
exit 1
else
echo >/path/to/pidfile
fi
else
echo > /path/to/pidfile
fi
这段代码检查指定路径中是否存在pid文件。如果pid文件存在,脚本从文件中读取pid,并通过向进程发送空信号(kill -0)来检查该进程是否仍在运行。如果该进程仍在运行,脚本将以错误信息退出。如果进程没有运行,脚本会用当前的进程ID覆盖pid文件。如果pid文件不存在,脚本会创建它并写入当前进程的id。
在脚本的最后,你可以添加以下代码来删除pid文件—-。
$ rm -f /path/to/pidfile
结论
确保一个bash脚本只有一个实例在Linux上运行是一项重要的工作,可以防止冲突、数据丢失和其他错误。有几种方法可以做到这一点,例如使用flock命令的锁文件,使用pid文件,或者使用 “pgrep “和 “kill “命令。每种方法都有其优点和缺点,对你的脚本来说,最好的方法取决于你的具体要求。通过实施这些方法中的任何一种,你都可以确保你的脚本顺利运行,没有错误。