我想将流程的标准输出和标准错误重定向到单个文件。我在巴什怎么做?
当前回答
简短回答:命令>文件名2>&1或命令>>文件名
说明:
考虑以下代码,该代码将单词“stdout”打印到stdout,将单词“tderror”打印到tderror。
$ (echo "stdout"; echo "stderror" >&2)
stdout
stderror
注意,“&”操作符告诉bash 2是文件描述符(指向stderr),而不是文件名。如果省略了“&”,该命令将stdout打印到stdout,并创建一个名为“2”的文件,并在其中写入stderror。
通过尝试上面的代码,您可以亲眼看到重定向操作符是如何工作的。例如,通过更改两个描述符1、2中的哪个文件被重定向到/dev/null,以下两行代码分别从stdout和stderror中删除所有内容(打印剩余内容)。
$ (echo "stdout"; echo "stderror" >&2) 1>/dev/null
stderror
$ (echo "stdout"; echo "stderror" >&2) 2>/dev/null
stdout
现在,我们可以解释为什么以下代码不产生输出的解决方案:
(echo "stdout"; echo "stderror" >&2) >/dev/null 2>&1
为了真正理解这一点,我强烈建议您阅读有关文件描述符表的网页。假设你已经完成了阅读,我们可以继续。注意,Bash从左到右处理;因此,Bash首先看到>/dev/null(这与1>/dev/null相同),并将文件描述符1设置为指向/dev/null而不是stdout。完成此操作后,Bash向右移动,看到2>&1。这将文件描述符2设置为指向与文件描述符1相同的文件(而不是指向文件描述符1本身!!!!(有关详细信息,请参阅此指针资源))。由于文件描述符1指向/dev/null,文件描述符2指向与文件描述符1相同的文件,因此文件描述符2现在也指向/dev/null。因此,两个文件描述符都指向/dev/null,这就是为什么不呈现输出。
为了测试您是否真正理解这个概念,请尝试在切换重定向顺序时猜测输出:
(echo "stdout"; echo "stderror" >&2) 2>&1 >/dev/null
标准错误
这里的理由是,从左到右计算,Bash看到2>&1,因此将文件描述符2设置为指向与文件描述符1相同的位置,即stdout。然后,它将文件描述符1(记住>/dev/null=1>/dev/null)设置为指向>/dev/null,从而删除通常发送到标准输出的所有内容。因此,我们只剩下未发送到子shell中的stdout的代码(括号中的代码),即“stderror”。值得注意的是,尽管1只是指向stdout的指针,但通过2>&1将指针2重定向到1不会形成指针链2->1->stdout。如果这样做了,作为将1重定向到/dev/null的结果,代码2>&1>/dev/null将给出指针链2->1->/dev/null,因此代码将不会生成任何内容,与我们上面看到的相反。
最后,我要指出,有一种更简单的方法可以做到这一点:
从这里的第3.6.4节中,我们可以看到我们可以使用运算符&>来重定向stdout和stderr。因此,要将任何命令的stderr和stdout输出重定向到\dev\null(这会删除输出),只需键入$command&>/dev/null或者在我的例子中:
$ (echo "stdout"; echo "stderror" >&2) &>/dev/null
关键要点:
文件描述符的行为类似于指针(尽管文件描述符与文件指针不同)将文件描述符“a”重定向到指向文件“f”的文件描述符“b”,会导致文件描述符“a”指向与文件描述符b-file“f”相同的位置。它不会形成指针链a->b->f由于以上原因,顺序很重要,2>&1>/dev/null是!=>/dev/null 2>&1。一个生成输出,另一个不生成!
最后看看这些伟大的资源:
重定向的Bash文档,文件描述符表的解释,指针介绍
其他回答
看看这里。应该是:
yourcommand &> filename
它将标准输出和标准错误重定向到文件名。
除了费南多·法布雷蒂所做的,我稍微改变了一下功能,去掉了&关闭,这对我来说很有用。
function saveStandardOutputs {
if [ "$OUTPUTS_REDIRECTED" == "false" ]; then
exec 3>&1
exec 4>&2
trap restoreStandardOutputs EXIT
else
echo "[ERROR]: ${FUNCNAME[0]}: Cannot save standard outputs because they have been redirected before"
exit 1;
fi
}
# Parameters: $1 => logfile to write to
function redirectOutputsToLogfile {
if [ "$OUTPUTS_REDIRECTED" == "false" ]; then
LOGFILE=$1
if [ -z "$LOGFILE" ]; then
echo "[ERROR]: ${FUNCNAME[0]}: logfile empty [$LOGFILE]"
fi
if [ ! -f $LOGFILE ]; then
touch $LOGFILE
fi
if [ ! -f $LOGFILE ]; then
echo "[ERROR]: ${FUNCNAME[0]}: creating logfile [$LOGFILE]"
exit 1
fi
saveStandardOutputs
exec 1>>${LOGFILE}
exec 2>&1
OUTPUTS_REDIRECTED="true"
else
echo "[ERROR]: ${FUNCNAME[0]}: Cannot redirect standard outputs because they have been redirected before"
exit 1;
fi
}
function restoreStandardOutputs {
if [ "$OUTPUTS_REDIRECTED" == "true" ]; then
exec 1>&3 #restore stdout
exec 2>&4 #restore stderr
OUTPUTS_REDIRECTED="false"
fi
}
LOGFILE_NAME="tmp/one.log"
OUTPUTS_REDIRECTED="false"
echo "this goes to standard output"
redirectOutputsToLogfile $LOGFILE_NAME
echo "this goes to logfile"
echo "${LOGFILE_NAME}"
restoreStandardOutputs
echo "After restore this goes to standard output"
在考虑使用exec2>&1之类的情况下,如果可能的话,我发现使用如下Bash函数重写代码更容易阅读:
function myfunc(){
[...]
}
myfunc &>mylog.log
您可以将stderr重定向到stdout,并将stdout重定向到文件中:
some_command >file.log 2>&1
见第20章。I/O重定向
这种格式比最流行的仅适用于Bash的&>格式更受欢迎。在Bourne shell中,它可以解释为在后台运行命令。格式也更可读-2(标准错误)重定向为1(标准输出)。
奇怪的是,这是有效的:
yourcommand &> filename
但这会产生语法错误:
yourcommand &>> filename
syntax error near unexpected token `>'
您必须使用:
yourcommand 1>> filename 2>&1
推荐文章
- 如何从查找“类型d”中排除此/ current / dot文件夹
- 检查bash变量是否等于0
- 只使用md5sum获取哈希值(没有文件名)
- 如何生成一个核心转储在Linux上的分段错误?
- 使用sh shell比较字符串
- 在Bash中测试非零长度字符串:[-n "$var"]或["$var"]
- 如何删除超过X小时的文件
- 如何创建Bash别名?
- 如何设置ssh超时时间?
- 将所有变量从一个shell脚本传递到另一个?
- 只列出UNIX中的目录
- 如何删除shell脚本中文件名的扩展名?
- 使用xargs调用shell函数
- 如何限制从grep返回的结果的数量?
- 'find -exec'是Linux中的shell函数