C语言read()读取STDERR的疑问及Bash管道重定向stderr方法咨询
问题解答
为什么从stderr(fd=2)读取会让终端等待输入?
这其实是Shell默认行为导致的——默认情况下,**标准输入(stdin, fd=0)、标准输出(stdout, fd=1)、标准错误(stderr, fd=2)**这三个文件描述符,都会被关联到同一个终端设备(比如/dev/pts/0这类伪终端文件)。
终端本身只是一个输入输出设备,它不会区分这三个文件描述符。所以你用read(2, buf, 4)读取fd=2时,本质上和读取fd=0(stdin)是一样的,都是从终端获取输入,自然会出现等待你输入内容的情况。
只有当你显式将stderr重定向到其他目标(比如文件、管道)时,读取fd=2才会从那个目标拿数据,而不是终端。比如你可以试试这个命令:
echo "test" > err_input.txt ./test 2< err_input.txt
这时候程序会直接从err_input.txt读取内容,不会再等待终端输入。
如何在Bash中把stderr输出到文件?
根据不同需求,有几种常用的写法:
1. 仅将stderr写入文件,stdout仍输出到终端
your_command 2> error.log
这里的2>表示把文件描述符2(stderr)的输出重定向到error.log。如果文件不存在会自动创建,存在则直接覆盖;如果想追加内容而不是覆盖,用2>> error.log。
2. 将stderr和stdout合并后写入同一个文件
如果需要把标准输出和错误信息都写到同一个文件里,可以用:
# 传统写法:先定向stdout,再把stderr指向stdout的目标 your_command > combined.log 2>&1 # Bash 4.0+支持的简写,更直观 your_command &> combined.log
注意2>&1必须放在>后面,它的意思是“让文件描述符2的输出,指向文件描述符1当前的目标位置”。
3. 将stderr通过管道传给其他命令处理
如果需要用管道把stderr内容传给下一个命令(比如用grep过滤错误关键词),可以这样写:
# 写法1:先把stderr重定向到stdout,再丢弃原stdout的内容 your_command 2>&1 >/dev/null | grep "error_keyword" # 写法2:Bash专属简写,效果和上面完全一致 your_command |& grep "error_keyword"
内容的提问来源于stack exchange,提问作者Wolfat
相关产品推荐
相关产品推荐

