好吧,这可能是一个非常愚蠢的问题,而且我不经常编写 shell 脚本。我试图在后台启动 3 个进程,在 shell 脚本中一个接一个地启动,例如:
#!/bin/sh
PROCESS1 &
PROCESS2 &
PROCESS3 &
问题就在这里。我需要按照所示的相同顺序启动这些进程。此外,PROCESS2 的 PID 需要作为命令行参数传递给 PROCESS3。所有这些进程都在无限循环中运行,并且在 3 个独立的终端中运行时,它们确实可以顺利运行。
我试过:
#!/bin/sh
PROCESS1 &
PROCESS2 &
PID_PROCESS2=$!
PROCESS3 ${PID_PROCESS2} &
这将启动 PROCESS1 和 PROCESS3,但 PROCESS2 立即退出,不会打印任何错误。它就这样消失了。 ps 命令没有显示 PROCESS2 的痕迹。打印 PID_PROCESS2 返回某个值“p”,并且 PROCESS3 使用值“p”作为其参数运行得很好。我有什么问题和不足吗?
可能重要的细节
在上面的示例中,我使用限定路径来调用相应的进程,它们都是本机二进制文件并且位于同一目录中。例如,
#!/bin/sh /usr/bin/PROCESS1 &
ps 的输出如上所述,
$ps | grep "/path/to/PROCESS" 10064 root 16536 S /path/to/PROCESS1 10066 root 11084 S /path/to/PROCESS3 10065
它清楚地告诉 PROCESS2 已启动但由于某种未知原因退出。
PROCESS2 通过 FIFO(命名管道)与 PROCESS1 进行通信,这是一种单向通信。
解决方法
#/bin/sh
/path/to/PROCESS1 &
/path/to/PROCESS2 & PROCESS2_PID=$!
export P2PID=${PROCESS2_PID}
sh -c "/path/to/PROCESS3 ${P2PID}"
这似乎为 sh 增加了一个额外的进程来完成这项工作。
$ps | grep "/path/to/PROCESS"
10174 root 16536 R /path/to/PROCESS1
10175 root 71720 S /path/to/PROCESS2
10177 root 27772 S sh -c /path/to/PROCESS3 10175
10076 root 11084 S /path/to/PROCESS3 100175
但我仍然不知道为什么会这样。有人可以建议在这种情况下发生了什么样的“魔法”吗?
答案1
根据您的描述,听起来 PROCESS2 存在根本性错误,导致其退出。如果我用 3 个进程对您所描述的内容进行建模,那么当您在后台运行 3 个进程,然后捕获第 2 个进程的 PID 并将其传递给进程 3 时,它基本上会按照预期工作。
例子
示例脚本$ cat runny.bash
#!/bin/bash
proc3func() {
echo $1
sleep 7 &
}
sleep 9 &
sleep 8 &
PID2=$!
proc3func ${PID2} &
示例运行
$ ./runny.bash ; sleep 2; ps -eaf
4279
UID PID PPID C STIME TTY TIME CMD
...
vagrant 4278 1 0 20:21 pts/1 00:00:00 sleep 9
vagrant 4279 1 0 20:21 pts/1 00:00:00 sleep 8
vagrant 4282 1 0 20:21 pts/1 00:00:00 sleep 7
在上面的输出中,我们可以看到 PID 4279 被回显到屏幕上,后面的输出ps -eaf
显示了我们的 3 个进程。
调试
我建议启用set -x
,以便您可以在运行脚本时遵循正在执行的命令或像这样运行它:
$ bash -x ./runny.bash
+ PID2=4612
+ sleep 9
+ sleep 8
+ proc3func 4612
+ echo 4612
4612
+ sleep 7