Analysis of using skills of RSH remote shell command in Linux

Time:2020-3-25

There are two modes of using RSH:

RSH $host: remote login, start interactive process.
RSH $host $command: executes the command remotely and displays the output.

rsh hosthostcommand

RSH $host $command is used to:

1. Execute command $command on remote machine
2. Redirect standard input and standard output of current process and remote process through network connection (socket)
3. The remote RSH process ends after the end of the remote process
4. The local RSH process reads the standard output of the remote process until the end (EOF)
A deep understanding of the implementation process is helpful to understand various “strange” phenomena and usages.

Copy code

The code is as follows:

+ Suspended (tty input)
$ rsh localhost infinite-loop &
[1] + Suspended (tty input) rsh pv007 infinite-loop
$ rsh -n localhost infinite-loop &
#Normal execution

When executing the RSH command in the background, an error message related to standard input is prompted. This is because RSH redirects the standard input of the current window to the remote process by default.
When the local RSH process runs as a background program, the standard input is blocked.

With the – N option, no redirection of standard input (stdin) is required.

Remote process execution

Executive order

Copy code

The code is as follows:

rsh somehost infinite-loop

To view related processes on a remote machine:

Copy code

The code is as follows:

$ pstree -a -p 3353
in.rshd,3353
└─csh,3363 -c infinite-loop
└─infinite-loop,3632 /u/szhang/bin/infinite-loop

As you can see, the rshd process on the remote machine is responsible for starting the remote process. And you can see that it is started through csh-c (here the user’s default shell is C shell).

Standard IO for remote processes

Check the file descriptor of the remote process:

Copy code

The code is as follows:

$ ls -l /proc/3363/fd /proc/3632/fd
/proc/3363/fd:
total 0
lrwx——. 1 Jul 30 23:47 16 -> socket:[1184748899]
lrwx——. 1 Jul 30 23:47 17 -> socket:[1184748899]
l-wx——. 1 Jul 30 23:47 18 -> pipe:[1184749092]
lrwx——. 1 Jul 30 23:47 19 -> socket:[1184748899]
Copy code

The code is as follows:

/proc/3632/fd:
total 0
lrwx——. 1 Jul 30 23:47 0 -> socket:[1184748899]
lrwx——. 1 Jul 30 23:47 1 -> socket:[1184748899]
l-wx——. 1 Jul 30 23:47 2 -> pipe:[1184749092]

It can be seen that the standard input and output of the remote mileage are redirected to the socket:

1. Stdin and stdout share a socket connection
2. Stderr is redirected through a pipe
3. Return value of RSH

The return value of the RSH program itself indicates the health of RSH itself, not the return value of the remote process.

Get the return value of the remote process

Copy code

The code is as follows:

#The far end is C shell
$ rsh $host “$command ; echo $status”
Copy code

The code is as follows:

#Bash shell at the far end
$ rsh $host “$command ; echo $?”
Copy code

The code is as follows:

#Remote shell type uncertain
$ rsh $host “sh -c ‘$command ; echo $?'”

Shell used to start the remote process

Because the shell type used to start the remote process is unknown, the syntax of some operations is different in different shells.

For example, input and output redirection, command return value, etc.

One way to solve this problem is to start the mileage that you really need by explicitly specifying the shell. For example:

Copy code

The code is as follows:

#Uncertain about the type of remote shell, explicitly start the required process through bash shell
$ rsh -n $host “sh -c ‘$command > /dev/null 2>&1′”

Another idea is to start the real command through a wrapper program.

Remote execution of background process through RSH

You want to execute a background process on a remote machine. The command RSH $host “$Command &” does not work, which will cause the local RSH process not to end.

The reason behind this should be that the standard input and output of $command is usually still bound to the socket of the RSH connection, so that the local RSH process cannot read the EOF.

Knowing the reason, we know what to do. The key is to shut down the background process and continue the standard input and output on the RSH connection.

Copy code

The code is as follows:

#If the remote shell is C shell
$ rsh -n $host “$command >& /dev/null &”
Copy code

The code is as follows:

#If the remote shell is bash shell
$ rsh -n $host “$command > /dev/null 2>&1 &”
Copy code

The code is as follows:

#Uncertain type of remote shell
$ rsh -n $host “sh -c ‘$command > /dev/null 2>&1 &'”

But the disadvantage of the above redirection method is that it can not get the output of any remote process, and sometimes we want to get some output information.
This requires that the remote process be able to run as a daemon.

In this case, the RSH command can be simply written: $RSH – N $host “$Command &”

The content of the remote background process is represented by TCL, with the following general idea:

Copy code

The code is as follows:

#/bin/env tclsh
puts “I am a background job”
puts “This Can Be Seen by Remote rsh Process”
close stdout
close stderr
#The RSH connection should end here.

puts “This Can NOT Be Seen by Remote rsh Process”
Further, we can even ignore the background runer in the RSH command: $RSH – N $host “$command”

At this time, the remote process needs to end itself by fork and start the real background process (daemons).

Blocking and timeout processing of RSH process

When calling RSH $host $command in a program, RSH process blocking may occur for various strange reasons. This is not what we would like to see.

We want to set a timeout mechanism to solve this problem.

An implementation in TCL program can be as follows: todo

RSH failure caused by too many TCP connection connections
The monitoring email shows that the RSH $host $command command command failed, and the error prompt is “poll: Protocol failure in circuit setup”“

It is suspected that it is caused by too many network connections.

Network connection process of RSH $host $command

Command RSH $host to connect to port 513 of the remote host.

The command RSH $host $command connects to port 514 of the remote host, and then sends a local port number to the remote host, asking the remote host to establish a new TCP connection to the port (it is not clear what the new connection does). Then it’s about sending the command and waiting for the command to end.

The result is that when there are too many RSH $host $command processes, the local open port resources are consumed, resulting in the failure of the new RSH $host $command.

This is RSH $host, which is still normal.

The defect of RSH mentioned here is also one of the reasons why we suggest to use SSH as much as possible.

Network connection not completely closed:

After killing the RSH process on the remote host, the TCP connection will not be completely closed.

The netstat command displays the close ﹣ wait status, and the port resources are not released.

According to the configuration file / proc / sys / net / IPv4 / TCP ﹣ keepalive ﹣ time, it takes two hours for those ports to be shut down and released due to timeout.

Copy code

The code is as follows:

%> netstat -a | grep localhost
tcp 0 0 localhost:933 localhost:935 CLOSE_WAIT
%> cat /proc/sys/net/ipv4/tcp_keepalive_time
7200 ;# in seconds. = 2 hours
%> echo “net.ipv4.tcp_keepalive_time = 120” >> /etc/sysctl.con