使用pgrep确定进程是否正在运行

时间:2012-02-01 23:19:39

标签: bash shell grep

我有一个脚本,我只想运行一次。如果脚本第二次被调用,我会检查它是否存在锁定文件。如果锁存文件存在,那么我想查看进程是否实际运行。

我一直在搞乱pgrep,但没有得到预期的结果:

#!/bin/bash
COUNT=$(pgrep $(basename $0) | wc -l)
PSTREE=$(pgrep $(basename $0) ; pstree -p $$)
echo "###"
echo $COUNT
echo $PSTREE
echo "###"
echo "$(basename $0) :" `pgrep -d, $(basename $0)`
echo sleeping.....
sleep 10

我得到的结果是:

$ ./test.sh  
###
2
2581 2587 test.sh(2581)---test.sh(2587)---pstree(2591)
###
test.sh : 2581
sleeping.....

我不明白为什么只有一个进程实际运行时我得到“2”。

有什么想法吗?我确定这就是我打电话的方式。我已经尝试了许多不同的组合,似乎无法弄明白。

解决方案:

我最终做的是这样做(我的部分内容):

function check_lockfile {
    # Check for previous lockfiles

    if [ -e $LOCKFILE ] 
    then
        echo "Lockfile $LOCKFILE already exists.  Checking to see if process is actually running...." >> $LOGFILE 2>&1
        # is it running?
        if [ $(ps -elf | grep $(cat $LOCKFILE) | grep $(basename $0) | wc -l) -gt 0 ]
        then
            abort "ERROR! - Process is already running at PID: $(cat $LOCKFILE).  Exitting..."
        else
            echo "Process is not running.  Removing $LOCKFILE" >> $LOGFILE 2>&1
            rm -f $LOCKFILE
        fi
    else
        echo "Lockfile $LOCKFILE does not exist." >> $LOGFILE 2>&1
    fi
}

function create_lockfile {
    # Check for previous lockfile
    check_lockfile

    #Create lockfile with the contents of the PID
    echo "Creating lockfile with PID:" $$ >> $LOGFILE 2>&1
    echo -n $$ > $LOCKFILE
    echo "" >> $LOGFILE 2>&1
}

# Acquire lock file
create_lockfile >> $LOGFILE 2>&1 \
|| echo "ERROR! - Failed to acquire lock!"

3 个答案:

答案 0 :(得分:3)

pgrep的参数是扩展的正则表达式模式。 在您的情况下,命令pgrep $(basename $0)将评估为pgrep test.sh,其匹配任何具有test后跟任何字符且最后跟sh的进程匹配}。所以它会与btest8shatest_shell等匹配。

您应该创建一个锁文件。如果锁定文件存在,程序应该退出。

lock=$(basename $0).lock
if [ -e $lock ] 
then 
    echo Process is already running with PID=`cat $lock`
    exit
else
    echo $$ > $lock
fi

答案 1 :(得分:0)

您已打开锁定文件。用它来让你的生活更轻松。

将进程ID写入锁定文件。当您看到锁定文件存在时,请阅读它以查看它应该锁定的进程ID,并检查该进程是否仍在运行。

然后在版本2中,您还可以编写程序名称,程序参数,程序启动时间等,以防止新进程以相同的进程ID启动。

答案 2 :(得分:0)

将它放在脚本顶部附近......

pid=$$
script=$(basename $0)
guard="/tmp/$script-$(id -nu).pid"
if test -f $guard ; then
    echo >&2 "ERROR: Script already runs... own PID=$pid"
    ps auxw | grep $script | grep -v grep >&2
    exit 1
fi
trap "rm -f $guard" EXIT
echo $pid >$guard

是的,测试命令和echo命令之间有一个竞争条件的小窗口,可以通过附加到保护文件来修复,然后检查第一行确实是我们自己的PID。此外,if中的诊断输出可以在生产版本中注释掉。