2012-10-01 80 views
0

我无法将标准错误发送到标准输出。我打算把它放在cron中,但现在我只是手动运行。将标准错误发送到标准输出不起作用

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

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

我在这里做错了什么?

回答

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,因为标准误差为 复制从标准输出之前的标准输出重定向到dlist的 。

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

之前的任何重定向发生全局表可能是这个样子

A: TERMINAL 

和进程表看起来像

0: A 
1: A 
2: A 

因为描述数字0,1,和2标准输入,标准输出,和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 

那么标准out变成指向新打开的文件(好像1>&3被完成),从而进程表现在

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

注意,2(错误)仍然指向该终端。

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

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

然后2>&1重定向改变什么2点给

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

所以现在输出和错误都去文件。

+0

我真的不明白这一点。如果它从左向右读,那么你建议的命令是不是不起作用?不是>>将标准重定向到文件?如果是这样,那么我需要确保我第一次有标准错误重定向第一...在这之前呢? – Brian

+0

@Brian,请参阅编辑。让我知道如果它仍然不清楚。 –

+0

嗯...当时,STDOUT的当前位置是终端。所以它将STDERR重定向到STDOUT,但它仍然只是终端。但是,那么>>应该重定向终端的STDOUT,它现在包括我的bash脚本中的STDERR不是吗? – Brian

2

重定向的顺序很重要。你应该将其更改为:

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

这个标准输出重定向到/var/log/backups/backup.log,然后重定向标准错误到标准输出(这是进入该文件)。

您还可以使用较短的形式:

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

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

相关问题