如何精确运行程序的 1 个实例。或者如何测试特定正在运行的程序

如何精确运行程序的 1 个实例。或者如何测试特定正在运行的程序

如何将程序的 1 个实例作为进程运行?或者,如何测试正在运行的程序是否存在?

便携式方法是优选的。

答案1

人们可以测试一个(命名)管道的可写性,并且通过适当的编程来测试正在运行的程序实例的存在。

假设我们保留一个文件名/tmp/fifo-myapp作为 FIFO 文件的名称(它应该为每个不同的应用程序定制;它通常驻留在一些特定于应用程序的文件夹并被指定为绝对路径):

文件1:test-wr-fifo

#!/bin/sh
# invocation: test-wr-fifo <timeout>

timeout="${1:=3}"

if ! [ -p "/tmp/fifo-myapp" ] ; then
    rm -f "/tmp/fifo-myapp"
    mkfifo "/tmp/fifo-myapp"
fi

{ sleep "$timeout" ; kill -s 0 $$ && kill -s TERM $$ ; } &
exec 3>"/tmp/fifo-myapp"

当 fifo 未打开且已达到指定超时时,该程序将以不成功状态退出。

文件2:single-inst-prog

#!/bin/sh

exec 3<"/tmp/fifo-myapp"

### Application Code ###

这是我们只需要 1 个实例的程序。

调用single-inst-prog

./test-wr-fifo || ./single-inst-prog &

此方法之所以有效,是因为打开 FIFO 的一端会阻塞(当 O_NONBLOCK 清零时),直到另一端也打开为止;此方法也有效,因为我们没有从 FIFO 读取任何数据或向 FIFO 写入任何数据,因此 EOF 条件和 SIGPIPE 永远不会发出信号。

答案2

我总是对锁定文件的竞争条件保持警惕,因此我使用特定的命名文件,并使用它,mv因为它是原子的。

通常,该进程使用永久文件名,例如/tmp/locks/myProcess.lock.任何想要获取锁的进程都会尝试将名称更改为/tmp/locks/myProcess.lock.myPID(用于mv(1)shell 和rename(2)C)。然后它可以检查其私有名称现在是否存在。如果没有,它会根据需要循环/睡眠。

如果小心的话,进程可以将日志附加到锁定文件:何时首次尝试锁定、何时成功、何时释放。

显然,它必须记住第一次尝试的时间,因为它只能在成功后记录。它还可以监视过度延迟并发出调查警报(可能是另一个进程副本失败,并且没有 onExit 来释放锁)。

答案3

这是一个 xmessage 的示例。不确定这是否适合您,但您可以尝试一下。

#!/bin/sh
xmessage 'hello this is the first xmessage' &
last=$(ps -a | grep '[ ]xmessage$' | awk '{print $1}')
sleep 1
if test $(($(date +%s) % 2)) -eq 0
  then
    kill $last
fi
sleep 1
if ! ps -p $last >/dev/null
  then
    xmessage 'Hi, this is the second xmessage. Visible only if the first is close!' &
fi

相关内容