回应输出到stderr

是否有一个标准的Bash工具,行为像回声,但输出到标准错误而不是标准输出?

我知道我可以做echo foo 1>&2但它是有点丑陋,我怀疑,容易出错(例如更容易被编辑错误,当事情改变)。

这个问题很古老,但你可以做到这一点,这有利于阅读:

 >&2 echo "error" 

操作符>&2字面意思是将文件描述符1( stdout )的地址redirect到该命令1的文件描述符2( stderr )的地址。 取决于你想了解它的深度,请阅读: http : //wiki.bash-hackers.org/howto/redirect_tutorial

为了避免与其他redirect的交互使用subshel​​l

 (>&2 echo "error") 

1 >&2文件描述符# >&2复制到文件描述符#1。 因此,执行此redirect之后,两个文件描述符都将引用同一个文件:一个文件描述符#2 最初指的是。

你可以定义一个函数:

 echoerr() { echo "$@" 1>&2; } echoerr hello world 

这将比脚本更快并且没有依赖关系。

Camilo Martin的bash特定build议使用“这里的string”,并且会打印任何你传给它的东西,包括通常会回显的参数(-n)

 echoerr() { cat <<< "$@" 1>&2; } 

格伦·杰克曼的解决scheme也避免了吞咽问题:

 echoerr() { printf "%s\n" "$*" >&2; } 

由于1是标准输出,所以您不必在输出redirect之前显式地将其命名为> ,而只需键入:

回声此消息发送到stderr>&2

既然你似乎担心1>&2会难以可靠地input,那么消除冗余1对你来说可能是一个小小的鼓励!

另外一个select

 echo foo >>/dev/stderr 

不,这是做这件事的标准方法。 它不应该导致错误。

这是一个简单的STDERR函数,它将pipe道inputredirect到STDERR。

 #!/bin/bash # ************************************************************* # This function redirect the pipe input to STDERR. # # @param stream # @return string # function STDERR () { cat - 1>&2 } # remove the directory /bubu if rm /bubu 2>/dev/null; then echo "Bubu is gone." else echo "Has anyone seen Bubu?" | STDERR fi # run the bubu.sh and redirect you output tux@earth:~$ ./bubu.sh >/tmp/bubu.log 2>/tmp/bubu.err 

不要像这里提到的那样使用catcat是一个程序,echoprintf是bash(shell)内置的。 启动一个程序或其他脚本(上面也提到)意味着创build一个新的过程,其所有的成本。 使用内置函数,编写函数非常便宜,因为不需要创build(执行)一个进程(环境)。

opner问“有没有标准的工具输出( pipe道 )到stderr”,schort答案是:没有…为什么? redux的pipe道是像unix(Linux …)和bash(sh)这样的概念构build的系统中的一个主要概念。

我同意这样一个重新定向的开门符: &2>1对于现代程序员来说并不是很愉快,但这就是bash。 Bash并不打算写出庞大而强大的程序,它的目的是帮助pipe理员在那里使用较less的按键; -)

至less,您可以将redirect放在任何位置:

 $ echo This message >&2 goes to stderr This message goes to stderr 

如果您不介意将消息logging到系统日志,那么not_so_ugly方法是:

 logger -s $msg 

-s选项表示:“将消息输出到标准错误以及系统日志。

注意:我正在回复post,而不是误导/模糊的“输出到stderr的回应”问题(OP已经回答)。

使用一个函数来显示意图,并获得你想要的实现。 例如

 #!/bin/bash [ -x error_handling ] && . error_handling filename="foobar.txt" config_error $filename "invalid value!" output_xml_error "No such account" debug_output "Skipping cache" log_error "Timeout downloading archive" notify_admin "Out of disk space!" fatal "failed to open logger!" 

error_handling是:

 ADMIN_EMAIL=root@localhost config_error() { filename="$1"; shift; echo "Config error in $filename: $*" 2>&1; } output_xml_error() { echo "<error>$*</error>" 2>&1; } debug_output() { [ "$DEBUG"=="1" ] && echo "DEBUG: $*"; } log_error() { logger -s "$*"; } fatal() { which logger >/dev/null && logger -s "FATAL: $*" || echo "FATAL: $*"; exit 100; } notify_admin() { echo "$*" | mail -s "Error from script" "$ADMIN_EMAIL"; } 

处理OP问题的理由:

  • 最好的语法可能(有意义的单词,而不是丑陋的符号)
  • 更难以发生错误(特别是如果您重复使用脚本)
  • 这不是一个标准的Bash工具,但它可以是你或你的公司/组织的标准shell库

其他原因:

  • 清晰度 – 向其他维护者展示意图
  • 速度 – function比shell脚本更快
  • 可重用性 – 一个函数可以调用另一个函数
  • 可configuration性 – 无需编辑原始脚本
  • debugging – 更容易find造成错误的线路(特别是如果您正在使用大量的redirect/过滤输出)
  • 健壮性 – 如果一个函数丢失,你不能编辑脚本,你可以退回到使用外部工具具有相同的名称(例如log_error可以别名logging器在Linux上)
  • 切换实现 – 您可以通过删除库的“x”属性来切换到外部工具
  • 输出不可知论 – 你不再需要关心是否去STDERR或其他地方
  • 个性化 – 您可以使用环境variablesconfiguration行为

制作一个脚本

 #!/bin/sh echo $* 1>&2 

那将是你的工具。

或者如果你不想在一个单独的文件中有一个脚本的话,可以创build一个函数。

read是打印到stderr的shell内置命令,可以像echo一样使用,而不执行redirect技巧:

 read -t 0.1 -p "This will be sent to stderr" 

-t 0.1是一个超时,禁止读取的主要function,将一行stdin存储到variables中。

这已经得到了回答,并获得了大量的选票。 只是为了logging:

echo "my errz" > /proc/self/fd/2

将有效输出到stderr 。 说明: /proc/self是当前进程的链接, /proc/self/fd保存进程打开的文件描述符。 然后, 02代表stdinstdoutstderr

我发现它更可读。 此外,这可能在大多数Linux分布:

echo "my errz" > /dev/stderr

使它更可读。

Mac OS X:我尝试了接受的答案和其他一些答案,所有这些都导致在我的Mac上写STDOUT而不是STDERR。

这是一个使用Perl写入标准错误的可移植方法:

 echo WARNING! | perl -ne 'print STDERR'