[comp.unix.questions] What's wrong with this sh script ?

luj@gus17.ecn.purdue.edu (Jun Lu) (03/25/91)

The following attached script can be executed by typing its file 
name(say test.sh) w/ no problem. "sh -x test.sh" also works OK.
But if I try to use the "at -s <time> test.sh", the problem arises.
I got the output(mail) like this:
---
Your "at" job "7148" produced the following output:

gus ...  10:56pm  up 2 days,  5:05,  1 user,  load average: 5.82, 6.24, 6.34
OK
___

But where is the output for 2nd machine ?

By the way the other day /bin/sh reported a syntax error(from within at), 
complaining "unexpected end of file", even though "sh -x test.sh" 
worked fine. I thought there might be some hidden char in the file, so
I manually retyped the script using vi(not emacs). This time I got the
above "truncated" output.(Admittedly, I got other various complaints
from at during debugging,  complaining /bin/sh encountered some 
syntax/parsing error. But I really can not reproduce them now.
 I also jsut rebooted "my" sun3/60 with a 'k2" ...)

Can you guru out there tell me what is wrong(sh problem, rsh problem
at problem, or my problem) ?  I'm running under Sun3/60(and Sparc) with
SunOS4.0.x.  Thanks in advance.

--------- script(devised to illustrate the problem) ---
#! /bin/sh
# NOTE: The intent of this script is NOT to test if the remote machine
# is died; rather it is used to  to illustrtate the problem
#
PATH=/usr/ucb:/bin:/usr/bin
export PATH

USER=luj
HOST=gus
echo -n "$HOST ..."
if rsh -l $USER $HOST uptime
then
    echo OK
else
    echo died
fi

USER=on5
HOST=mace.cc
echo -n "$HOST ..."
if rsh -l $USER $HOST uptime
then
    echo OK
else
    echo died
fi
--------------- end of the script --------------

--
-- Jun Lu                          Internet:luj@ecn.purdue.edu          --
-- Aeronautics & Astronautics      Bitnet:  luj%ecn.purdue.edu@purccvm  --
-- Purdue University               UUCP:    pur-ee!luj                  -- 
-- W. Lafayette, IN 47907          Phone:317-494-9410  Fax:317-494-0307 --

pfalstad@phoenix.Princeton.EDU (Paul Falstad) (03/25/91)

luj@gus17.ecn.purdue.edu (Jun Lu) wrote:
>Your "at" job "7148" produced the following output:
>
>gus ...  10:56pm  up 2 days,  5:05,  1 user,  load average: 5.82, 6.24, 6.34
>OK
>___
>
>But where is the output for 2nd machine ?

...

>echo -n "$HOST ..."
>if rsh -l $USER $HOST uptime
>then
>    echo OK
>else
>    echo died
>fi

The problem is that rsh eats up its standard input, which also happens
to be the shell script you're executing, since at gives your script to
the shell as standard input.  So when you rsh to the first
host, while you're waiting for uptime to execute, rsh reads its input
(your shell script), and sends it over the socket.  Then uptime
exits without reading anything.  Now when the shell wakes up and tries
to read the rest of your script, it gets an EOF, since rsh has eaten up
all its input.  The reason that the shell managed to print the OK is because
the rsh was part of a control structure; the shell read in the whole if ... fi
structure before executing rsh.  Nothing after the fi was executed.  You can
try for yourself that if you put the whole script in braces { }, forcing the
shell to parse all of it before executing, it will work fine.

The easiest way to fix this is just to use the -n flag of rsh.

rsh -n -l $USER $HOST uptime

Read the FM for more information.

--
Paul Falstad, pfalstad@phoenix.princeton.edu | 10 PRINT "PRINCETON CS"
[Your blood pressure just went up.]          | 20 GOTO 10
Princeton University would like to apologize to everyone for this article.