[comp.unix.wizards] RSH

duane@anasaz.UUCP (Duane Morse) (12/13/89)

Is it a feature of rsh that the process started on the remote end
and all of its children terminate before the remote shell (and its
partner on the local side) terminate? That seems to be the way it
works on our Pyramid MIS machine and a couple of 386/IX boxes. It
doesn't matter if I do a nohup and/or run things in background; server
processes on both ends stick around until everything on the remote
side terminates.
-- 

Duane Morse	e-mail: duane@anasaz (or ... asuvax!anasaz!duane)
(602) 861-7609

chris@mimsy.umd.edu (Chris Torek) (12/13/89)

In article <1035@anasaz.UUCP> duane@anasaz.UUCP (Duane Morse) writes:
>Is it a feature of rsh that the process started on the remote end
>and all of its children terminate before the remote shell (and its
>partner on the local side) terminate? That seems to be the way it
>works on our Pyramid MIS machine and a couple of 386/IX boxes.

No; that is not how it works.  Rsh waits not for processes to exit,
but rather for EOF on its socket.  Since the socket is naturally
closed once all processes exit, this will cause rsh to finish; however,
by closing the socket earlier, rsh will get an EOF sooner, and
it will finish sooner:

#! /bin/sh
#
# xrsh - start an X11 process on another host
#
# simply exports $DISPLAY, and runs the given command

case $# in
0|1) echo "usage: $0 host cmd [args]" 1>&2; exit 1;;
esac

: ${DISPLAY?"no DISPLAY environment variable"}

host="$1"
shift

rsh $host -n "setenv DISPLAY $DISPLAY; exec $@ </dev/null >&/dev/null"
-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163)
Domain:	chris@cs.umd.edu	Path:	uunet!mimsy!chris

gwyn@smoke.BRL.MIL (Doug Gwyn) (12/14/89)

In article <1035@anasaz.UUCP> duane@anasaz.UUCP (Duane Morse) writes:
>Is it a feature of rsh that the process started on the remote end
>and all of its children terminate before the remote shell (and its
>partner on the local side) terminate? That seems to be the way it
>works on our Pyramid MIS machine and a couple of 386/IX boxes. It
>doesn't matter if I do a nohup and/or run things in background; server
>processes on both ends stick around until everything on the remote
>side terminates.

I frankly didn't understand what you were asking, but here is how
4.3BSD "rsh" functions on the remote end:

On the remote system, the rshd process that inetd starts up to service
the connection forks into two processes.  The child is overlaid by the
command that you specified when invoking "rsh". The child's stdin and
stdout are connected to one socket, and the child's stderr is piped
to the rshd parent, which merely routes stderr and signal information
through a second socket.

If the overlaid rshd child terminates, the rshd parent will notice
this (read on a broken pipe used for child stderr) and also go away,
severing the second socket connection.  (The first was severed when
the child terminated.)

By the way, if you don't specify a command then 4.3BSD "rsh" invokes
"rlogin" instead, which uses a different protocol.

richard@aiai.ed.ac.uk (Richard Tobin) (12/14/89)

In article <21262@mimsy.umd.edu> chris@mimsy.umd.edu (Chris Torek) writes:

>rsh $host -n "setenv DISPLAY $DISPLAY; exec $@ </dev/null >&/dev/null"

But beware of mutant csh-derivatives that fail to ensure that FSHIN etc
are closed when exec()ing.  I found this in a variant of tcsh recently.
How it crept in I don't know.

-- Richard


-- 
Richard Tobin,                       JANET: R.Tobin@uk.ac.ed             
AI Applications Institute,           ARPA:  R.Tobin%uk.ac.ed@nsfnet-relay.ac.uk
Edinburgh University.                UUCP:  ...!ukc!ed.ac.uk!R.Tobin

duane@anasaz.UUCP (Duane Morse) (12/18/89)

In article <1035@anasaz.UUCP>, duane@anasaz.UUCP (Duane Morse) writes:
> Is it a feature of rsh that the process started on the remote end
> and all of its children terminate before the remote shell (and its
> partner on the local side) terminate?

Thanks for the e-mail and the Usenet postings. In summary, most people
seem to think that redirecting stdin, stdout, and stderr to /dev/null on the
target host should be sufficient to allow the rsh on the local host to terminate
without waiting for the program(s) on the target to terminate. That isn't
the case on the two 5.3 machines we have.

