是否有一个标准的Bash工具,它像echo一样但输出到stderr而不是stdout?
我知道我可以做echo foo 1>&2
但是它有点难看,而且我怀疑,容易出错(例如,当事情发生变化时更有可能被编辑错误)。
答案 0 :(得分:1180)
这个问题很老,但你可以这样做,这有利于阅读:
>&2 echo "error"
运算符>&2
字面意思是将文件描述符1(stdout
)的地址重定向到该命令 1 stderr)的地址>。根据您想要了解它的深度,请阅读:http://wiki.bash-hackers.org/howto/redirection_tutorial
为避免与其他重定向的交互,请使用subshell
(>&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
是程序
而echo
和printf
是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问题的原因:
其他原因:
答案 9 :(得分:6)
这已经得到了回答并且获得了很多选票。仅供记录:
echo "my errz" > /proc/self/fd/2
将有效输出到stderr
。说明:/proc/self
是指向当前进程的链接,/proc/self/fd
包含进程打开的文件描述符。然后,0
,1
和2
分别代表stdin
,stdout
和stderr
。
我发现它更具可读性。这也适用于大多数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 Roth和Glenn Jackman建议的组合解决方案
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'