Linux 中为什么有些程序正常运行可以在标准输出中打印,用了重定向>或者管道|后,重定向文件及管道中无任何输入?

2022-12-02 23:10:36 +08:00
 varius
如题。
有些程序直接运行 COMMAND ,就能在屏幕中打 log 。
但是如果在后面加上> 或者 | xargs 后,文件或管道中不能收到任何数据。
想请教一下各位 Bash 玩的比较六的大佬们,到底什么问题?
2237 次点击
所在节点    程序员
22 条回复
moen
2022-12-02 23:17:20 +08:00
可能你看到其实是输出到 stderr ,直接重定向当然是没有内容
varius
2022-12-02 23:18:01 +08:00
@moen 这个问题我有考虑过,然后将 stderr 重定向到 stdout 中,但是也失效。很奇怪
gam2046
2022-12-02 23:23:56 +08:00
有些程序指的是哪些,给几个例子看,让人上来就猜是不是有点困难。
varius
2022-12-02 23:28:29 +08:00
@gam2046 比如 bazel
conanforever22
2022-12-02 23:53:11 +08:00
我之前遇到过这样的问题,不知道和你的情况是否类似
```sh
cmd_write_to_stderr 2>&1 > foo.txt # > 在 2>&1 后边的话是重定向不成功的
```
但是
```sh
cmd_write_to_stderr > foo.txt 2>&1 # > 在 2>&1 前边的话是没问题的
```
kirory
2022-12-02 23:55:48 +08:00
因为没有用 stdout / stderr, 比如 sudo 的输入用的都不是这些,而是直接读写终端
kirory
2022-12-02 23:58:55 +08:00
比如这些命令,对应的设备可能不是 1 ,可以多试几个数字
echo Hello > /dev/pts/1
cat < /dev/pts/1
kirory
2022-12-03 00:04:54 +08:00
@kirory 改进一下,把重定向位置改成 $(tty)
geelaw
2022-12-03 00:08:17 +08:00
因为程序可以选择查看自己的标准流是哪里并选择不同的行为。比如 git diff 在 stdout 接入 terminal 的时候默认使用转义序列显示彩色,但 stdout 接入文件时默认不用。
varius
2022-12-03 01:01:07 +08:00
@conanforever22 有些类似
varius
2022-12-03 01:01:25 +08:00
@kirory 谢谢老哥指教,我测试一下
varius
2022-12-03 01:01:54 +08:00
@geelaw 的确是的。而且现在有些 log 框架也会有类似的情况
varius
2022-12-03 01:02:54 +08:00
@kirory 再请教下老哥,如果是直接读写终端的话,按道理不会出现用了管道或者重定向之后屏幕不输出的情况吧。
luvjoey1996
2022-12-03 01:09:40 +08:00
@conanforever22 参考一下 shellcheck
bigdoing
2022-12-03 01:11:36 +08:00
还是让高手来回答你们
程序判断输出是 tty 的时候,按照行缓冲输出,有了新一行,就写
如果是 pipe 的话,就会攒着,到一大块的时候,再写
这种一般有参数控制,比如 grep ,就有一个参数控制
varius
2022-12-03 01:20:42 +08:00
@bigdoing 请教一下,在这种情况如何可以强迫前面的有一行输出一行呢?
jasonyang9
2022-12-03 07:54:48 +08:00
aloxaf
2022-12-03 08:39:06 +08:00
@varius
在伪终端里运行它们即可,zsh 用户的而话可以直接用 zpty 命令:
https://github.com/lilydjwg/dotzsh/blob/master/zshrc#LL561-L561C7
7RTDKSAK
2022-12-03 15:31:00 +08:00
@conanforever22

因为重定向是有序地(至少在 BASH 中是有序地,其它 SHELL 我不了解)

第一种写法:
第一阶段:文件描述符 1 和 2 都指向屏幕(姑且说成"屏幕",方便理解),你把串流 2 重定向到了串流 1,而串流 1 又指向了屏幕,所以最终效果就是串流 2 指向了屏幕(虽然它原来也指向屏幕),串流 1 没有变化依旧指向屏幕
第二阶段:在第一阶段(或者说在以前所有重定向阶段)基础上,串流 1 重定向到了文件(所以在屏幕上看不到了),串流 2 没有变化依旧指向屏幕
所以最终效果就是你所说得"重定向不成功"

第二种写法:
略,言之有理即可(滑稽)

另外,推荐&>file 这种写法,一次性把文件描述符 1 和 2 同时重定向到文件
JohnBull
2022-12-03 17:32:42 +08:00
不可能的

肯定是太着急了,数据还在 buffer 里没刷出来呢,你就去看输出文件,发现是空的,就 sigint 了……

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/899729

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX