在 bash shell 中重定向流 - 如何在 shell 命令行的其余部分上设置无条件

在 bash shell 中重定向流 - 如何在 shell 命令行的其余部分上设置无条件

我注意到apt在 Bash shell 中单独执行时和输出重定向到文件时输出是不同的。

例如:

$ apt install ./*.deb --simulate 1>111.txt 2>222.txt

在流 2 的文件中添加重定向结果文本WARNING: apt does not have a stable CLI interface. Use with caution in scripts.,而运行 apt w/out 重定向不会在 shell 窗口中显示此文本。

为什么输出取决于重定向?也许apt将重定向视为其参数?如何编写重定向以使 shell 命令行的其他部分不被注意到?

PS 我在 Ubuntu 18 中看到了它,并且apt是特定的应用程序,但也许这个问题对于 Unix 来说是普遍的,所以我只把它放在shell标签中。

答案1

apt历史上设计时就考虑到了交互式命令行的使用,因此出现了编码警告,这是有意在 shell 中/由 shell 完成的apt,而不是由 shell 完成的。

然而,apt不一定是解析命令行; shell 在调用 时已经完成了这项工作apt。正在apt做的是检测stdout流是否已更改/重定向。

至于apt在脚本中使用,您已经获得了类似的旧命令apt-get,它或多或少执行相同的操作,并且在stdout重定向时不会发出警告。

TLDR 不是在 中写入错误消息的 shell stderr,而是apt命令。

事实上,您能够apt stderr在 shell 中捕获输出是 Unix 作为多任务操作系统的产物,并不意味着它是 shell 生成该输出。

附言。对命令进行 strace,可以看到apt写入该消息:

strace apt get install bash > a
....
write(2, "\n", 1
)                       = 1
write(2, "WARNING: ", 9WARNING: )                = 9
write(2, "apt", 3apt)                      = 3
write(2, " ", 1 )                        = 1
write(2, "does not have a stable CLI inter"..., 38does not have a stable CLI interface. ) = 38
write(2, "Use with caution in scripts.", 28Use with caution in scripts.) = 28
write(2, "\n", 1
)                       = 1
write(2, "\n", 1
)                       = 1

答案2

“如何编写重定向以使 shell 命令行的其他部分不被注意到?”

您不必执行任何操作,警告位于 stdErr 上。尝试这个:

apt list adghdgd | grep .
2>/dev/null apt list adghdgd | grep .

如果您的发行版默认为 grep 着色,您将看到实际进入 grep 的部分被着色。在第二种形式中,stdErr 被完全抑制。

Grep 的行为也不同,比较一下:

echo hello | grep .
echo hello | grep . | cat

第二种形式没有着色,因为 grep 注意到它的 stdOut 不是终端,而是管道。他/她怎么知道????

比较

ls -l /proc/self/fd/1
( ls -l /proc/self/fd/1 ) | cat

在第一种形式中,stdOut 是 tty/pts。第二个是管道。

相关内容