我希望能够执行以下操作:
command 2>&1 | shell_script.sh "subject line"
运行的 stdout 和 sterrcommand
将通过管道传输到其中,shell_script.sh
以作为电子邮件正文发送。我想要获得的是退出状态,command 2>&1
以便我可以将正确的工作状态附加到电子邮件主题。在当前的实现中,当command 2>&1
是通过管道传输时,${PIPESTATUS[0]}
始终设置为0
。但是,如果我删除2>&1
,则 stderr 输出不会通过管道传输到电子邮件正文中。尝试过几种不同的变体,但仍然无法弄清楚。
以下是我的shell_script.sh
:
#!/usr/bin/env bash
SUBJ="$@"
read EMAIL_BODY
jobsuccess=${PIPESTATUS[0]}
if [ $jobsuccess -eq 0 ] # Job succeeded
then
echo $EMAIL_BODY | mail -s "$SUBJ Success" [email protected]
else
echo $EMAIL_BODY | mail -s "$SUBJ Fail" [email protected]
fi
答案1
#!/bin/bash
subject="subject line"
tmpfile=$(mktemp)
trap 'rm -f "$tmpfile"' EXIT
if command >"$tmpfile" 2>&1; then
subject+=" Success"
else
subject+=" Failure"
fi
mail -s "$subject" [email protected] <"$tmpfile"
因此,将输出保存到临时文件,然后邮寄该文件。发送前根据命令的退出状态设置主题行。不需要两个脚本。
您无法访问PIPESTATUS
管道内部,因为管道尚未执行完毕。此外,外部脚本在任何情况下都无法访问它,因为它在自己的环境中运行。
同样不可能的是通过管道传输来自通用命令的输入,然后对该命令的退出状态进行操作。无法从管道本身访问管道中前一个命令的退出状态。
你什么可以do 是将命令包装在输出一段文本的代码中,表示成功或失败。该文本将与其余数据一起通过管道传输(必要时,作为最后的额外信息):
{ if command 2>&1; then echo SUCCESS; else echo FAILURE; } | shell_script.sh
...与shell_script.sh
存在
#!/bin/bash
subject="subject line"
tmpfile=$(mktemp)
trap 'rm -f "$tmpfile"' EXIT
cat >"$tmpfile"
if [[ $(tail -n 1 "$tmpfile") == *SUCCESS* ]]; then
subject+=" Success"
else
subject+=" Failure"
fi
sed '$d' "$tmpfile" | mail -s "$subject" [email protected]
这仍然需要将数据保存到临时文件中才能访问它的最后一行(这是使用cat
默认情况下读取标准输入来完成的)。然后它决定它是否成功并相应地设置主题。然后,删除最后一行的数据将被邮寄。
另一种选择是运行邮件脚本后运行命令(管道中的命令同时执行),然后只需将退出状态作为命令行参数传递即可:
command >command.log 2>&1
shell_script.sh "$?" <command.log
rm -f command.log
脚本看起来像
#!/bin/bash
subject="subject line"
if [[ $1 == 0 ]]; then
subject+=" Success"
else
subject+=" Failure"
fi
mail -s "$subject" [email protected]
在这种情况下,要邮寄的数据通过标准输入传递,mail
实用程序将默认读取该输入(就像cat
前面的示例中所做的那样)。