如何打印我的脚本所属的完整管道?

时间:2012-02-21 19:18:23

标签: bash

使用echo "blah" | myscript作为示例管道,我正在寻找“myscript”中的方法:

echo "$SOME_BUILTIN"

其输出将是原始管道:

echo "blah" | myscript

有什么想法吗?

2 个答案:

答案 0 :(得分:1)

你走了:

#!/usr/bin/env bash

siblings=($(pgrep -P "$(ps -p $$ o ppid=)" | grep -Fvx $$))
pids=$$
sibling=$$

while true
do
    pid=$sibling
    for sibling in ${siblings[@]}
    do
        if [ "$(readlink "/proc/${sibling}/fd/1")" = "$(readlink "/proc/${pid}/fd/0")" ]
        then
            # Found previous pipe process
            pids="${sibling},${pids}"
            continue 2
        fi
    done
    break # No previous pipe process
done

while IFS= read -r line
do
    pipeline="${pipeline+${pipeline} | }$line"
done < <(ps --sort=pid -p "$pids" o args=)
printf '%s\n' "$pipeline"

示例:

$ ./test.sh
bash ./test.sh

$ cat /dev/zero | sleep 1 | ./test.sh
cat /dev/zero | sleep 1 | bash ./test.sh

使用小project来使其成为一个合适的工具。

答案 1 :(得分:0)

直接执行此操作并不容易,但您可以使用以下信息重新创建管道:

  • 您的脚本的PID位于$$ env变量
  • 使用ps -fe并查看第2列和第3列,您可以找到脚本的父级和父级的父级,依此类推。管道由一系列直接祖先组成,您可以按照路径向下处理PID 1(init过程或等效过程)。
  • 了解每个进程的PID,您可以从/proc/PID/cmdline获取其命令行(使用'\0'替换tr的空格,以获取人类可读的格式
  • 如果您知道脚本是从管道中调用的,那么基本上就完成了。如果您需要确定是从管道调用还是以交互方式调用它,您可能需要检查ls -lh /proc/self/fd/0打印的内容。那是第0个文件描述符,意思是stdin。如果它指向/dev/someting(如/dev/pts/XX),那么您可能是互动的。如果链接的目标以pipe:[开头,则可能是您正在从管道接收数据(它也可能是网络套接字,但希望您可以在设置中将此情况排除在外)。