0

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

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

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

我在这里做错了什么?

4

2 回答 2

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

于 2012-10-01T15:07:12.640 回答
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 分别是标准输入、标准输出和标准错误。

然后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 都进入文件。

于 2012-10-01T15:09:51.317 回答