确保只有一个 Bash 脚本实例正在运行的最佳方法是什么?

新手上路,请多包涵

确保给定脚本只有一个实例正在运行的最简单/最好的方法是什么——假设它是 Linux 上的 Bash?

目前我正在做:

 ps -C script.name.sh > /dev/null 2>&1 || ./script.name.sh

但它有几个问题:

  1. 它将检查放在脚本之外
  2. 它不允许我从不同的帐户运行相同的脚本 - 我有时会喜欢。
  3. -C 只检查进程名的前 14 个字符

当然,我可以编写自己的 pidfile 处理,但我觉得应该有一个简单的方法来做到这一点。

原文由 user80168 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 820
2 个回答

如果所有用户的脚本都相同,则可以使用 lockfile 方法。如果您获得了锁,则继续,否则显示一条消息并退出。

举个例子:

 [Terminal #1] $ lockfile -r 0 /tmp/the.lock
[Terminal #1] $

[Terminal #2] $ lockfile -r 0 /tmp/the.lock
[Terminal #2] lockfile: Sorry, giving up on "/tmp/the.lock"

[Terminal #1] $ rm -f /tmp/the.lock
[Terminal #1] $

[Terminal #2] $ lockfile -r 0 /tmp/the.lock
[Terminal #2] $

获得 /tmp/the.lock 后,您的脚本将是唯一可以执行的脚本。完成后,只需卸下锁即可。在脚本形式中,这可能看起来像:

 #!/bin/bash

lockfile -r 0 /tmp/the.lock || exit 1

# Do stuff here

rm -f /tmp/the.lock

原文由 ezpz 发布,翻译遵循 CC BY-SA 2.5 许可协议

咨询锁定已经使用了很长时间,它可以在 bash 脚本中使用。我更喜欢简单的 flock (来自 util-linux[-ng] )而不是 lockfile (来自 procmail )并且永远记住那些脚本中的退出陷阱(sigspec == EXIT0 ,捕获特定信号是多余的)。

2009 年,我发布了我的可锁定脚本样板(最初在我的 wiki 页面上可用,现在以 gist 的形式提供)。将其转换为每个用户一个实例是微不足道的。使用它,您还可以轻松地为需要锁定或同步的其他场景编写脚本。

为了您的方便,这里是提到的样板。

 #!/bin/bash
# SPDX-License-Identifier: MIT

## Copyright (C) 2009 Przemyslaw Pawelczyk <przemoc@gmail.com>
##
## This script is licensed under the terms of the MIT license.
## https://opensource.org/licenses/MIT
#
# Lockable script boilerplate

### HEADER ###

LOCKFILE="/var/lock/`basename $0`"
LOCKFD=99

# PRIVATE
_lock()             { flock -$1 $LOCKFD; }
_no_more_locking()  { _lock u; _lock xn && rm -f $LOCKFILE; }
_prepare_locking()  { eval "exec $LOCKFD>\"$LOCKFILE\""; trap _no_more_locking EXIT; }

# ON START
_prepare_locking

# PUBLIC
exlock_now()        { _lock xn; }  # obtain an exclusive lock immediately or fail
exlock()            { _lock x; }   # obtain an exclusive lock
shlock()            { _lock s; }   # obtain a shared lock
unlock()            { _lock u; }   # drop a lock

### BEGIN OF SCRIPT ###

# Simplest example is avoiding running multiple instances of script.
exlock_now || exit 1

# Remember! Lock file is removed when one of the scripts exits and it is
#           the only script holding the lock or lock is not acquired at all.

原文由 przemoc 发布,翻译遵循 CC BY-SA 3.0 许可协议

推荐问题