廖彗云 发表于 2025-12-31 07:10:00

“这行命令跑了一晚,日志全丢了?”—— 5分钟彻底搞懂 Linux I/O 重定向与 tee 大法

1. 引言:午夜心碎时刻

你有没有经历过这样的场景:
临下班前,你写好了一个数据迁移脚本,在终端敲下命令,看着进度条开始跑,心满意足地回家了。 第二天一早,你满怀期待地打开电脑,发现终端窗口因为网络波动断开了(Broken Pipe),或者被系统的自动更新重启了。
结果: 屏幕上的日志没了,文件里也没存。脚本到底跑完了吗?报错了吗?在哪断的? 答案: 上帝才知道。
这就是**“数据流失”**的惨痛教训。
今天要讲的 >、>>、& 和 tee,就是 Linux 世界里的管道工工具包。学会它们,你就能随心所欲地控制程序输出的去向——既能在屏幕上看“现场直播”,又能把日志存进文件“录像回放”。
2. 概念拆解:Linux 的水管系统

在 Linux 的哲学里,“一切皆文件”。程序的输入输出,本质上就是三根水管。
核心三要素

我们把一个运行的程序想象成一台净水器:

[*]标准输入 (stdin, 0):进水管。通常是键盘输入,或者别的文件传进来的数据。
[*]标准输出 (stdout, 1):出水管(净水)。程序正常运行产生的打印信息,默认流向你的显示器。
[*]标准错误 (stderr, 2):排污管(废水)。程序报错时的警告或错误信息,默认也流向你的显示器。
符号图解


[*]> (覆盖重定向): 相当于把出水管从显示器上拔下来,插到一个桶(文件)里。 注意:每次都会先把桶倒空,再接水。
[*]>> (追加重定向): 也把出水管插到桶里。 区别:如果桶里原本有水,它不倒掉,直接接着往里灌。
[*]| (管道): 把前一台净水器的出水管,直接接到下一台净水器的进水管。
[*]tee (T型三通管): 这就是神奇的神器。它是一个T型接头。水流过来,一份流向屏幕(让你看),一份分流进文件(存盘)。
3. 动手实战:从青铜到王者

我们先创建一个极简的脚本 demo.sh 来模拟真实场景。这个脚本会同时产生“正常日志”和“错误报错”。
Bash # demo.sh
# 模拟正常输出 (stdout)
echo "✅ 处理数据块 1..."
echo "✅ 处理数据块 2..."

# 模拟报错 (stderr) - 注意这里我们强制输出到 stderr
echo "❌ 连接数据库失败!" >&2

echo "✅ 任务结束。"场景一:初级——直接存文件 (>)

你只想把结果存起来,不关心屏幕看没看见。
Bash bash demo.sh > result.log

[*]结果:

[*]result.log 里只有 ✅ ...。
[*]等等! 屏幕上居然打印了 ❌ ...?

[*]为什么?

[*]因为 > 默认只接管了 1号水管 (stdout)。
[*]2号水管 (stderr) 依然指向屏幕,所以报错漏出来了,没存进文件里!

场景二:进阶——全量保存 (2>&1)

这是新手最头疼的符号。我们想把“报错”和“正常日志”都存进同一个文件。
Bash bash demo.sh > result.log 2>&1

[*]代码解析:

[*]> result.log:先把 1号管 接到文件。
[*]2>&1:这是一个“并管”操作。意思是:把 2号管 (stderr) 的出口,汇入到 1号管 (stdout) 当前的流向中。
[*]结果:正常日志和报错都乖乖进了 result.log。

场景三:王者——我全都要 (tee)

这就是解决引言中痛点的终极方案。既要在屏幕上监控进度,又要存文件备份。
Getty Images我们需要一个 T型三通(Tee)。
Bash bash demo.sh | tee result.log

[*]发生了什么?

[*]|:管道符,把 demo.sh 的输出传给 tee 命令。
[*]tee:接收到数据后,左手画圆(打印到屏幕),右手画方(写入 result.log)。

