错误重定向无反应的根本原因是命令未产生stderr;2>覆盖写适合调试,2>>追加写适合长期监控;合并stdout和stderr需用>&或2>&1避免错乱;丢弃输出应使用>/dev/null或&>/dev/null。

错误输出重定向为什么总是没反应
经常会遇到这样的情况:执行 command 2> error.log 后,error.log 却是空的,或者命令明明报错了,却没有写入到这个文件中。这可不是因为语法错误,而是另有原因:命令根本就没有产生 stderr——比如说,ls /valid/path 执行成功时,是不会往 fd 2 输出任何东西的;只有像 ls /noexist 这种真正执行失败的命令,才会让 2> 起作用。
验证方式很简单:echo "test" 2> out.txt 不会写入(因为 echo 从不写 stderr),但 ls /xxx 2> out.txt 会写入错误信息。
2> 和 2>> 怎么选
覆盖写还是追加写,取决于日志用途:
2> error.log:每次运行都清空旧内容,适合单次调试、临时抓错2>> error.log:保留历史,适合长期监控脚本,比如定时任务每小时跑一次,你想看全部失败记录- 混用也合法:
command 1>> output.log 2> error.log—— 正确输出追加,错误输出覆盖,避免错误日志被冲掉关键上下文
把 stdout 和 stderr 合并写入同一个文件要注意顺序
直接写 command > all.log 2> all.log 是错的:两股流竞争写入,内容会错乱(比如“Permission”和“denied”被拆开写在不同位置)。
正确做法只有两种:
command > all.log 2>&1:先重定向 stdout 到文件,再让 stderr 指向 stdout 当前目标(即文件)command &> all.log:等价于上一条,更简洁,但 CentOS 7 bash 4.2+ 才支持(默认系统满足)- 追加合并用:
command >> all.log 2>&1或command &>> all.log
注意:2>&1 必须写在 > 之后,顺序反了(如 2>&1 > all.log)会导致 stderr 仍输出到终端。
丢弃错误输出就用 /dev/null
不想保存错误、也不让它干扰终端,直接扔进黑洞:
command 2> /dev/null:错误消失,stdout 照常输出到屏幕command > /dev/null 2>&1:彻底静默,所有输出都不见(常用于 cron 脚本避免邮件告警)- 别写成
2> /dev/null 1> /dev/null—— 多余,&> /dev/null一条就够了
真正容易被忽略的是:/dev/null 不是“文件”,而是一个内核设备节点,写进去的东西瞬间蒸发,不占磁盘,也不触发 I/O 错误 —— 这正是它比创建空文件再重定向更可靠的原因。