如何将输出从一个进程传输到另一个进程,但仅在第一个进程有输出时才执行?

如何将输出从一个进程传输到另一个进程,但仅在第一个进程有输出时才执行?

如果有输出,如何将此命令重写为仅发送电子邮件mailq | grep

mailq | egrep 'rejected|refused' -A 5 -B 5 | mail -s 'dd' email@email

这甚至可以在一条线上实现吗?

检查管道是否为空,如果不是则对数据运行命令对于比发送电子邮件更一般的情况。

答案1

我认为您必须使用临时文件来执行此操作,以便您可以使用运算&&符仅在 grep 返回退出状态表明它具有如下匹配项时运行邮件命令:

TMPFILE=`mktemp /tmp/mailqgrep.XXXXXX`; mailq | egrep 'rejected|refused' -A5 -B5 > "$TMPFILE" && mail -s 'dd' email@email < "$TMPFILE"; rm "$TMPFILE"

如果您不介意临时文件保留在某处并且可以为其使用静态名称,则可以跳过特殊的命名和删除内容:

 mailq | egrep 'rejected|refused' -A5 -B5 > /tmp/mailqgrep && mail -s 'dd' email@email < /tmp/mailqgrep

编辑:看到后格伦的回答我又玩了一些,显然使用$()语法分配一个变量会返回命令的退出代码,因此您可以跳过他用于字符串长度的测试并使用它。这一切都在一个命令中:

data=$(mailq | egrep 'rejected|refused' -A 5 -B 5) && mail -s 'dd' email@email <<< "$data"

编辑2:看到后西蒙的回答我检查了我的mail程序。它的行为方式与他所描述的默认方式不同,但确实有一个选项。从手册页:

-E如果传出消息的第一个或唯一的消息部分不包含任何文本,则不发送它,而是静默丢弃它,从而在程序启动时有效地设置skipemptybody变量。这对于从 cron(8) 启动的脚本发送消息非常有用。

使这成为可能:

mailq | egrep 'rejected|refused' -A 5 -B 5 | mail -E -s 'dd' email@email

答案2

实用程序伊夫内明确出于此目的而存在:如果标准输入不为空,则运行命令。

mailq | egrep 'rejected|refused' -A 5 -B 5 | ifne mail -s 'dd' email@email

ifne 命令是更多实用程序包,被宣传为“一个不断增长的 Unix 工具集合,很久以前,当 Unix 还很年轻的时候,没有人想到要编写这些工具”。

答案3

您可以将输出保存在变量中,然后在字符串长度非零时调用 mail 命令。

data=$(mailq | egrep 'rejected|refused' -A 5 -B 5)
[[ -n "$data" ]] && mail -s 'dd' email@email <<< "$data"

对于一行,用分号连接两个命令。

答案4

在这种特殊情况下,如果您mail支持该-E选项,就用它吧。一般情况下,可以尝试读一个字;如果有,则启动后处理命令并从文件的其余部分向其提供该字符。

pipe_if_not_empty () {
  a=$(dd bs=1 count=1 2>/dev/null; echo .)  # read at most one character
  if [ "$a" != "." ]; then                  # if there were two characters,
    { printf %s "${a%.}";                   # then output the first character
      cat; } |                              # and the rest of the input   
    "$@"                                    # into the specified program
  fi
}

mailq | egrep 'rejected|refused' -A 5 -B 5 |
pipe_if_not_empty mail -s 'dd' email@email

注意 的有用用法cat。添加echo .使得即使输入中的第一个字符是换行符也可以使该函数起作用(请记住该$(…)构造会去除终端换行符)。

对于大多数 shell(据我所知,除了 zsh 之外的任何 shell),如果文件以空字符开头,则此代码将认为它是空的。解决这个问题留给读者作为练习。 (提示:od在第一个子 shell 中使用并printf打印第一个字节。)(解决方案:如何检查管道是否为空) 如果文件以在当前语言环境中不是有效字符的字节开头,您可能会遇到相同的问题;通过使用 运行此代码更容易修复此问题LC_ALL=C

相关内容