"Ambiguous output redirect" trying to send both stdout and stderr to mailx from a command sent to at
The command executed via at
is:
~/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:
$ 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:
% 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.
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
tomocafe
Updated on April 22, 2020Comments
-
tomocafe about 4 years
I have a bash script called test.sh which, for the sake of simplicity, prints one line to stdout and one line to stderr.
test.sh:
#!/bin/bash echo "this is to stdout" echo "this is to stderr" 1>&2
I want to run the script test.sh at 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.I want the output of test.sh (both stdout and stderr) to be sent to me in an email. I use
mailx
to do this so I can get a nice subject name.Furthermore, I want
at
to shut up. No output fromat
because it always sends me ugly emails (no subject line) ifat
produces any output.schedule.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.sh from
cron
(which runs the script withsh
), it works perfectly. However, when I manually run schedule.sh from the terminal (NB: I'm usingtcsh
),at
(notmailx
) sends me an email sayingAmbiguous output redirect.
I'm not sure why the shell I run schedule.sh from makes a difference, when schedule.sh is a bash script.
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 toat
, andat
runs that argument as a command usingsh
. The redirection2>&1 |
is in the style ofsh
for this reason.When I remove
2>&1
and only pipe the stdout of test.sh tomailx
, it does work; however, I receive 2 emails: one with stdout frommailx
and another from stderr fromat
.What gives? How can I make this work regardless of the shell I'm calling it from?
Thanks.
edit:
uname -o
says my OS isGNU/Linux
Here is
uname -a
if it helps: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 usingat -c
, here's what I see:#!/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
?