如何将程序的 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