确保在 Linux 上仅运行一个 Bash 脚本实例


简介

在 Linux 上运行bash脚本时,务必确保一次只运行一个脚本实例。这对于执行关键任务的脚本尤其重要,例如更新数据库或发送电子邮件的脚本。同时运行多个相同脚本实例可能会导致冲突、数据丢失和其他错误。在本文中,我们将讨论确保 Linux 上仅运行一个bash脚本实例的不同方法。

使用 Flock

确保 Linux 上仅运行一个bash脚本实例的一种方法是使用“flock”命令。flock命令用于对文件创建锁,并且是大多数 shell(例如BashZsh等)中内置的命令。这是一种简单有效的方法,可以确保一次只运行一个脚本实例。

我们可以信任这种方法,因为它不会出现竞争条件。此外,当进程完成时,文件上的所有锁都会被释放。这些优点使得 flock 成为确保仅运行一个实例的安全方法。另一个好处是 flock 程序是 flock 系统调用的实现。

flock默认情况下会阻塞,直到锁被释放,然后继续执行,不会出现错误。我们可以使用“-n”参数以非阻塞方式使用 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,并将我们需要保护的所有内容括在方括号(子 shell)中,并将其重定向到我们用作锁的文件。我们使用在重定向中使用的文件描述符在开头调用 flock。因此,如果 flock 以错误退出,我们就知道有另一个实例正在运行。

子级别完成后,锁文件将关闭,锁将自动释放。

使用 Pid 文件

确保 Linux 上仅运行一个bash脚本实例的另一种方法是使用pid文件。pid 文件是一个特殊文件,其中包含正在运行的脚本的进程 ID (PID)。通过检查 pid 文件,我们可以确定脚本是否正在运行,如果正在运行,则以错误消息退出脚本。

要实现此方法,我们可以将以下代码添加到脚本的开头:

if [ -f /path/to/pidfile ]; then
   pid=$(cat /path/to/pidfile)
   if kill -0 $pid 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

结论

确保 Linux 上仅运行一个 bash 脚本实例是一项重要任务,可以防止冲突、数据丢失和其他错误。有几种方法可以做到这一点,例如使用 flock 命令使用锁文件,使用 pid 文件,或使用“pgrep”和“kill”命令。每种方法都有其优点和缺点,最适合您的脚本的方法将取决于您的特定需求。通过实现任何这些方法,您可以确保您的脚本顺利运行且不会出错。

更新于:2023年1月20日

2K+ 次浏览

开启您的职业生涯

完成课程获得认证

开始学习
广告
© . All rights reserved.