【问题标题】:How to check in a bash script if something is running and exit if it is如何检查 bash 脚本是否正在运行并退出
【发布时间】:2009-05-29 17:04:36
【问题描述】:

我有一个脚本,每 15 分钟运行一次,但有时如果盒子很忙,它会挂起,下一个过程将在第一个过程完成创建雪球效果之前开始。如何在 bash 脚本中添加几行代码,以检查是否在开始之前先运行某些内容?

【问题讨论】:

标签: bash scripting


【解决方案1】:

如果你知道进程名,你可以使用pidof -x,如果你知道PID,你可以使用kill -0

例子:

if pidof -x vim > /dev/null
then
    echo "Vim already running"
    exit 1
fi

【讨论】:

  • 如果您正在检查脚本,请确保使用 -x 标志,否则您将无法找到匹配项,因为它将寻找“bash”
【解决方案2】:

为什么不设置锁定文件?

有点像

yourapp.lock

处理完成后将其删除,并在启动前检查它。

可以使用

if [ -f yourapp.lock ]; then
echo "The process is already launched, please wait..."
fi

【讨论】:

  • 因为正确管理锁定文件,特别是处理进程不正确退出并且未能清除其锁定文件的情况,在 bash 中需要多于几行。
  • 如果使用flock,锁文件很容易管理——但是是的,使用-f来测试它们的存在是邪恶和错误的。
【解决方案3】:

代替 pidfile,只要您的脚本有一个唯一可识别的名称,您就可以执行以下操作:

#!/bin/bash
COMMAND=$0
# exit if I am already running
RUNNING=`ps --no-headers -C${COMMAND} | wc -l`
if [ ${RUNNING} -gt 1 ]; then
  echo "Previous ${COMMAND} is still running."
  exit 1
fi
... rest of script ...

【讨论】:

  • 我做了这个,我不得不稍微调整一下。首先,COMMAND 包含完整路径,因此除非您从同一个目录运行它,否则它不起作用。无论如何,我硬编码了这个名字。其次,出于某种原因 ps --no-headers -C${COMMAND} | wc -l 总是返回 1 而没有运行,因为这个脚本在检查另一个 1 时正在运行,所以它总是返回 2。我不得不将 -gt 1 更改为 -gt 2 并且它工作。谢谢。
【解决方案4】:
pgrep -f yourscript >/dev/null && exit

【讨论】:

  • pkill -0 yourscript 可能会更好
【解决方案5】:

这就是我在一项 cron 工作中的做法

lockfile=~/myproc.lock
minutes=60
if [ -f "$lockfile" ]
then
  filestr=`find $lockfile -mmin +$minutes -print`
  if [ "$filestr" = "" ]; then
    echo "Lockfile is not older than $minutes minutes! Another $0 running. Exiting ..."
    exit 1
  else
    echo "Lockfile is older than $minutes minutes, ignoring it!"
    rm $lockfile
  fi
fi

echo "Creating lockfile $lockfile"
touch $lockfile

并在脚本末尾删除锁定文件

echo "Removing lock $lockfile ..."
rm $lockfile

【讨论】:

    【解决方案6】:

    【讨论】:

      【解决方案7】:

      我最近有同样的问题,从上面发现 kill -0 最适合我的情况:

      echo "Starting process..."
      run-process > $OUTPUT &
      pid=$!
      echo "Process started pid=$pid"
      while true; do
          kill -0 $pid 2> /dev/null || { echo "Process exit detected"; break; }
          sleep 1
      done
      echo "Done."
      

      【讨论】:

        【解决方案8】:

        为了扩展@bgy 所说的内容,如果锁文件尚不存在则创建一个锁文件,如果不存在则失败的安全原子方法是创建一个临时文件,然后将其硬链接到标准锁定文件。这可以防止在您测试文件和创建文件之间创建文件的另一个进程。

        这是我的每小时备份脚本中的锁定文件代码:

        echo $$ > /tmp/lock.$$
        if ! ln /tmp/lock.$$ /tmp/lock ; then 
                echo "previous backup in process"
                rm /tmp/lock.$$
                exit
        fi
        

        完成后不要忘记删除锁定文件和临时文件,即使您因错误而提前退出。

        【讨论】:

          【解决方案9】:

          使用这个脚本:

          FILE="/tmp/my_file"
          if [ -f "$FILE" ]; then
             echo "Still running"
             exit
          fi
          trap EXIT "rm -f $FILE"
          touch $FILE
          
          ...script here...
          

          此脚本将创建一个文件并在退出时将其删除。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2023-01-16
            • 1970-01-01
            • 2013-09-07
            • 2019-03-10
            • 2010-10-21
            相关资源
            最近更新 更多