Linux 下 ssh 执行远程服务器命令
通常在 Windows或者其他 OS 环境下使用远程连接客户端(例如:Xshell)登录服务器后就可以操作远程服务器,这次项目中接到了一项部署改造的任务,需求是:在服务器 A 上有个 start.sh 脚本,这个脚本会调用到另一台服务器 B 下的一个 bootstrap.sh 脚本,这里就需要使用到 ssh 远程执行的相关命令了,这里做个总结,方便下次快速回顾和翻阅。
测试环境搭建
开启 VMware 虚拟机创建两台 CentOS7 系统的服务器(VMware 虚拟机安装 CentOS7 请点击这里),默认下开机两个服务器都不会自动获取 IP ,没有IP ,ssh 命令就无法使用,Xshell 自然也就连不上,使用如下方式更改即可:
# 1. 使用如下命令,将 ONBOOT=no 改为 yes
vi /etc/sysconfig/network-scripts/ifcfg-ens33
# 2. 重启网络服务
service network restart
# 3. 查看 IP
ip addr
搭建好两台服务器,用户名分别为 guan 和 tomcat,IP 分别为 192.168.209.129 和 192.168.209.131 。
远程执行脚本
登录其中一台服务器(guan,192.168.209.131),执行如下命令即可在另一台服务器(tomcat,192.168.209.129)上显示 tomcat 用户家目录下的文件信息(cd ~;ls) :
ssh tomcat@192.168.209.129 "cd ~ ;ls"
Are you sure you want to continue connecting (yes/no)? 输入 yes,再输入密码即可,效果如下:
第一次执行的话,会在 guan 用户家目录下会生成一个 .ssh/known_hosts 文件,并添加相应主机的信息,第二次执行时就不会再提示 Are you sure you want to continue connecting (yes/no)? 如下:
远程执行脚本
远程执行命令还不够,我们还需要做到在远程服务器上执行脚本,在 tomcat 那台服务器上写个 Hello.sh 脚本打印 HelloWorld(Shell 编程请点击这里),
使用如下命令即可调用到 tomcat 服务器上的脚本:
ssh tomcat@192.168.209.129 "~/Hello.sh"
效果如下:
在 guan 服务器下把 ssh tomcat@192.168.209.129 "~/Hello.sh" 写到 Test.sh 脚本里,chmod 权限后,执行 Tesh.sh 脚本效果一致,如下:
配置 ssh 互信
每次执行 ssh 远程命令时,都要输入密码,是很麻烦的事情,可以配置服务器之间的 .ssh 互信,免去输入密码的过程,配置过程步骤如下(原理见下一节):
1. 生成秘钥和公钥
两台服务器下都使用如下命令生成秘钥公钥,然后就会在 guan 用户目录下生成 .ssh 目录,目录下有私钥(id_rsa)和公钥(id_rsa.pub)文件。
ssh-keygen -t rsa
ssh-keygen -m PEM -t rsa -b 4096
2. 生成 authorized_keys 认证文件
进入 .ssh 目录,将公钥拷贝一份,并命名为 authorized_keys ,这个其实就是认证文件,从 id_rsa.pub 拷贝一份也就相当于把自身也给加进了 authorized_keys 文件里(自己也可以用 ssh 远程调用自己)。
cp id_rsa.pub authorized_keys
3. 配置authorized_keys
使用 vi 命令把两台服务器 id_rsa.pub 下的内容相互添加到彼此的 authorized_keys 文件上,此时互信配置完成,在 tomcat 服务器上执行 命令:ssh guan@192.168.209.131 "~/Test.sh" ,就会执行 guan 服务器上的 Test.sh 脚本,然后又返回来调用 tomcat 下的 Hello.sh 脚本,效果如下:
ssh互信的原理
ssh 互信中用到了公钥和秘钥,还有认证文件 authorized_keys ,那他们具体是做什么的用的呢?
这里涉及到了密码学的一点小知识,用到了非对称加密算法中的公钥加密算法,这种算法公钥和秘钥是成对出现的(上面使用 ssh-keygen -t rsa 后在 .ssh 下就生成了 id_rsa.pub 和 id_rsa),公钥是可以对外暴露,不用害怕别人知道,使用公钥加密的数据只能用对应的私钥才能解开,而私钥作为解开公钥加密数据的唯一一把钥匙,是不可对外暴露的。
在互信配置完成后,在 guan 服务器使用 ssh tomcat@192.168.209.129 "~/Hello.sh" 去让远程 tomcat 服务器执行对应命令时,guan 服务器会把自己的公钥发给 tomcat 服务器,tomcat 服务器此时就会在 authorized_keys 认证文件中去匹配看有没有 guan 服务器的公钥,如果有,就会用它的公钥加密认证数据发回给 guan 服务器,guan 服务器接到这个加密后的认证数据,就会用私钥进行解密,再发回给 tomcat 服务器,此时 tomcat 服务器就会进行核对解密后的数据是否和加密前的一致,一致则认证成功,不一致则认证失败。
关于环境变量问题
过程中遇到了一个环境变量导致的问题,在 tomcat 服务器下配置了 JAVA_HOME 环境变量的,是可以执行 java 命令,如下:
但是在 guan 服务器上执行 ssh tomcat@192.168.209.129 "java" ,远程在 tomcat 服务器上执行 java 命令则会提示 java 命令不存在,如下:
可以确定是远程执行 ssh 命令时 JAVA_HOME 环境变量没有生效,解决办法是使用全路径去执行 java 命令,如下: