我有一个 bash 脚本,在其中我在后台调用函数:
process_manager $1 $2 $3 &
该函数运行/执行在后台作为参数传递的命令。
如何在函数 process_manager 中获取子进程列表?
我尝试这样做:
process_manager () {
count=$1
interval=$2
cmd=$3
bash_pid=$$
last_pid=$!
echo "bash_pid: $bash_pid, ppid: $PPID, last_pid: $last_pid"
$cmd &
$cmd &
sleep 30 &
}
process_manager $1 $2 $3 &
process_manager $1 $2 $3 &
process_manager $1 $2 $3 &
但这里函数process_manager不会显示$!或第一次调用时的 $last_pid 。
在这种情况下我应该如何获取 $last_pid 并能够访问子进程列表?
答案1
$$
包含 shell 的 pid被处决来解释脚本。该 shell 的每个子 shell 中都是相同的。
$!
包含在后台运行的最后一个子命令的 pid(使用&
或 coproc 或进程替换)
在后台运行的命令中,$!
它没有设置。$!
是为父进程准备的,这样它就可以等待或杀死它的孩子。
bash
有一个$BASHPID
包含 pid 的变量当前子shell。
并不总是清楚它是什么过程。
在:
echo "$BASHPID"
它是解释该命令的进程的 pid echo
,但在
/bin/echo "$BASHPID"
它确实分叉了一个进程,但$BASHPID
不报告该分叉进程的 pid,而是报告父进程的 pid。而在:
/bin/echo "$BASHPID" &
(唯一的区别是父进程不等待其子进程),$BASHPID
报告分叉进程的 pid:
$ bash -c 'echo "$$"; echo "$BASHPID"; /bin/echo "$BASHPID"; /bin/echo $BASHPID &'
3264
3264
3264
3266
但就您而言,您可以安全地执行以下操作:
process_manager () {
pid_of_last_command_run_in_background=$!
mypid=$BASHPID
cmd &
cmd1pid=$!
cmd &
cmd2pid=$!
}
$pid_of_last_command_run_in_background
将是在后台运行的最后一个命令的 pid(由当前子 shell 或其父级或其祖级)。这就是为什么你$last_pid
在第二次运行中得到一些东西(前一个 process_manager 的 pid)而不是在第一次运行中。