In particular, between one 386/ix machine and another 386/ix machine,
it appears necessary to run both sides with I/O redirected to /dev/null.
Further, one must run the target side 'nohup'. Example:
rsh target 'nohup prog </dev/null >/dev/null 2>&1 &' </dev/null >/dev/null 2>&1

Between two Pyramid MIS machines, even this extreme doesn't work; the
local rsh just plan hangs around until target is done. This is a Pyramid
peculiarity; it occurs even if the host is a 386/ix machine. The
other arrangement works if the host is the Pyramid and the target is a
386/ix machine. [Note: on the Pyramid, this is the AT&T universe I'm
talking about.]

Hence, some combination of 'nohup', redirecting I/O to /dev/null, and
running the target program(s) in background should work, but the combination
that works for your machines may vary.
-- 

Duane Morse	e-mail: duane@anasaz (or ... asuvax!anasaz!duane)
(602) 861-7609

seth@ctr.columbia.edu (Seth Robertson) (12/20/89)

I had the same problem under SunOS 4.0 (just closing stdin/out/err didn't
work) so I wrote a small program to close everything.  The major part of
the program is this:

  for (fd = 0; fd < getdtablesize(); fd++)
    close (fd);

everything else is just support and other things which are nice but
not necessary.

Here is the complete program:
[Usage:  rsh -n host unrsh rprocess]

#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of shell archive."
# Contents:  /home/sirius/seth/c/unrsh.c
# Wrapped by seth@sirius on Tue Dec 19 11:04:17 1989
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f '/home/sirius/seth/c/unrsh.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'/home/sirius/seth/c/unrsh.c'\"
else
echo shar: Extracting \"'/home/sirius/seth/c/unrsh.c'\" \(1750 characters\)
sed "s/^X//" >'/home/sirius/seth/c/unrsh.c' <<'END_OF_FILE'
X/*
X** Program to unrshfy a process
X**
X** (if a process was started by rsh, this will make the rsh stuff die)
X**
X** This program has been tested under SunOS4.0
X**
X** This program has been placed in the public domain.  There are no
X** restrictions on its distribution, and no one is responsible for
X** anything that might occur do to the use of this program.
X*/
X
X/* I probably don't need all of these... */
X#include <stdio.h>
X#include <ctype.h>
X#include <sys/types.h>
X#include <sys/stat.h>
X#include <sys/file.h>
X#include <time.h>
X#include <errno.h>
X#include <fcntl.h>
X#include <signal.h>
X#include <sys/file.h>
X#include <sys/ioctl.h>
X#include <sys/param.h>
X
X
Xmain(argc,argv,envp)
X
Xint argc;
Xchar **argv;
Xchar **envp;
X
X{
X  int	pid;			/* Process id of child */
X  register int fd;		/* File desc. */
X  int 	err = 0;		/* Error variable */
X
X				/* bail on a controlling tty, if any */
X  if ((fd = open ("/dev/tty", O_RDWR)) >= 0)
X    {
X      err = (err << 1) | (ioctl (fd, TIOCNOTTY, (char *) 0) == -1);
X      err = (err << 1) | (close (fd) == -1);
X    }
X  
X  /* The following command will get rid of the stupid in.rshd
X   * process
X   */
X				/* close all files */
X  for (fd = 0; fd < getdtablesize(); fd++)
X    close (fd);
X
X				/* Open stdin/out/err */
X  err = (err << 1) | (open ("/dev/null", O_RDONLY) == -1);
X  err = (err << 1) | (open ("/dev/null", O_WRONLY) == -1);
X  err = (err << 1) | (open ("/dev/null", O_WRONLY) == -1);
X
X				/* detach from process group */
X  err = (err << 1) | (setpgrp (0, (pid = getpid ())) == -1);
X  
X  
X				/* check for errors before running program */
X  err <<= 1;
X
X  if (err)			/* Run the program if no error */
X    exit(1);			/* Not much we can do */
X
X  argv++;
X
X  execvp(*argv, argv);
X
X  perror("s: execvp");
X  exit(-1);
X}
END_OF_FILE
if test 1750 -ne `wc -c <'/home/sirius/seth/c/unrsh.c'`; then
    echo shar: \"'/home/sirius/seth/c/unrsh.c'\" unpacked with wrong size!
fi
# end of '/home/sirius/seth/c/unrsh.c'
fi
echo shar: End of shell archive.
exit 0

                                        -Seth Robertson
                                         seth@ctr.columbia.edu