注:这是一个没什么鸟用的功能。不过也算是一种拓展。

通常在那些"一键化部署"的shell脚本中,可能需要使用ssh执行远程命令来实现一些简单的自动化,这些远程命令可能需要执行一段时间才能结束(如yum命令)。例如,远程ssh配置yum源,远程ssh安装软件包。

为了让脚本实现"并行"执行,这个远程ssh命令往往还会加上"-f"选项使其进入后台执行。此时,如果后续的远程任务正好要依赖于这个命令已经执行完成,那么我们要判断前面的任务是否执行完成。例如,在配置软件的时候,必须先判断软件是否安装结束。

判断的方式挺简单,只需判断这个ssh进程是否存在就可以了。例如:

[root@node1 ~]# ssh 192.168.100.101 -f 'yum makecache'
[root@node1 ~]# killall -s 0 ssh
[root@node1 ~]# echo $?

这样的方法没错,也能应付绝大多数情况,但如果有多个远程后台命令的ssh进程,就无法知道具体是哪个ssh进程。

于是,可以采用另一种方法,将执行远程命令的ssh进程放进后台,再用$!来获取最近的后台ssh进程。例如:

[root@node1 ~]# ssh 192.168.100.101 -f 'yum makecache' & echo $!
[1] 76115
76115

但这是错误的方法,如果你现在去查看ssh进程,你会发现进程号不是76115。

[root@node1 ~]# pstree -p | grep 'ssh('|-ssh(76116)

因为ssh在执行远程后台命令(加上"-f"选项)的时候,它自身会在建立ssh连接后再fork一个后台ssh进程用来执行远程命令。

也就是说,当ssh执行远程后台命令的时候,会有两个ssh进程:

  • 第一个ssh进程是初始ssh进程,用于建立连接、发送要执行的命令、fork新的ssh进程等,当这些任务结束后,这个ssh进程会消逝;
  • 第二个ssh进程是第一个ssh进程fork出来的新进程(调试的结果将显示"debug1: forking to background"),用来执行远程命令。它是后台进程,挂靠在init/systemd进程下。当远程命令执行结束时,这个后台ssh进程会消逝。

注意,只有使用了"-f"选项,第一个ssh进程才会fork新的后台ssh进程,因为前台的任务(没有使用"-f")可以直接在第一个ssh进程上执行。

第二个后台ssh进程无法用$!捕捉,$!捕捉到的只是&的后台,而对于ssh ... &中的"&"来说,它是将ssh连接进程(即第一个ssh进程)置于后台,而不是将fork出来的ssh后台进程再放入后台。所以上面的"echo $!"的结果76115比后台ssh进程号76116要小。

那么有什么好方法可以判断多个远程ssh进程中的每一个?没有好方法(我个人还没有想到),只能通过比较愚笨的方式来实现判断:将每个后台ssh进程的pid号保存起来(存放到每个变量中,或数组中)。

例如,有两个执行远程命令的ssh进程:

ssh 192.168.100.101 -f 'sleep 50'
ssh_pid1=`ps x | awk '/ssh.*slee[p]/{print $1}' | tail -1`
ssh 192.168.100.101 -f 'sleep 60'
ssh_pid2=`ps x | awk '/ssh.*slee[p]/{print $1}' | tail -1`# ssh_pid1 finished?
kill -0 $ssh_pid1
echo $?# ssh_pid2 finished?
kill -0 $ssh_pid2
echo $?

最后补上ssh连接或执行远程命令时,内部过程的详细信息。这些信息使用ssh -vvv即可获取,此处给出的是筛选后的一小部分。

当ssh建立连接或执行前台远程命令(没有使用"-f"选项)时:

OpenSSH_6.6.1, OpenSSL 1.0.1e-fips 11 Feb 2013
debug1: Reading configuration data /etc/ssh/ssh_config
debug1: /etc/ssh/ssh_config line 56: Applying options for *
debug2: ssh_connect: needpriv 0
debug1: Connecting to 192.168.100.101 [192.168.100.101] port 22.
debug1: Connection established                          # tcp连接建立
.....................
debug1: Authentication succeeded (publickey).
Authenticated to 192.168.100.101 ([192.168.100.101]:22).  # 用户认证成功
debug1: channel 0: new [client-session]
debug3: ssh_session2_open: channel_new: 0
debug2: channel 0: send open                  # ssh连接建立
debug1: Requesting no-more-sessions@openssh.com
debug1: Entering interactive session.         # ssh连接进程进入交互式模式[1]+  Stopped                 ssh -vvvv 192.168.100.101