[*]注意:tee 默认只接收 stdout。如果也要保存报错,需要先合并流:
Bash # 完美方案:标准输出+错误,既看屏幕,又存文件
bash demo.sh 2>&1 | tee result.log场景四:不讲武德——追加模式 (tee -a & >>)

如果你不想覆盖昨天的日志,而是想接着写:

[*]普通重定向:用 >> 代替 >。
[*]Tee 模式:用 -a (append) 参数。
Bash bash demo.sh 2>&1 | tee -a result.log4. 进阶深潜:那些你不知道的坑

坑 1:sudo 也不好使?

你可能遇到过这种情况:想把一段文本写入一个只有 root 权限才能写的文件(比如 /etc/profile)。
Bash # ❌ 错误示范
sudo echo "export JAVA_HOME=..." >> /etc/profile
# 报错: Permission denied为什么? 因为 sudo 只对 echo 命令生效。后面的 >> 是由你当前的 Shell 执行的,而你的 Shell 没有权限写 /etc/profile。
✅ 最佳实践 (使用 tee):
Bash echo "export JAVA_HOME=..." | sudo tee -a /etc/profile这里 sudo 提升了 tee 的权限,tee 负责写文件,完美解决。为了不让屏幕多打印一遍,可以扔进黑洞:
Bash echo "data" | sudo tee file.txt > /dev/null坑 2:2>&1 > file vs > file 2>&1

这两个命令看起来很像,但效果完全不同!顺序非常重要!

[*]正确: > file 2>&1

[*]解释:先把 1 指向文件,然后把 2 指向 1(也就是文件)。
[*]结果:大家都在文件里。

[*]错误: 2>&1 > file

[*]解释:先把 2 指向 1(此时 1 还在屏幕),所以 2 去了屏幕。然后把 1 指向文件。
[*]结果:报错打在了屏幕上,只有正常日志进了文件。

5. 总结与延伸

一句话总结


[*]> 是“洗心革面”(覆盖文件)。
[*]>> 是“再续前缘”(追加文件)。
[*]2>&1 是“兄弟齐心”(错误流汇入标准流)。
[*]tee 是“分身有术”(屏幕和文件我都要)。

来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

村亢 发表于 2026-1-17 10:16:10

感谢分享,下载保存了,貌似很强大

闵雇 发表于 2026-1-23 08:38:22

分享、互助 让互联网精神温暖你我

沦嘻亟 发表于 2026-2-2 02:27:11

新版吗?好像是停更了吧。

岳娅纯 发表于 2026-2-2 03:09:24

感谢,下载保存了

抽厉 发表于 2026-2-3 06:26:28

喜欢鼓捣这些软件,现在用得少,谢谢分享!

羊舌正清 发表于 2026-2-5 02:49:32

感谢发布原创作品,程序园因你更精彩

呈步 发表于 2026-2-7 04:59:25

东西不错很实用谢谢分享

左丘纨 发表于 2026-2-8 09:56:16

懂技术并乐意极积无私分享的人越来越少。珍惜

昝琳怡 发表于 2026-2-8 10:02:01

东西不错很实用谢谢分享

染罕习 发表于 2026-2-8 10:23:44

感谢分享,下载保存了,貌似很强大

纪音悦 发表于 2026-2-9 01:33:30

鼓励转贴优秀软件安全工具和文档!

貊淀 发表于 2026-2-9 05:23:54

感谢分享,下载保存了,貌似很强大

呵桢 发表于 2026-2-10 07:41:41

感谢分享,学习下。

公新蕾 发表于 2026-2-12 16:28:04

用心讨论,共获提升!

琦谓 发表于 2026-2-21 04:28:11

这个好,看起来很实用

迫蔺 发表于 2026-2-23 08:33:16

鼓励转贴优秀软件安全工具和文档!

挽幽 发表于 2026-2-25 11:10:38

感谢分享,下载保存了,貌似很强大

殷罗绮 发表于 2026-3-2 11:48:47

感谢发布原创作品,程序园因你更精彩

眺愤 发表于 2026-3-9 03:11:07

热心回复!
页: [1] 2
查看完整版本: “这行命令跑了一晚,日志全丢了?”—— 5分钟彻底搞懂 Linux I/O 重定向与 tee 大法