shell中的 2>&1含义

在平常项目中,我们经常可以看到如下的shell命令:

* * * * * php /path-to-your-project/artisan schedule:run >> /dev/null 2>&1

前面的命令含义我们都明白,但是后面的 >> /dev/null 2>&1却不太明白,现在就来探讨一下这个命令的含义。

/dev/null

/dev/null(或称空设备)在类Unix系统中是一个特殊的设备文件,它丢弃一切写入其中的数据(但报告写入操作成功),读取它则会立即得到一个EOF[1]

上面这句话摘抄自维基百科。

简单来说,/dev/null就是一个垃圾桶,任何投向这个文件的东西都会被丢弃。所以我们可以将不需要保存的任何输出都可以丢到这里面。

2>&1

理解这个命令的含义之前,我们需要先理解一下在类Unix系统下,每个程序运行后,都会至少打开三个文件描述符。

  • 0:标准输入(stdin)
  • 1:标准输出(stdout)
  • 2:错误输入(stderr)

假如我们有一个shell脚本如下:

#!/bin/bash
date         #打印当前时间
while true   #死循环
do
    #每隔2秒打印一次
    sleep 2
    whatthis    #不存在的命令
    echo -e "std output"
done

上续脚本运行的时候,会抛出异常,如下:

Tue Aug 24 09:44:50 CST 2021
./test.sh: line 7: whatthis: command not found
std output
./test.sh: line 7: whatthis: command not found
std output
./test.sh: line 7: whatthis: command not found
std output
./test.sh: line 7: whatthis: command not found
std output
./test.sh: line 7: whatthis: command not found
std output
./test.sh: line 7: whatthis: command not found
std output
./test.sh: line 7: whatthis: command not found
std output

我们通过ps aux| grep test.sh可以找到这个脚本的进程ID:

root@ezreal:~# ps aux | grep test.sh | grep -v 'grep '
root     31807  0.0  0.1  12228  3296 pts/0    S+   09:44   0:00 /bin/bash ./test.sh

进程ID为31807,然后打开ls -al /proc/31807/fd可以看到这三个文件描述符。

root@ezreal:~# ls -al /proc/31807/fd
total 0
dr-x------ 2 root root  0 Aug 24 09:44 .
dr-xr-xr-x 9 root root  0 Aug 24 09:44 ..
lrwx------ 1 root root 64 Aug 24 09:44 0 -> /dev/pts/0
lrwx------ 1 root root 64 Aug 24 09:44 1 -> /dev/pts/0
lrwx------ 1 root root 64 Aug 24 09:46 2 -> /dev/pts/0
lr-x------ 1 root root 64 Aug 24 09:46 255 -> /root/test.sh

如果这个时候我们想将这个shell脚本输出都重定向到一个log文件中。我们可以这样处理:

./test.sh >> test.log

运行之后我们发现,标准输出是可以追加到日志中去,但是错误输出无法追加,

root@ezreal:~# ./test.sh >> test.log 
./test.sh: line 7: whatthis: command not found
./test.sh: line 7: whatthis: command not found
./test.sh: line 7: whatthis: command not found

这个时候就需要使用2>&1这个命令了。这个命令的含义就是将错误输出重定向到标准输出中去,而标准输出我们重定向到了test.log中,就意味着错误输出也重定向到了test.log中了。但是为什么要加上&这个符号呢。因为重定向符号>右侧必须是一个文件,&1就代表引用了标准输出这个文件描述符。

这时我们更改命令如下:

root@ezreal:~# ./test.sh >> test.log  2>&1

发现没有错误输出了。

然后查看该命令的进程相关信息:

root@ezreal:~# ps aux | grep test.sh | grep -v 'grep '
root      1362  0.0  0.1  12228  3136 pts/0    S+   09:55   0:00 /bin/bash ./test.sh
root@ezreal:~# ls -al /proc/1362/fd
total 0
dr-x------ 2 root root  0 Aug 24 09:55 .
dr-xr-xr-x 9 root root  0 Aug 24 09:55 ..
lrwx------ 1 root root 64 Aug 24 09:55 0 -> /dev/pts/0
l-wx------ 1 root root 64 Aug 24 09:55 1 -> /root/test.log
l-wx------ 1 root root 64 Aug 24 09:56 2 -> /root/test.log
lr-x------ 1 root root 64 Aug 24 09:56 255 -> /root/test.sh
root@ezreal:~# 

可以发现文件描述符1,也就是stdout,文件描述符2,也就是stderr都指向了test.log这个文件了。我们查看一下test.log文件可以发现:

./test.sh: line 7: whatthis: command not found
std output
./test.sh: line 7: whatthis: command not found
std output
./test.sh: line 7: whatthis: command not found
std output
./test.sh: line 7: whatthis: command not found
std output
./test.sh: line 7: whatthis: command not found
std output
./test.sh: line 7: whatthis: command not found
std output
./test.sh: line 7: whatthis: command not found
std output
./test.sh: line 7: whatthis: command not found
std output
./test.sh: line 7: whatthis: command not found
std output
./test.sh: line 7: whatthis: command not found
std output

发现错误也打印进来了。

暂无评论

发送评论 编辑评论


|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