回应输出到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的交互使用subshell
(>&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
不要像这里提到的那样使用cat
。 cat
是一个程序,而echo
和printf
是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
保存进程打开的文件描述符。 然后, 0
和2
代表stdin
, stdout
和stderr
。
我发现它更可读。 此外,这可能在大多数Linux分布:
echo "my errz" > /dev/stderr
使它更可读。
Mac OS X:我尝试了接受的答案和其他一些答案,所有这些都导致在我的Mac上写STDOUT而不是STDERR。
这是一个使用Perl写入标准错误的可移植方法:
echo WARNING! | perl -ne 'print STDERR'