通过后台 shell 函数获取子进程列表

通过后台 shell 函数获取子进程列表

我有一个 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)而不是在第一次运行中。

相关内容