好记性,不如烂笔头,趁热记录下,给未来的自己
0 | 先说结论
先看看chatGPT怎么说:
我的理解:
- 2 表示 linux 的 stderr(标准错误输出) 的文件描述符,也就是说 如果 linux shell 执行一个命令(比如:
pip install -y something >1.log 2>2.log
),如果代码里抛出了异常错误,那么这个错误日志会被输出到 stderr,也就是其对应的文件描述符 2,也就是2.log
- > 表示 重定向
- & 表示 等同于
- 那么 >&1 表示 等同于重定向到 1
- 1 表示 linux 的 stdout(标准输出)的文件描述符,那么
pip install -y something >1.log 2>2.log
就会将正常的日志重定向到1.log
- 另外,我们也经常看到这样的命令
apt-get update -y >/dev/null 2>&1
, 作用是更新apt包的时候不显示log。可以这么理解:>/dev/null
等同于1>/dev/null
(默认 1 可以不写),表示 stdout 的日志重定向到/dev/null
;2>&1
表示 stderr 这个管道接到 1,也就是 stdout,再重定向到/dev/nul
;/dev/null
是一个 linux 不存在的设备,可以理解成一个黑洞,所有重定向到这里的文件都会被吞噬。
到这里,相信大家对这个命令已经理解了。如果你对这个命令的使用场景感兴趣,可以继续往下看。
1 | 还原场景
以 huggingface 的调试页面举例:
可以看到,容器的log里如果有报错的话,前端页面上是会获取到并展示出来的。这个怎么实现的?或者说如果要去实现,能想到什么方法?
通常的做法一般是写一个过滤器去识别容器里的日志,通过关键词过滤,正则匹配等方式获取日志里的特定信息。 这种方法有种显而易见的不稳定点:如果日志的报错信息多种多样,五花八门,这个过滤器就会失效或者覆盖不完全。
那么,如果理解了 linux 的管道 2>&1,stdout,stderr 这些知识点,那么这个请求就可以很轻松的实现。
2 | 模拟实现
用以下三个命令来模拟实现。这三个命令是通过pip来安装包,其中 onnx 是存在的安装过程不会报错,onnx1/onnx2 是不存在的,安装过程会报错。
touch 1.log 2.log
pip install -y onnx >1.log 2>2.log
pip install -y onnx1 >1.log 2>2.log
pip install -y onnx2 >1.log 2>&1
pip install onnx >1.log 2>2.log
那么针对这个命令,执行完,1.log 里有安装的日志,而 2.log 是空的。
pip install onnx1 >1.log 2>2.log
那么针对这个命令,执行完,1.log 里是空的,而 2.log 是报错信息。
pip install onnx2 >>1.log 2>&1
那么针对这个命令,执行完,1.log 里有报错信息,2.log 是空的。
3 | 几点感悟
其实这是一个实际的业务需求转换出来的一篇文章,在解决这个问题的过程中,有几点感悟,一吐为快:
- 工程上的东西,真的没啥门槛,也没啥秘密,只要有人能做出来,那就一定能做出来;
- 对于搞后端,搞 devops 的人来说,linux 真的得好好学习;
- 有对标的产品可以“抄”, 真的很爽,虽然工程上的技术是黑盒,但是对于有经验的开发同学来说,基本就是明盘了。
所以,你理解 2>&1 了么?
以上