重定向符号顺序错误会导致执行失败:如> file.txt hello.txt将字面量"hello.txt"写入而非读取文件;正确应为cat hello.txt > file.txt;2>&1必须置于>之后,否则stderr无法捕获。

重定向符号写错顺序会直接执行失败
Linux 里 > 和 看似对称,但位置错了命令就不是你想要的——比如 <code>cat > file.txt hello.txt 不会把 hello.txt 内容写进 file.txt,而是把字面量 hello.txt 当作字符串输出进去。因为 shell 把 > 后面紧挨的内容当成目标文件,其余参数全当 cat 的输入参数(而 cat 没指定输入源时读 stdin)。
正确写法是:cat hello.txt > file.txt 或 cat file.txt。注意: 必须紧跟在命令后或参数之间,不能塞在中间;<code>> 和 >> 只能出现在命令行末尾或重定向链中靠后位置。
-
2>&1要写在>后面,否则 stderr 不会被捕获:用command > out.txt 2>&1,别写成command 2>&1 > out.txt(后者2>&1指向的是原始 stdout,还没被重定向) -
2>/dev/null单独使用没问题,但和>组合时,顺序错会导致静默丢数据 - bash 4.0+ 支持
&>file简写等价于>file 2>&1,但老系统或 dash/sh 下不认,别无脑用
用 exec 持久重定向整个 shell 会话
临时重定向只影响单条命令,想让后续所有命令输出都进日志?得靠 exec。它不是执行新进程,而是修改当前 shell 的 fd 映射——所以生效后连 echo、ls 都走新路径。
常见误操作是漏掉 fd 编号或搞混方向:exec > log.txt 把 stdout(fd 1)重定向到文件;exec 3>tmp.txt 是开一个新 fd 3,不干扰默认流;exec 2>&1 才是把 stderr 接到当前 stdout(此时若 stdout 已被重定向,stderr 就也进去了)。
- 要同时重定向 stdout 和 stderr 到同一文件:先
exec > log.txt,再exec 2>&1(顺序不能反) - 恢复默认终端输出:用
exec > /dev/tty 2>/dev/tty,别试exec > /dev/stdout——那只是个符号链接,可能已被改写 - 脚本开头加
exec 3>&1可保存原始 stdout,之后用echo "debug" >&3输出到终端,不影响主流程重定向
tee 分流时 -a 参数决定是否覆盖
tee 看似简单,但默认行为是覆盖文件,跟 > 一样;想追加得显式加 -a。很多人写 cmd | tee log.txt,跑两次后发现只有第二次结果——因为第一次的 log 被清空了。
另一个坑是管道中断导致 tee 提前退出,上游命令却还在写,可能触发 SIGPIPE。比如 yes | tee /tmp/junk.txt,手动 killall tee 后 yes 进程常卡住不动(实际是被信号终止,但现象像卡死)。
- 需要追加日志:用
cmd | tee -a log.txt,别依赖默认行为 - 既要屏幕输出又要存两份不同格式?
cmd | tee log.txt | grep "ERROR"—— 注意tee的 stdout 是管道,不是终端,所以第二段命令才能继续处理 - 避免
tee成为瓶颈:大数据量时加--output-error=exit让它出错立刻报,而不是默默丢数据
重定向到不存在目录会报错,mkdir -p 不能自动补救
写 command > /path/to/log/file.log 前,shell 不会帮你建中间目录。报错不是 No such file or directory,而是更迷惑的 No such file or directory(提示的是文件路径整体不可写),新手常以为是权限问题,其实只是 /path/to/log/ 根本不存在。
有人想用 mkdir -p $(dirname /path/to/log/file.log); command > /path/to/log/file.log,但要注意 $(dirname ...) 在重定向解析前就执行了,如果路径含变量或命令替换,得用子 shell 或提前展开。
- 安全做法:先
mkdir -p /path/to/log,再重定向;或者用set -o pipefail配合if判断目录是否存在 - 脚本里别写
command > $(mktemp)就完事——临时文件没清理,且mktemp返回路径带换行或空格时会崩 - zsh 用户注意:
cd foo && command > ../bar/out.log中的../bar是相对于原工作目录还是当前?答案是原目录——重定向路径解析不随cd实时更新
重定向看着只是加几个符号,但 fd 层、shell 解析顺序、子进程继承规则全在底下咬着。最常翻车的地方不是语法记错,而是以为“它该懂我的意图”,结果它只认字面意思。