当执行远程后台任务时(加上"-f"选项):

[root@node1 ~]# ssh -vvv 192.168.100.101 -f 'sleep 50' & echo $!
[1] 65570
65570                 # echo $!得到的上一个后台进程位65570
[root@node1 ~]# OpenSSH_6.6.1, OpenSSL 1.0.1e-fips 11 Feb 2013
debug1: Reading configuration data /etc/ssh/ssh_config
debug1: /etc/ssh/ssh_config line 56: Applying options for *
debug2: ssh_connect: needpriv 0
debug1: Connecting to 192.168.100.101 [192.168.100.101] port 22.
debug1: Connection established.        # tcp连接建立
....................................
debug1: Authentication succeeded (publickey).     # 用户认证成功
Authenticated to 192.168.100.101 ([192.168.100.101]:22).
debug2: fd 4 setting O_NONBLOCK
debug1: channel 0: new [client-session]
debug3: ssh_session2_open: channel_new: 0
debug2: channel 0: send open                 # ssh连接建立
debug1: Requesting no-more-sessions@openssh.com
debug1: forking to background             # 注意此处:fork一个新ssh进程到后台
debug1: Entering interactive session.     # ssh连接进程进入交互式模式
debug2: callback start
......................................

http://www.rwi9374.cn/
http://www.gky0942.cn/
http://www.ice7855.cn/
http://www.koi7857.cn/
http://www.dmi4893.cn/
http://www.yxp3496.cn/
http://www.xkk9615.cn/
http://www.ixa0880.cn/
http://www.gfw0394.cn/
http://www.ucl3937.cn/
http://www.eqv5313.cn/
http://www.qyd5295.cn/
http://www.mau6270.cn/
http://www.ecc2991.cn/
http://www.qdj0796.cn/
http://www.sfx6922.cn/
http://www.huh0545.cn/
http://www.kgg2505.cn/
http://www.dhg3119.cn/
http://www.azd6793.cn/
http://www.vuf7734.cn/
http://www.ums9455.cn/
http://www.dli5822.cn/
http://www.rik3314.cn/
http://www.arf0717.cn/
http://www.dsx1888.cn/
http://www.dsd3012.cn/
http://www.pur5137.cn/
http://www.fsj6077.cn/
http://www.tvz4241.cn/
http://www.qndfr.org/
http://www.zcshr.org/
http://www.fnfdf.cc/
http://www.taoshun1688.com/
http://www.unuu6393.cn/
http://www.ebll4793.cn/
http://www.wzxw0148.cn/
http://www.jknp6659.cn/
http://www.eaxv3478.cn/
http://www.enyy1947.cn/
http://www.vcqr8578.cn/
http://www.pbss8753.cn/
http://www.gwvq8861.cn/
http://www.taum0602.cn/
http://www.wuoe3708.cn/
http://www.spyb0748.cn/
http://www.jbxu3084.cn/
http://www.eami4345.cn/
http://www.zzyb6904.cn/
http://www.wead0122.cn/
http://www.iyld2675.cn/
http://www.yeex2195.cn/
http://www.fgro9441.cn/
http://www.kvvz4431.cn/
http://www.uuza3384.cn/
http://www.yyvw5376.cn/
http://www.keej8837.cn/
http://www.izpt4079.cn/

