获取生成管道数据的命令

获取生成管道数据的命令

我想找出一种方法来访问描述当前命令运行之前运行的命令的字符串。

例如,如果我运行:

ls | myscripthere

我希望能够知道“ls”命令是生成我通过 STDIN 获得的输出的命令。有什么办法可以做到这一点吗?

谢谢

答案1

管道接收端的程序实际上没有办法知道传入数据的来源是什么。使用你的例子:

$ ls | myscript

的标准输出ls将被重定向到 的标准输入myscript。然而,这与以下内容完全没有区别:

$ ls > datafile
$ myscript < datafile

或者

$ ls > datafile
$ cat datafile | myscript

或者

$ wget -o - https://www.example.com/some/file/that/resembles/the/output/of/ls | myscript

或者

$ ls | sed '/secrethiddenfile/d' | myscript

甚至

$ cat - | myscript

文字只是文字。

答案2

你可以这样做:

echo 'ls' | read var;echo $var > var_file;$var | myscript

它将把命令的值写入文件中var_file

echo 'ls'ls作为字符串输入给出,并且 的值var将变为ls$var将扩展为ls并将其输出通过管道提供给myscript

如果您有多个命令并希望在 中逐行获取它们var_file,则替换>>>ie:

echo 'ls' | read var;echo $var >> var_file;$var | myscript

答案3

一般来说,这是不可能的,因为:

管道中的每个命令都在其自己的子 shell 中执行

(来自bash手册)。

如果发送命令持续的时间足够长,您就有机会找到它。下面是一个“接收者”脚本示例;它从中获取lsof与接收器的 stdin 相对应的NODE 列,然后lsof在更广泛的输出中搜索 stdout NODE 匹配的进程:

#!/bin/sh
# look for f0 and get its node
node=$(lsof -p "$$" -Ffi | awk '/^p/ { node=""; } /^f0$/ { getline; node=substr($0, 2); exit; } END { print node }')

# run lsof and get the pid(s) with f1 whose node match $node
lsof -Ffci | awk -v node="$node" '
  /^c/ { procname=substr($0, 2); }
  /^f1$/ { getline; thisnode=substr($0, 2); }
  /^p/ { if (procname != "" && thisnode == node) { print procname; procname=""; thisnode=""; } }
  END { if (procname != ""&& thisnode == node) print procname; }
  '
cat

答案4

我在我的程序中使用这个函数.bash_aliases来提供一个类似于 Tee 的工具:

function teee { 
#This can be used between pipes to print on screen what is coming in from the left command and flows to the next command
        v="$(</dev/stdin)"; 
        echo '---------------- pipe entry-------------' >/dev/tty;
        while read -r l;do 
          echo "$l" >/dev/tty;
        done <<<"$v";
        echo '---------------- pipe exit-------------' >/dev/tty;
        echo "$v"; ##echo to pipe buffer - necessary to keep the data flow to the next command
                }

测试:

cat file11
1
2
3
8
9

cat file11 |sed 's/3//' |teee |sed 's/1//'
---------------- pipe entry-------------
1
2

8
9
---------------- pipe exit-------------

2

8
9

在您的情况下,您可以将所有内容替换>/dev/tty>logfile脚本内的内容。

相关内容