bash: 转储 parent 调用树

bash: Dump a parent call tree

我正在寻找一个递归 Makefile,我希望看到完整的调用树,它让我到达我所在的位置(包括所有参数等)。我不关心系统上的其他进程。

我要找的本质上是pstree -ha,它只输出突出显示的部分(加上当前进程)。请注意 pstree -ha <PID> 不起作用,因为它出于某种原因不显示 parent 的 parent(它不会一直到 init)。我找到了另一个 SO 答案 ps -f -g$BINOSPID,但它显示了我不想要的兄弟姐妹。

说出我要找的东西:我想要的是这个:

~> sh 
sh-4.1$ bash
~> pstree -?? $$

init
`- sshd
   `- bash
      `- sh
         `- bash
            `- pstree -?? 1402

此外,作为附带问题,pstree -ha 会在参数列表过长时自动截断它。有没有办法避免这种情况?

在原生 bash 中实现,具体取决于具有 procfs 的操作系统:

#!/usr/bin/env bash

pid=${1:-${BASHPID:-$$}}
while (( pid )); do
   mutated=0
   cmdline=( )
   while IFS= read -r -d '' piece || { [[ $piece ]] && mutated=1; }; do
       cmdline+=( "$piece" )
   done <"/proc/$pid/cmdline"
   printf '%s\t' "$pid"
   if (( mutated )); then
     printf '%s ' "${cmdline[@]}"
   else
     printf '%q ' "${cmdline[@]}"
   fi
   printf '\n'
   stat_data=$(<"/proc/$pid/stat") || break
   read _ ppid _ <<<"${stat_data##*')'}" || break
   [[ $ppid = "$pid" ]] && break
   pid=$ppid
done

如果 cmdline 不以 NUL 分隔符结尾,则设置 mutated 标志。这意味着命令行已被 运行 的程序修改,不再包含其原始值。 OpenSSH 特别倾向于这样做。在那种情况下,与其将命令行视为以 NUL 分隔的文字参数列表(并转义这些文字以生成可以复制和粘贴以在调用时生成相同命令的输出),不如将其视为已格式化以供人类阅读。

我们正在分析 "${stat_data##*')'}" 脱离偏执狂,以防止在其可执行文件名称中包含文字空格或 ) 字符的应用程序摆脱对 /proc/$pid/stat 的解释。