Linux的这个命令相信很多人还是不理解 | 2>&1

4,108 阅读3分钟

好记性,不如烂笔头,趁热记录下,给未来的自己

0 | 先说结论

先看看chatGPT怎么说:

img_v2_9267b43f-e438-4c8f-a056-97be2d1f420g.jpg

我的理解:

  1. 2 表示 linux 的 stderr(标准错误输出) 的文件描述符,也就是说 如果 linux shell 执行一个命令(比如:pip install -y something >1.log 2>2.log),如果代码里抛出了异常错误,那么这个错误日志会被输出到 stderr,也就是其对应的文件描述符 2,也就是 2.log
  2. > 表示 重定向
  3. & 表示 等同于
  4. 那么 >&1 表示 等同于重定向到 1
  5. 1 表示 linux 的 stdout(标准输出)的文件描述符,那么 pip install -y something >1.log 2>2.log 就会将正常的日志重定向到 1.log
  6. 另外,我们也经常看到这样的命令 apt-get update -y >/dev/null 2>&1, 作用是更新apt包的时候不显示log。可以这么理解:>/dev/null 等同于 1>/dev/null(默认 1 可以不写),表示 stdout 的日志重定向到 /dev/null2>&1 表示 stderr 这个管道接到 1,也就是 stdout,再重定向到 /dev/nul/dev/null 是一个 linux 不存在的设备,可以理解成一个黑洞,所有重定向到这里的文件都会被吞噬。

到这里,相信大家对这个命令已经理解了。如果你对这个命令的使用场景感兴趣,可以继续往下看。

1 | 还原场景

以 huggingface 的调试页面举例:

image.png 可以看到,容器的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 是空的。

image.png

  • pip install onnx1 >1.log 2>2.log 那么针对这个命令,执行完,1.log 里是空的,而 2.log 是报错信息。

image.png

  • pip install onnx2 >>1.log 2>&1 那么针对这个命令,执行完,1.log 里有报错信息,2.log 是空的。

image.png

3 | 几点感悟

其实这是一个实际的业务需求转换出来的一篇文章,在解决这个问题的过程中,有几点感悟,一吐为快:

  1. 工程上的东西,真的没啥门槛,也没啥秘密,只要有人能做出来,那就一定能做出来;
  2. 对于搞后端,搞 devops 的人来说,linux 真的得好好学习;
  3. 有对标的产品可以“抄”, 真的很爽,虽然工程上的技术是黑盒,但是对于有经验的开发同学来说,基本就是明盘了。

所以,你理解 2>&1 了么?

以上