脚本的单个实例,但仅具有相同的参数

脚本的单个实例,但仅具有相同的参数

我这里有一段漂亮的小代码,如果有另一个脚本实例正在运行,它将从脚本中退出:

single_instance(){
    if pidof -x "${0##*/}" -o %PPID >/dev/null; then
        exit 0
    fi
}

但我正在寻找的是一个只有在脚本被执行时才会退出的函数使用相同的参数调用

我知道我可以通过解决方案破解我的方式cat | grep | awk | cut | sed | tac | sort | uniq,但我想知道是否有一种简单的方法可以使用 、 等实用程序来实现此pidof目的ps

你会怎样做呢?

答案1

你可以这样做:

#!/bin/bash

single_instance() {

   pid=$(pidof -x "${0##*/}" -o %PPID)

   if [[ $(xargs -0 < /proc/$pid/cmdline) == $@ ]]
   then
       echo QUITTING
       exit 1
   fi
}

single_instance $(xargs -0 < /proc/$$/cmdline)

while :
do
    sleep 10
done

答案2

man ps我在研究并添加@goldilocks 的一些代码后想到了这个。它在处理带有空格的参数方面做得很好,并且如果脚本被调用为bash scriptname

single_instance(){
    if ps -efww | grep "$(ps -o cmd= -p $$)$" | grep -vq " $$ "; then
        exit 0
    fi
}

答案3

fn() { IFS='
';  set -- $(ps -o args= -C "${0##*/}")
    unset IFS
    [ $(($(printf $(printf %s\\n "$@" | sort | uniq -c | sort -rn)))) -gt 1 ] &&
        exit 0
}

exit 0如果当前正在运行两个或多个$0使用相同参数调用的进程,则会出现这种情况。

答案4

使用/进程:

single_instance(){

   local tl=$(cat /proc/$$/cmdline)
   local l

   tl=${tl##*/}

   for pid in $(pidof -x "${0##*/}" -o %%PPID); do
        l=$(cat /proc/$pid/cmdline)
        if [ ${l##*/} = $tl ]; then
            echo "already running..."
            exit 0
        fi
    done
}

它在没有启动路径的情况下对命令行进行精确比较(就像您在脚本中所做的那样)。这些/proc/*/cmdline值中没有任何空格,因此您可以直接比较它们。如果参数顺序发生变化,它不会注意到。

相关内容