判断ssh远程命令是否执行结束相关推荐

  1. linux显示远程命令执行情况,判断ssh远程命令是否执行结束

    通常在那些"一键化部署"的shell脚本中,可能需要使用ssh执行远程命令来实现一些简单的自动化,这些远程命令可能需要执行一段时间才能结束(如yum命令).例如,远程ssh配置yu ...

  2. ssh远程执行服务器命令,ssh远程连接服务器执行命令

    问题 首先说一下使用ssh远程连接服务器执行命令的方法: 为了方便描述,这里把测试服务器称之为A1,目标服务器称之为A2 A1与A2之间首先要建立ssh免密登录,在A1上生成公钥和私钥 ssh-key ...

  3. shell脚本中判断上一个命令是否执行成功

    2018-12-21 shell中使用符号"$?"来显示上一条命令执行的返回值,如果为0则代表执行成功,其他表示失败. 结合if-else语句实现判断上一个命令是否执行成功 示例如 ...

  4. shell脚本判断上一个命令是否执行成功

    shell脚本中判断上一个命令是否执行成功 shell中使用符号"$?"来显示上一条命令执行的返回值,如果为0则代表执行成功,其他表示失败. 结合if-else语句实现判断上一个命 ...

  5. 远程命令/代码执行漏洞(RCE)总结

    介绍 Command Injection,即命令注入,是指通过提交恶意构造的参数破坏命令语句结构,从而达到执行恶意命令的目的.PHP命令注入攻击漏洞是PHP应用程序中常见的脚本漏洞之一. 当应用需要调 ...

  6. SSH远程登录并执行命令测试

    SSH 是 Linux 下进行远程连接的基本工具,但是如果仅仅用它来登录那可是太浪费啦!SSH 命令可是完成远程操作的神器啊,借助它我们可以把很多的远程操作自动化掉!下面就对 SSH 的远程操作功能进 ...

  7. python ssh 远程登录路由器执行命令_ssh批量登录并执行命令(python实现)

    局域网内有一百多台电脑,全部都是linux操作系统,所有电脑配置相同,系统完全相同(包括用户名和密码),ip地址是自动分配的.现在有个任务是在这些电脑上执行某些命令,者说进行某些操作,比如安装某些软件 ...

  8. RCE详解(远程命令/代码执行漏洞)

    1.RCE(remote command/code execute)概述 RCE漏洞,可以让攻击者直接向后台服务器远程注入操作系统命令或者代码,从而控制后台系统. 远程系统命令执行 一般出现这种漏洞, ...

  9. RCE 远程命令代码执行漏洞

    什么是REC Remote Command/Code Execute,远程命令或者代码执行.通过构造特殊的字符串,将数据提交到WEB应用程序,并利用该方式外部程序或命令进行攻击,类似SQL注入. We ...

最新文章

  1. MEET2020 | 嘉宾已确认!李开复、倪光南等AI大咖齐聚,共话人工智能新价值新边界新格局...
  2. Java 转型问题(向上转型和向下转型)
  3. vue拖动改变模板_可视化拖拽 UI 布局之拖拽篇
  4. 空except的慎用
  5. 推荐!计算机视觉最适合入门的 8 本教程,算法与实战兼备
  6. java 自定义xml_6.1 如何在spring中自定义xml标签
  7. python模型训练框架_Pytorch-Transformers 1.0发布,支持六个预训练框架,含27个预训练模型...
  8. Spring Boot的SpringApplication类详解
  9. 课程设计——企业网络项目搭建(上)
  10. php pdo exec,PDO::exec
  11. 游戏策划入门(6)——把模块变成现实
  12. win10隐藏任务栏_推荐我使用的一个任务栏软件:7+ Taskbar Tweaker
  13. 从互联网大佬到田间养猪,佛系丁磊从未躺平
  14. linux 清除dns缓存
  15. MMORPG开发入门
  16. 周易六十四卦——风火家人卦
  17. Flutter 中由 BuildContext 引发的血案
  18. 计算机系统软件简介功能,计算机系统简介2
  19. nodejs MVC框架:Adonisjs框架入门-001概述
  20. 记录一下sql两个表关联的查询使用方法

热门文章

  1. 图的深度遍历(邓俊辉版)
  2. 37岁Java程序员求职6K+职位被怼,你怎么看?
  3. c#调用新浪微博开放平台接口
  4. 密码模块安全等级 GM/T 0028
  5. 跟了老板10年被劝退,“忠诚”就换来这个?
  6. btb和oto,btc模式是什么意思
  7. 新东方 词根词缀 excel_词根词缀记忆英语单词,高效,不易遗忘
  8. 华为鸿蒙HarmonyOS 简介
  9. iOS 相册备份功能实现
  10. 别再自己抠图了,3行Python代码实现图像照片抠图和换底色的方法