• 企业400电话
  • 微网小程序
  • AI电话机器人
  • 电商代运营
  • 全 部 栏 目

    企业400电话 网络优化推广 AI电话机器人 呼叫中心 网站建设 商标✡知产 微网小程序 电商运营 彩铃•短信 增值拓展业务
    Linux中rsh远程shell命令的使用技巧解析

    rsh有两种使用模式:

    rsh $host : 远程登录,启动交互式进程。
    rsh $host $command :远程执行命令,并显示输出。

    rsh hosthostcommand

    rsh $host $command的作用是:

    1.在远程机器上执行命令$command
    2.通过网络连接(socket)重定向当前进程和远端进程的标准输入和标准输出
    3.远端rsh进程在远端进程结束后结束
    4.本地rsh进程读取远端进程的标准输出直到结束(EOF)
    深刻理解这个执行过程有助于理解各种“奇怪”的现象和用法。

    复制代码
    代码如下:

    + Suspended (tty input)
    $ rsh localhost infinite-loop
    [1] + Suspended (tty input) rsh pv007 infinite-loop
    $ rsh -n localhost infinite-loop
    # 执行正常

    后台执行rsh命令时,提示了和标准输入相关的错误信息。这是因为rsh默认会把当前窗口的标准输入重定向到远端进程。
    而本地rsh进程作为后台程序运行的话,标准输入被“阻塞”了。

    通过-n选项制定不需要重定向标准输入(stdin)。


    远端进程的执行

    执行命令

    复制代码
    代码如下:
    rsh somehost infinite-loop

    在远端机器上查看相关进程:

    复制代码
    代码如下:

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

    可以看出,远端机器上的rshd进程负责启动远端进程。而且可以看出是通过csh -c的方式启动的(这里用户的默认Shell是C Shell)。

    远端进程的标准IO

    检查远端进程的文件描述符:

    复制代码
    代码如下:

    $ 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]


    复制代码
    代码如下:

    /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]

    可以看出远端里程的标准输入输出是被重定向到socket上的:

    1.stdin 和 stdout 共享一个socket连接
    2.stderr 则通过一个pipe重定向(重定向到stdout ???)
    3.rsh 的返回值

    rsh程序自身的返回值表明的是rsh自身的运行状况,而不是远端进程的返回值。

    获得远端进程的返回值

    复制代码
    代码如下:

    # 远端是C Shell
    $ rsh $host "$command ; echo $status"


    复制代码
    代码如下:

    # 远端是Bash Shell
    $ rsh $host "$command ; echo $?"


    复制代码
    代码如下:

    # 远端Shell类型不确定
    $ rsh $host "sh -c '$command ; echo $?'"

    启动远端进程所用的Shell

    由于用于启动远端进程的Shell类型是未知的,而有些操作的语法在不同Shell里是不同的。

    比如输入输出重定向、命令返回值等。

    解决该问题的方法之一是通过明确指定的Shell来启动真正需要的里程。比如:

    复制代码
    代码如下:

    # 不确定远端Shell的类型,显式通过Bash Shell来启动需要的进程
    $ rsh -n $host "sh -c '$command > /dev/null 2>1'"

    另一种思路,则是通过一个wrapper程序来启动真正的命令。

    通过rsh在远端执行后台进程

    想在远端机器上执行后台进程。命令rsh $host "$command "是不起作用的,会导致本地的rsh进程不能结束。

    背后的原因应该是,$command的标准输入输出通常仍然绑定在rsh连接的socket上,从而导致本地的rsh进程无法读取到文件结束符EOF。

    知道了原因就知道该怎么办了,关键是关闭后台进程续定在rsh连接上的标准输入输出。

    复制代码
    代码如下:

    # 如果远端Shell是C Shell
    $ rsh -n $host "$command > /dev/null "


    复制代码
    代码如下:

    # 如果远端Shell是Bash Shell
    $ rsh -n $host "$command > /dev/null 2>1 "


    复制代码
    代码如下:

    # 不确定远端Shell的类型
    $ rsh -n $host "sh -c '$command > /dev/null 2>1 '"

    但上面这样重定向的办法有个缺点是不能得到任何远端进程的输出,而有时我们希望获得一些输出信息。
    这时就需要远端进程能够以守护进程(daemon)的方式运行。

    这种情况下,rsh命令可以简单地写作:$ rsh -n $host "$command "

    远端后台进程的内容用Tcl表示,大意如下:

    复制代码
    代码如下:

    #/bin/env tclsh
    puts "I am a background job"
    puts "This Can Be Seen by Remote rsh Process"
    close stdout
    close stderr
    # rsh连接到此应该结束。

    puts "This Can NOT Be Seen by Remote rsh Process"
    更进就步,我们可以甚至忽略rsh命令中的后台运行符:$ rsh -n $host "$command"

    这时远端进程需要通过fork的方式结束自己,并启动真正的后台进程(守护进程)。

    rsh进程的阻塞和超时处理

    在程序中调用rsh $host $command时可能由于各种奇怪的原因发生rsh进程的阻塞,这不是我们希望看到的。

    我们希望设置一个超时(timeout)机制来解决这个问题。

    在Tcl程序中的一种实现可以这样: TODO


    TCP Connection连接数过多引起的rsh失败
    监控邮件显示rsh $host $command命令失败,错误提示为“poll: protocol failure in circuit setup"

    怀疑是网络连接数过多所引起。

    rsh $host $command 的网络连接过程

    命令rsh $host连接远程主机的513端口。

    命令rsh $host $command则连接远程主机的514端口,并随后发送一个本地端口号给远程主机,要求远程主机建立一个新的TCP连接到这个端口(还不清楚这个新的连接有什么作用)。然后才是传送命令和等待命令结束。

    这样做的结果就是在rsh $host $command进程过多时,本地开放的端口资源被消耗完了,从而导致新的rsh $host $command失败。

    这是rsh $host的使用则依然正常。

    这里提到的rsh的缺陷,也是建议尽量使用ssh的原因之一。

    没有完全关闭的网络连接:

    在远程主机上kill掉相关的rsh进程后,会导致TCP连接没有完全关闭。

    netstat命令显示CLOSE_WAIT状态,端口资源并没有释放出来。

    根据配置文件/proc/sys/net/ipv4/tcp_keepalive_time显示,需要等待2个小时,那些端口才会因为超时而被真正关闭,从而释放出来。

    复制代码
    代码如下:

    %> 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

    上一篇:Linux上设置用户通过SFTP访问目录的权限的方法
    下一篇:linux/aix怎么用命令查看某个目录下子目录占用空间的大小?
  • 相关文章
  • 

    © 2016-2020 巨人网络通讯 版权所有

    《增值电信业务经营许可证》 苏ICP备15040257号-8

    Linux中rsh远程shell命令的使用技巧解析 Linux,中,rsh,远程,shell,命令,