我有一个主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进程。我正在考虑为它们分配一个PID,并将该PID添加到每个子shell的消息输出中。 这看起来如下:
[123]This is a process
[234]This is a process
...
谢谢!
编辑在main.sh中启用此功能会很棒,而不是修改子shell进程,因为我只想看一些它们进行调试。
答案 0 :(得分:2)
变量$$
包含当前PID。
echo "[$$]This is a process"
答案 1 :(得分: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/^/[$!] /" &
应该有用。
答案 2 :(得分: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"
在bash
4或更高版本中,您可以使用$BASHPID
访问shell的进程ID,以便您
启动每个后台进程时不需要指定MY_ID
。
#a.sh
echo "[$BASHPID]This is a process"
如果要使用标识符自动添加每行输出,则需要为echo
定义包装器,而不是直接使用它:
my_echo () { echo "[$MY_ID]$*"; }
my_echo () { echo "[$BASHPID]$*"; }
答案 3 :(得分:0)
您可以创建一个名为“echo”的bash包装函数并将其导出,因此您的后台脚本使用此覆盖版本:
ubuntu@ubuntu:~$ cat bgscript #!/bin/bash for i in {1..3}; do echo "i=$i"; done ubuntu@ubuntu:~$ function echo { builtin echo "[$$]$@"; } ubuntu@ubuntu:~$ export -f echo ubuntu@ubuntu:~$ ./bgscript & [1] 7290 ubuntu@ubuntu:~$ [7290]i=1 [7290]i=2 [7290]i=3 [1]+ Done ./bgscript ubuntu@ubuntu:~$
答案 4 :(得分:0)
你可以使用bash coprocesses来实现这样的目标(需要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 &
这是因为你需要实现两个目标:
协处理基本上是./a.sh &
,但输入和输出重定向到匿名管道。管道fds放在${COPROC[@]}
数组中。如果你没有足够新的bash,你可以使用命名管道。
这里做了什么:
${!}
获得分叉PID。${COPROC[0]}
的管道读取脚本输出,并将pid添加到它。请注意sed
本身会阻止脚本,因此您也需要对其进行分叉。并且因为它需要访问管道,所以不能单独分叉。相反,我们分叉整个函数。
陷阱确保在您终止衍生函数时生成的脚本将被终止。多亏了这一点,你可以做类似的事情:
prepend_pid ./a.sh &
spid=$!
sleep 4
kill ${spid}
不用担心./a.sh
会在没有输出的情况下继续在后台运行。