bash “模糊输出重定向”试图从发送到 at 的命令将 stdout 和 stderr 发送到 mailx

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/23164614/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-18 10:15:04  来源:igfitidea点击:

"Ambiguous output redirect" trying to send both stdout and stderr to mailx from a command sent to at

linuxbashshellunixio-redirection

提问by tomocafe

I have a bash script called test.shwhich, for the sake of simplicity, prints one line to stdoutand one line to stderr.

我有一个名为test.sh的 bash 脚本,为了简单起见,它向stdout打印一行,向stderr打印一行。

test.sh:

测试.sh:

#!/bin/bash
echo "this is to stdout"
echo "this is to stderr" 1>&2

I want to run the script test.shat 7:00 PM, but only if certain conditions are met. To this end, I have another bash script called schedule.sh, which checks some stuff and then submits the command to atto be run later.

我想在晚上 7:00运行脚本test.sh,但前提是满足某些条件。为此,我有另一个名为schedule.sh 的bash 脚本,它会检查一些东西,然后提交at要稍后运行的命令。

I want the output of test.sh(both stdoutand stderr) to be sent to me in an email. I use mailxto do this so I can get a nice subject name.

我希望test.sh的输出(包括stdoutstderr)通过电子邮件发送给我。我过去mailx常常这样做,所以我可以获得一个很好的主题名称。

Furthermore, I want atto shut up. No output from atbecause it always sends me ugly emails (no subject line) if atproduces any output.

而且,我想at闭嘴。没有输出,at因为如果at产生任何输出,它总是向我发送丑陋的电子邮件(没有主题行)。

schedule.sh:

时间表.sh:

#!/bin/bash
my_email="[email protected]" # Email is a variable
# Check some stuff, exit if certain conditions not met
echo "~/test.sh 2>&1 | mailx -s\"Cool title\" $my_email" | at 7:00 PM &> /dev/null

What's interesting is that when I run schedule.shfrom cron(which runs the script with sh), it works perfectly. However, when I manually run schedule.shfrom the terminal (NB: I'm using tcsh), at(not mailx) sends me an email saying

有趣的是,当我从(用 运行脚本)运行schedule.sh时,它运行良好。但是,当我从终端手动运行schedule.sh 时(注意:我正在使用),(不是)给我发送一封电子邮件说cronshtcshatmailx

Ambiguous output redirect.

I'm not sure why the shell I run schedule.shfrom makes a difference, when schedule.shis a bash script.

schedule.sh是一个 bash 脚本时,我不确定为什么我运行schedule.sh的 shell会有所不同。

Here is my thinking in looking at schedule.sh. Everything within the quotation marks "~/test.sh 2>&1 | mailx -s\"Cool title\" [email protected]"should be an argument to at, and atruns that argument as a command using sh. The redirection 2>&1 |is in the style of shfor this reason.

这是我在查看schedule.sh 时的想法。引号内的所有内容都"~/test.sh 2>&1 | mailx -s\"Cool title\" [email protected]"应该是 的参数at,并at使用 将该参数作为命令运行sh。出于这个原因,重定向2>&1 |的风格是sh

When I remove 2>&1and only pipe the stdoutof test.shto mailx, it does work; however, I receive 2 emails: one with stdoutfrom mailxand another from stderrfrom at.

当我删除2>&1并仅将test.sh标准输出通过管道传输到 时,它确实有效;不过,我收到2封电子邮件:一个标准输出从另一个来自标准错误的。mailxmailxat

What gives? How can I make this work regardless of the shell I'm calling it from?

是什么赋予了?无论我从哪个 shell 调用它,我怎样才能使它工作?

Thanks.

谢谢。

edit:

编辑:

uname -osays my OS is GNU/Linux

uname -o说我的操作系统是 GNU/Linux

Here is uname -aif it helps:

这是uname -a它是否有帮助:

Linux [hostname censored] 2.6.9-89.ELlargesmp #1 SMP Mon Jun 22 12:46:58 EDT 2009 x86_64 x86_64 x86_64 GNU/Linux

When I check the atcontents using at -c, here's what I see:

当我at使用 来检查内容时at -c,我看到的是:

#!/bin/sh
# atrun uid=xxxxx gid=xxxxx
# mail  username 0
# ...
SHELL=/bin/tcsh; export SHELL
# ...
${SHELL:-/bin/sh} << `(dd if=/dev/urandom count=200 bs=1 2>/dev/null|LC_ALL=C tr -d -c '[:alnum:]')`

~/test.sh 2>&1 | mailx -s"Cool title" [email protected]

I'm having a hard time understanding the second to last line... is this going to execute using $SHELL or /bin/sh?

我很难理解倒数第二行...这是要使用 $SHELL 还是执行/bin/sh

采纳答案by Keith Thompson

The command executed via atis:

通过执行的命令at是:

~/test.sh 2>&1 | mailx -s\"Cool title\" $my_email

The behavior of atcommand varies from one system to another. On Linux, the command is executed using /bin/sh. In fact, on my system (Linux Mint 14), it prints a warning message:

at命令的行为因系统而异。在 Linux 上,该命令使用/bin/sh. 事实上,在我的系统(Linux Mint 14)上,它会打印一条警告消息:

$ echo 'printenv > at.env' | at 19:24
warning: commands will be executed using /bin/sh

On Solaris, the command is executed by the shell specified by the current value of the $SHELLenvironment variable. Using an account where my default shell is /bin/tcshon Solaris 9, I get:

在 Solaris 上,命令由$SHELL环境变量的当前值指定的 shell 执行。使用我的默认 shell/bin/tcsh在 Solaris 9 上的帐户,我得到:

% echo 'printenv > at.env' | at 19:25
commands will be executed using /bin/tcsh
job 1397874300.a at Fri Apr 18 19:25:00 2014
% echo 'printenv > at.env' | env SHELL=/bin/sh at 19:28
commands will be executed using /bin/sh
job 1397874480.a at Fri Apr 18 19:28:00 2014

Given that at's behavior is inconsistent (and frankly confusing), I suggest having it execute just a single command, with any I/O redirection being performed inside that command. That's the best way to ensure that the command will be executed correctly regardless of which shell is used to execute it.

鉴于该at的行为不一致(坦率地说令人困惑),我建议让它只执行一个命令,在该命令内执行任何 I/O 重定向。这是确保无论使用哪个 shell 执行命令都能正确执行命令的最佳方法。

For example (untested code follows):

例如(未经测试的代码如下):

echo '#!/bin/bash' > tmp.bash
echo "~/test.sh 2>&1 | mailx -s\"Cool title\" $my_email" >> tmp.bash
chmod +x tmp.bash
echo "./tmp.bash" | at 7:00 PM