我试图找出程序/脚本的输出是否被传递给 eval,尤其是在 bash 脚本中。
例如,我可以区分:
$ ./program.sh
从
$ eval "$(./program.sh)"
在program.sh内?后者将打印要评估的环境变量,而第一个则不会。
这将使我免于开发./program.sh print-env
用于传递到 eval 的程序。
另一方面,我可以看到,有了这种可能,就有可能编写出在输出传递到eval
.想法?
答案1
在:
eval "$(./program.sh)"
shell 将./program.sh
在其标准输出重定向到管道的情况下运行,并在管道的另一端读取内存中的输出。然后,一旦./program/sh
消失(导致在该管道上看到 eof,并且随后wait()
由进程上的大多数 shell 完成返回),保存的内容减去尾随换行符将被传递到eval
.
因此,为了./program.sh
检测这种情况,需要:
- 检测到它的标准输出是一个管道。这很容易。在 Linux 上,可以使用
[ -p /dev/stdout ]
. - 这是一个在管道另一端读取数据的 shell 进程。这变得更加复杂。在使用最近的 Linux 上
lsof
,您可以在 的输出中查找lsof +E -Fca -ap "$$" -d 1
名称以sh
该结尾的进程,该进程打开了管道以读取大于 10 的 fd。 - 然后您需要确定该 shell 进程当前正在解释
eval something
命令行。为此,您可能需要将调试器附加到该 shell 并了解该特定 shell 的内部数据结构,以查看它实际运行的命令。
简而言之,你不能。但也许您可以满足于在输出进入 tty 时和不进入 tty 时提供不同的输出,这应该只是一个问题:
if [ -t 1 ]; then
echo output for tty
else
echo output for something else
fi