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


当前回答

看看FLOM (Free LOck Manager) http://sourceforge.net/projects/flom/:,您可以使用文件系统中不需要锁文件的抽象资源来同步命令和/或脚本。您可以在没有NFS(网络文件系统)服务器这样的NAS(网络附加存储)的情况下同步在不同系统中运行的命令。

使用最简单的用例,序列化“command1”和“command2”可能和执行一样简单:

flom -- command1

and

flom -- command2

来自两个不同的shell脚本。

其他回答

你需要一个原子操作,比如flock,否则最终会失败。

但是如果没有羊群,该怎么办呢?这是mkdir。这也是一个原子操作。只有一个进程会成功执行mkdir,其他进程都会失败。

所以代码是:

if mkdir /var/lock/.myscript.exclusivelock
then
  # do stuff
  :
  rmdir /var/lock/.myscript.exclusivelock
fi

你需要处理陈旧的锁,否则崩溃后你的脚本将永远不会再次运行。

使用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以外的操作系统,那么它可能不可用,也可能不可用。

羊群走的路才是正确的。想想当脚本突然失效时会发生什么。在羊群的情况下,你只是松散的羊群,但这不是一个问题。另外,请注意,一个邪恶的伎俩是在脚本本身取一群。但这当然会让您完全陷入权限问题。

又快又脏?脚本顶部的一行代码可以工作:

[[ $(pgrep -c "`basename \"$0\"`") -gt 1 ]] && exit

当然,只要确保您的脚本名称是唯一的。:)

迟来的派对,使用来自@Majal的想法,这是我的脚本,只启动emacsclient GUI的一个实例。有了它,我可以设置快捷键打开或跳回相同的瘦弱。我有另一个脚本调用emacsclient在终端当我需要它。在这里使用emacsclient只是为了展示一个实际的例子,人们可以选择其他的东西。对于我的小脚本来说,这种方法足够快、足够好。告诉我哪里脏:)

#!/bin/bash

# if [ $(pgrep -c $(basename $0)) -lt 2 ]; then # this works but requires script name to be unique
if [ $(pidof -x "$0"|wc -w ) -lt 3 ]; then
    echo -e "Starting $(basename $0)"
    emacsclient --alternate-editor="" -c "$@"
else
    echo -e "$0 is running already"
fi