将标准错误发送到标准输出不起作用

时间:2012-10-01 15:01:45

标签: linux cron

我无法获得将标准错误发送到标准输出的命令。我打算把它放在cron中,但现在只是手动运行。

/home/backups/backup_scripts/backup.sh 2>&1 >> /var/log/backups/backup.log

我希望日志文件包含任何打印到标准输出的消息,但日志文件只显示标准输出,并且控制台输出显示错误。

我在这里做错了什么?

2 个答案:

答案 0 :(得分:2)

重定向的顺序很重要。你应该把它改成:

/home/backups/backup_scripts/backup.sh >> /var/log/backups/backup.log 2>&1 

这会将stdout重定向到/var/log/backups/backup.log,然后将stderr重定向到stdout(进入文件)。

您还可以使用以下简短形式:

/home/backups/backup_scripts/backup.sh &>> /var/log/backups/backup.log

&>>file在语义上等同于>>file 2>&1

答案 1 :(得分:2)

这是因为重定向的顺序。 2>&1表示“将标准错误重定向到标准输出的当前位置”。它们从左到右处理,因此第一个标准错误被重定向到当前标准输出(仍然是终端),然后标准输出被重定向到文件。如果您将订单切换为阅读

/home/backups/backup_scripts/backup.sh >> /var/log/backups/backup.log 2>&1

它应该做你想要的。如果您的shell是bash,它有一个快捷方式可以同时重定向标准输出和标准错误:command &> file将它们重定向到文件,command &>> file将两者都附加到文件。 bash手册中还提到了这种顺序依赖性

  

请注意,重定向的顺序非常重要。例如,命令

ls > dirlist 2>&1
     

将标准输出和标准错误都指向文件dirlist,同时命令

ls 2>&1 > dirlist
     

仅将标准输出定向到文件dirlist,因为标准错误是   在标准输出重定向到标准输出之前从标准输出重复   dirlist。

我认为对文件描述符和重定向的工作方式存在一些误解。内核有一个包含系统中所有打开文件的大表,其中包含文件偏移量,状态标志和文件本身的名称。然后,每个进程都有一个表,用于将文件描述符编号映射到此全局表中的条目。

在任何重定向发生之前,全局表可能看起来像这样

A: TERMINAL

,进程表看起来像

0: A
1: A
2: A

因为描述符编号0,1和2分别是stdin,stdout和stderr。

然后处理2>&1重定向。这会更改进程表,以便2包含与1相同的全局条目的点。但是,它们已经相同,因此没有任何反应。

处理>> /var/log/backups/backup.log重定向时。首先打开文件并将其分配给进程表中的文件描述符3,使表格看起来像

A: TERMINAL
B: /var/log/backups/backup.log

0: A
1: A
2: A
3: B

然后将标准输出更改为指向新打开的文件(就好像1>&3已完成),因此进程表现在是

0: A
1: B
2: A
3: B

请注意,2(stderr)仍然指向终端。

当重定向以其他顺序完成时,>> /var/log/backups/backup.log之后的表格看起来相同。

0: A
1: B
2: A
3: B

然后2>&1重定向会改变2分给予

0: A
1: B
2: B
3: B

所以现在stdout和stderr都转到了文件。