这可能是以最简单的形式提出问题的最佳地点。我正在编写一个脚本,它将命令的输出放入变量中。经过一些调试,我发现命令出错时不会转到标准输出,而是转到控制台(或墙上)。请参见下面的示例:
当命令成功运行时
root@local# apcaccess status
APC : 700
VERSION : xxxxx
BATTSTAT : AC
当命令出错时
root@local# apcaccess status
apcupsd @ localhost: Connection Refused.
root@local# apcaccess status | grep -i version
apcupsd @ localhost: Connection Refused.
我注意到,当我尝试通过 grep 'apcaccess status | grep -i version' 管道传输命令时,如果运行成功,我会得到版本号,但在出错的系统上,我会收到错误消息。我相信它没有通过标准输出。
问题是:我怎样才能强制输出转到标准输出?
答案1
# apcaccess status 2>&1 | grep -i version
这会将 stderr 重定向到 stdout,因此 grep 将看到输出。
答案2
原因是实际上有两个打开的文件描述符会“打印”到您的屏幕上。stdout(由文件描述符 1 表示)和 stderr(文件描述符 2)。当您将一个命令通过管道传输到另一个命令时,您只需从第一个命令中获取 stdout,然后将其作为 stdin“通过管道传输”到第二个命令。但是,如果第一个命令将某些内容打印到 stderr(通常是错误消息),则它不会通过管道传输,而是直接打印到您的屏幕上。
所以需要将 stderr 重定向到 stdout。通过以下方式实现。
命令1 2>&1 | 命令2
专家提示:之所以需要使用 & 符号,是因为你需要说明你正在将 stderr (2) 重定向到文件描述符stdout (1)。否则,没有 & 符号,您只是告诉 stderr 重定向到文件当前工作目录中名为“1”的文件。类似于您通过“command > myfile.log”将命令的“输出”(stdout)转储到文件时可能执行的操作。如果在重定向命令前面不放置文件描述符,则默认为 1(stdout)。