有什么快速而简单的方法可以确保在给定时间内只有一个shell脚本实例在运行?


当前回答

使用进程的锁更强大,还可以处理不合理的退出。 只要进程在运行,Lock_file就保持打开状态。一旦进程存在,它将被关闭(通过shell)(即使它被杀死)。 我发现这个方法非常有效:

lock_file=/tmp/`basename $0`.lock

if fuser $lock_file > /dev/null 2>&1; then
    echo "WARNING: Other instance of $(basename $0) running."
    exit 1
fi
exec 3> $lock_file 

其他回答

使用flock(1)在文件描述符上创建一个独占作用域锁。通过这种方式,您甚至可以同步脚本的不同部分。

#!/bin/bash

(
  # Wait for lock on /var/lock/.myscript.exclusivelock (fd 200) for 10 seconds
  flock -x -w 10 200 || exit 1

  # Do stuff

) 200>/var/lock/.myscript.exclusivelock

这确保(和)之间的代码一次只由一个进程运行,并且该进程不会为锁等待太长时间。

注意:这个特殊的命令是util-linux的一部分。如果您运行的是Linux以外的操作系统,那么它可能不可用,也可能不可用。

您可以使用GNU Parallel,因为它在作为sem调用时是作为互斥量工作的。所以,具体来说,你可以使用:

sem --id SCRIPTSINGLETON yourScript

如果你也想要一个超时,使用:

sem --id SCRIPTSINGLETON --semaphoretimeout -10 yourScript

如果信号量在超时时间内没有释放,Timeout <0表示退出而不运行脚本,>的Timeout表示仍然运行脚本。

注意,您应该给它一个名称(使用——id),否则它默认为控制终端。

GNU Parallel在大多数Linux/OSX/Unix平台上是一个非常简单的安装程序——它只是一个Perl脚本。

信号量实用程序使用flock(如上所述,例如by presto8)来实现计数信号量。它支持您想要的任意数量的并发进程。我们使用它来限制各种队列工作者进程的并发级别。

它很像sem,但重量轻得多。(完全披露:我是在发现sem对我们的需求来说太繁重了,而且没有一个简单的计数信号量实用程序可用后写的。)

我有一个基于文件名的简单解决方案

#!/bin/bash

MY_FILENAME=`basename "$BASH_SOURCE"`

MY_PROCESS_COUNT=$(ps a -o pid,cmd | grep $MY_FILENAME | grep -v grep | grep -v $$ | wc -
l)

if [ $MY_PROCESS_COUNT -ne 0  ]; then
  echo found another process
  exit 0
if

# Follows the code to get the job done.

在flock(2)系统调用周围有一个包装器,毫无想象力地称为flock(1)。这使得可靠地获得独占锁相对容易,而不必担心清理等问题。手册页上有一些关于如何在shell脚本中使用它的示例。