1

我有一个主 shell 文件main.sh和许多后台子 shell 文件,所有这些文件都由执行调用。这些文件是a.sh, b.sh, c.sh...

我主要调用这些子shell文件,如下所示:

#main.sh
./a.sh &
./b.sh &
./c.sh &

在每个后台子shell文件中,格式如下

#a.sh
echo "This is a process"

子shell几乎相同,输出消息对于我的任务是必要的,但很难确定哪些消息对应于哪个子shell进程。我正在考虑为它们分配一个 PID,并将该 PID 附加到每个子外壳的消息输出中。如下所示:

[123]This is a process
[234]This is a process
...

谢谢!

编辑在 main.sh 中启用此功能而不是修改 subshel​​l 进程会很棒,因为我只想查看它们几次进行调试。

4

5 回答 5

2

该变量$$包含当前 PID。

echo "[$$]This is a process"
于 2013-11-04T19:35:12.750 回答
1

你为什么不直接启动它们呢?

./a.sh | sed 's/^/[a] /' &
./b.sh | sed 's/^/[b] /' &
./c.sh | sed 's/^/[c] /' &

或者即使你真的想包含 PID:

./a.sh | sed "s/^/[$!] /" &
./b.sh | sed "s/^/[$!] /" &
./c.sh | sed "s/^/[$!] /" &

应该管用。

于 2013-11-04T20:30:24.753 回答
0

您可以使用bash 协进程(需要 bash 4)来实现类似的目标。代码如下:

prepend_pid() {
    coproc "${@}"
    pid=${!}
    trap "kill ${pid}" EXIT
    sed -e "s:^:${pid} :" </dev/fd/${COPROC[0]}
}

prepend_pid ./a.sh &
prepend_pid ./b.sh &
prepend_pid ./c.sh &

这是因为您需要实现两个目标:

  1. 你需要先 fork 脚本才能知道它的 PID,
  2. 您需要在分叉之前重定向脚本输出。

协进程基本上是一个./a.sh &,但输入和输出重定向到匿名管道。管道 fds 放置在${COPROC[@]}数组中。如果您没有足够新的 bash,则可以改用命名管道。

这里做了什么:

  1. 您在协同进程中启动脚本。它的输出排队到尚未使用的管道。
  2. 您从 获取分叉的 PID ${!}
  3. 当阅读器终止时,您设置了一个陷阱来杀死生成的脚本。
  4. 您启动一个新的 sed 进程,该进程从 fd 的管道读取脚本输出${COPROC[0]}并将 pid 预先添加到它。

请注意,sed它本身会阻止脚本,因此您也需要分叉它。而且由于它需要访问管道,所以不能单独分叉。相反,我们 fork 整个函数。

陷阱确保在您终止生成的函数时将终止生成的脚本。多亏了这一点,您可以执行以下操作:

prepend_pid ./a.sh &
spid=$!
sleep 4
kill ${spid}

不用担心./a.sh会继续在后台运行而没有输出。

于 2013-11-04T20:49:40.590 回答
0

如果它不需要是实际的进程 ID,而只是一个唯一标识符,则可以设置一个已知的环境变量:

#main.sh
MY_ID=1 ./a.sh &
MY_ID=2 ./b.sh &
MY_ID=3 ./c.sh &

#a.sh
echo "[$MY_ID]This is a process"

bash4 或更高版本中,您可以使用 访问 shell 的进程 ID ,这样您在启动每个后台进程时$BASHPID就不需要指定 a 。MY_ID

#a.sh
echo "[$BASHPID]This is a process"

如果你想自动为每一行输出添加标识符,你需要定义一个包装器echo而不是直接使用它:

my_echo () { echo "[$MY_ID]$*"; }
my_echo () { echo "[$BASHPID]$*"; }
于 2013-11-04T20:00:55.793 回答
0

您可以创建一个名为“echo”的 bash 包装函数并将其导出,因此您的后台脚本使用此覆盖版本:

ubuntu@ubuntu:~$ cat bgscript
#!/bin/bash
对于 {1..3} 中的 i;做回声“i = $ i”;完毕

ubuntu@ubuntu:~$ function echo { 内置 echo "[$$]$@"; }
ubuntu@ubuntu:~$ export -f echo
ubuntu@ubuntu:~$ ./bgscript &
[1] 7290
ubuntu@ubuntu:~$ [7290]i=1
[7290]i=2
[7290]i=3

[1]+ 完成 ./bgscript
ubuntu@ubuntu:~$
于 2013-11-04T20:13:31.640 回答