如果调用了另一个实例,请重新运行bash脚本 [英] Re-run bash script if another instance was invoked

查看:43
本文介绍了如果调用了另一个实例,请重新运行bash脚本的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个bash脚本,可以同时调用多次.为了保护脚本访问的状态信息(保存在/tmp 文件中),我正在使用文件锁定,如下所示:

I have a bash script that may be invoked multiple times simultaneously. To protect the state information (saved in a /tmp file) that the script accesses, I am using file locking like this:

do_something()
{
...
}

// Check if there are any other instances of the script; if so exit
exec 8>$LOCK
if ! flock -n -x 8; then
        exit 1
fi

// script does something...
do_something

现在,此脚本运行时调用的任何其他实例都将退出.如果要同时执行n次而不是n次调用,我希望脚本仅额外运行一次,如下所示:

Now any other instance that was invoked when this script was running exits. I want the script to run only one extra time if there were n simultaneous invocations, not n-times, something like this:

do_something()
{
...
}

// Check if there are any other instances of the script; if so exit
    exec 8>$LOCK
    if ! flock -n -x 8; then
        exit 1
    fi

// script does something...
do_something

// check if another instance was invoked, if so re-run do_something again
    if [ condition ]; then
       do_something
    fi

我该如何去做?退出前先触摸羊群内部的文件,然后将该文件作为第二个文件的条件,看来似乎行不通.

How can I go about doing this? Touching a file inside the flock before quitting and having that file as the condition for the second if doesn't seem to work.

推荐答案

它们并不是所有人的最爱,但由于它们是原子性的,所以我一直非常喜欢用于创建锁文件的符号链接.例如:

They're not everone's favourite, but I've always been a fan of symbolic links to make lockfiles, since they're atomic. For example:

lockfile=/var/run/`basename $0`.lock
if ! ln -s "pid=$$ when=`date '+%s'` status=$something" "$lockfile"; then
  echo "Can't set lock." >&2
  exit 1
fi

通过将有用的信息直接编码到链接目标中,可以消除写入文件时引入的竞争条件.

By encoding useful information directly into the link target, you eliminate the race condition introduced by writing to files.

也就是说,Dennis发布的链接提供了更多有用的信息,在编写更多脚本之前,您可能应该尝试理解这些信息.上面的示例与 BashFAQ/045 有关,它建议对做类似的事情mkdir .

That said, the link that Dennis posted provides much more useful information that you should probably try to understand before writing much more of your script. My example above is sort of related to BashFAQ/045 which suggests doing a similar thing with mkdir.

如果我正确理解了您的问题,则可以通过使用两个锁定文件来实现(略微不可靠)您想要做的事情.如果设置第一个锁失败,我们尝试第二个锁.如果设置第二个锁失败,则退出.如果第一个锁在我们检查之后但在检查第二个现有锁之前被删除,则存在错误.如果您可以接受此错误级别,那就太好了.

If I understand your question correctly, then what you want to do might be achieved (slightly unreliably) by using two lock files. If setting the first lock fails, we try the second lock. If setting the second lock fails, we exit. The error exists if the first lock is delete after we check it but before check the second existant lock. If this level of error is acceptable to you, that's great.

这是未经测试的;但是在我看来,这是合理的.

This is untested; but it looks reasonable to me.

#!/usr/local/bin/bash

lockbase="/tmp/test.lock"

setlock() {
  if ln -s "pid=$$" "$lockbase".$1 2>/dev/null; then
    trap "rm \"$lockbase\".$1" 0 1 2 5 15
  else
    return 1
  fi
}

if setlock 1 || setlock 2; then
  echo "I'm in!"
  do_something_amazing
else
  echo "No lock - aborting."
fi

这篇关于如果调用了另一个实例,请重新运行bash脚本的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