echo输出到stderr

时间:2010-06-07 14:36:17

标签: bash

是否有一个标准的Bash工具,它像echo一样但输出到stderr而不是stdout?

我知道我可以做echo foo 1>&2但是它有点难看,而且我怀疑,容易出错(例如,当事情发生变化时更有可能被编辑错误)。

16 个答案:

答案 0 :(得分:1180)

这个问题很老,但你可以这样做,这有利于阅读:

>&2 echo "error"

运算符>&2字面意思是将文件描述符1(stdout)的地址重定向到该命令 1 stderr)的地址>。根据您想要了解它的深度,请阅读:http://wiki.bash-hackers.org/howto/redirection_tutorial

为避免与其他重定向的交互,请使用subshel​​l

(>&2 echo "error")

1 >&2将文件描述符#2复制到文件描述符#1。因此,执行此重定向后,两个文件描述符将引用同一文件:一个文件描述符#2 最初引用。

答案 1 :(得分:383)

您可以定义一个函数:

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

这比脚本更快,没有依赖。

Camilo Martin的bash特定建议使用“here string”并打印传递给它的任何内容,包括echo通常会吞下的参数(-n):

echoerr() { cat <<< "$@" 1>&2; }
格伦杰克曼的解决方案也避免了吞咽问题的争论:

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

答案 2 :(得分:215)

由于1是标准输出,因此您不必在>之类的输出重定向前明确命名,而只需键入:

echo This message goes to stderr >&2

由于您似乎担心1>&2难以可靠地输入,因此消除多余的1可能会对您有点鼓励!

答案 3 :(得分:44)

另一个选择

echo foo >>/dev/stderr

答案 4 :(得分:29)

不,这是执行此操作的标准方法。它不应该导致错误。

答案 5 :(得分:11)

这是一个简单的STDERR函数,它将管道输入重定向到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

答案 6 :(得分:11)

如果您不介意将消息记录到syslog中,则not_so_ugly方式为:

logger -s $msg

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

答案 7 :(得分:9)

不要使用cat,因为这里提到了一些。 cat程序echoprintf是bash(shell)内置的。启动程序或其他脚本(也在上面提到)意味着创建一个包含所有成本的新流程。使用内置函数,编写函数非常便宜,因为不需要创建(执行)进程(-environment)。

opner问“是否有任何标准工具输出( pipe )到stderr”,schort答案是:NO ...为什么? ... rediredcting管道是像unix(Linux ...)和bash(sh)这些概念的系统中的一个元素概念。

我同意用这样的符号重定向的开场白:&2>1对于现代程序员来说不是很愉快,但那是bash。 Bash并不打算编写庞大而强大的程序,它旨在帮助管理员以更少的按键来完成工作; - )

至少,您可以将重定向放在行中的任何位置:

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

答案 8 :(得分:7)

注意:我正在回答帖子 - 而不是误导/模糊的“输出到stderr的回声”问题(已由OP回答)。

使用功能显示意图并获取所需的实施。 E.g。

#!/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库

其他原因:

  • 清晰度 - 显示对其他维护者的意图
  • 速度 - 函数比shell脚本快
  • 可重用性 - 一个函数可以调用另一个函数
  • 可配置性 - 无需编辑原始脚本
  • 调试 - 更容易找到导致错误的行(特别是如果你有大量的重定向/过滤输出)
  • 健壮性 - 如果缺少某个功能并且您无法编辑该脚本,您可以回退使用具有相同名称的外部工具(例如,log_error可以别名为Linux上的记录器)
  • 切换实现 - 您可以通过删除库的“x”属性来切换到外部工具
  • 输出不可知 - 您不再需要关心它是否转到STDERR或其他地方
  • 个性化 - 您可以使用环境变量配置行为

答案 9 :(得分:6)

这已经得到了回答并且获得了很多选票。仅供记录:

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

将有效输出到stderr。说明:/proc/self是指向当前进程的链接,/proc/self/fd包含进程打开的文件描述符。然后,012分别代表stdinstdoutstderr

我发现它更具可读性。这也适用于大多数Linux分发:

echo "my errz" > /dev/stderr

让它更具可读性。

答案 10 :(得分:4)

read是一个shell内置命令,可以打印到stderr,并且可以像echo一样使用而不执行重定向技巧:

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

-t 0.1是一个超时,禁用读取的主要功能,将一行stdin存储到变量中。

答案 11 :(得分:4)

James RothGlenn Jackman建议的组合解决方案

  • 添加ANSI颜色代码以红色显示错误消息:
    df <- c()
for ( i in 1:20) {
  source_frnd <- frnd_20$screen_name[i]
  for(j in 1:20){
    target_frnd <- frnd_20$screen_name[j]
    a<-lookup_friendships(source_frnd,target_frnd)
    df <- rbind(df,a)
  }

}

答案 12 :(得分:2)

制作剧本

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

这将是你的工具。

如果您不想在单独的文件中添加脚本,请创建一个函数。

答案 13 :(得分:2)

Another option that I recently stumbled on is this:

    {
        echo "First error line"
        echo "Second error line"
        echo "Third error line"
    } >&2

This uses only Bash built-ins while making multi-line error output less error prone (since you don't have to remember to add &>2 to every line).

答案 14 :(得分:0)

这是用于检查最后一条命令的退出状态,显示错误并终止脚本的功能。

or_exit() {
    local exit_status=$?
    local message=$*

    if [ "$exit_status" -gt 0 ]
    then
        echo "$(date '+%F %T') [$(basename "$0" .sh)] [ERROR] $message" >&2
        exit "$exit_status"
    fi
}

用法:

gzip "$data_dir"
    or_exit "Cannot gzip $data_dir"

rm -rf "$junk"
    or_exit Cannot remove $junk folder

该函数打印出脚本名称和日期,以便在从crontab调用脚本并记录错误时有用。

59 23 * * * /my/backup.sh 2>> /my/error.log

答案 15 :(得分:-6)

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

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

echo WARNING! | perl -ne 'print STDERR'