2

可能重复:
确保一次只运行一个 shell 脚本实例的快捷方式

我是 shell 脚本的新手。

我想做的是避免运行脚本的多个实例。

我有这个 shell 脚本 cntps.sh

#!/bin/bash
cnt=`ps -e|grep "cntps"|grep -v "grep"`
echo $cnt >> ~/cntps.log
if [ $cnt < 1 ];
then 
    #do something.
else
    exit 0
fi

如果我以这种方式运行它$./cntps.sh,它会回显 2

如果我以这种方式运行它$. ./cntps.sh,它会回显 0

如果我用 运行它crontab,它会回显 3

有人可以向我解释为什么会这样吗?避免运行多个脚本实例的正确方法是什么?

4

3 回答 3

2

我稍微更改了您的命令以输出ps到日志文件,这样我们就可以看到发生了什么。

cnt=`ps -ef| tee log | grep "cntps"|grep -v "grep" | wc -l`

这是我看到的:

32427 -bash
  20430 /bin/bash ./cntps.sh
    20431 /bin/bash ./cntps.sh
      20432 ps -ef
      20433 tee log
      20434 grep cntps
      20435 grep -v grep
      20436 wc -l

如您所见,我的终端的 shell (32427) 生成了一个新的 shell (20430) 来运行脚本。然后该脚本生成另一个子 shell (20431) 用于命令替换 ( `ps -ef | ...`)。

所以,两个的计数是由于:

  20430 /bin/bash ./cntps.sh
    20431 /bin/bash ./cntps.sh

在任何情况下,这都不是确保只有一个进程在运行的好方法。请参阅此SO 问题

于 2012-11-01T10:31:53.697 回答
1

首先,我建议使用pgrep而不是这种方法。其次,我认为您缺少 awc -l来计算脚本中的实例数

回答您的计数问题:

如果我以这种方式运行它$./cntps.sh,它会回响2

这是因为反引号调用:ps -e ...正在触发一个子shell,该子shell也被调用cntps.sh,这会触发两个项目

如果我以这种方式运行它$. ./cntps.sh,它会回响0

这是因为您没有运行,而是实际上将其采购到当前运行的 shell 中。这会导致没有以该名称运行的脚本副本cntps

如果我运行它crontab,它会回显3

两个来自调用,一个来自产生的 crontab 调用本身sh -c 'path/to/cntps.sh'

请参阅此问题以了解如何执行单实例 shell 脚本。

于 2012-11-01T10:18:59.187 回答
0

使用“锁定”文件作为互斥锁。

if(exists("lock") == false)
{
    touch lock file // create a file named "lock" in the current dir
    execute_script_body // execute script commands
    remove lock file // delete the file
}
else
{
    echo "another instance is running!"
}

exit
于 2012-11-01T10:39:26.610 回答