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
"Ambiguous output redirect" trying to send both stdout and stderr to mailx from a command sent to at
提问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 at
to 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 mailx
to do this so I can get a nice subject name.
我希望test.sh的输出(包括stdout和stderr)通过电子邮件发送给我。我过去mailx
常常这样做,所以我可以获得一个很好的主题名称。
Furthermore, I want at
to shut up. No output from at
because it always sends me ugly emails (no subject line) if at
produces 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 时(注意:我正在使用),(不是)给我发送一封电子邮件说cron
sh
tcsh
at
mailx
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 at
runs that argument as a command using sh
. The redirection 2>&1 |
is in the style of sh
for this reason.
这是我在查看schedule.sh 时的想法。引号内的所有内容都"~/test.sh 2>&1 | mailx -s\"Cool title\" [email protected]"
应该是 的参数at
,并at
使用 将该参数作为命令运行sh
。出于这个原因,重定向2>&1 |
的风格是sh
。
When I remove 2>&1
and only pipe the stdoutof test.shto mailx
, it does work; however, I receive 2 emails: one with stdoutfrom mailx
and another from stderrfrom at
.
当我删除2>&1
并仅将test.sh的标准输出通过管道传输到 时,它确实有效;不过,我收到2封电子邮件:一个标准输出从另一个来自标准错误的。mailx
mailx
at
What gives? How can I make this work regardless of the shell I'm calling it from?
是什么赋予了?无论我从哪个 shell 调用它,我怎样才能使它工作?
Thanks.
谢谢。
edit:
编辑:
uname -o
says my OS is GNU/Linux
uname -o
说我的操作系统是 GNU/Linux
Here is uname -a
if 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 at
contents 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 at
is:
通过执行的命令at
是:
~/test.sh 2>&1 | mailx -s\"Cool title\" $my_email
The behavior of at
command 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 $SHELL
environment variable. Using an account where my default shell is /bin/tcsh
on 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