实际背景
在日常工作中, 大家难免会遇到这样一种情况, 就是我需要先登陆一台Linux服务器A, 然后从A登陆到另一台Linux服务器B.
这么设计的目的一般都是出于安全的考虑, 将可以线下直接访问的服务器和提供服务的服务器隔离开, 同时也能防范一些***. 但是这种设计对于正常使用也会带来一些麻烦, 因此期望某些设计能够帮助我们更方便的使用.
ssh 命令行直接登陆
假设我们命令终端可以访问到的机器是A, 也就代表A是能够被公司内网访问到, 我们的目标服务器是B, 那么我们可以在服务器A上提供一个web服务, 然后通过接口的方式直接访问B服务器的内容, 具体思路如下:
核心思路:
在服务器A上 可以通过ssh 命令直接登陆到服务器B上, 那么就可以直接通过命令行的形式直接在B服务器执行相应命令.
在A服务器执行如下命令:
ssh B服务器名 "具体命令" 复制代码
注意: 具体命令是被包括在双引号中, 如果命令中还有单双引号或者/等特殊符号, 一定要注意转义
java代码如下:
String [] cmdArray = new String[] {"/bin/sh", "-c", finalCmd}; process = Runtime.getRuntime().exec(cmdArray); 复制代码
正常的返回可以通过process.getInputStream()得到
异常信息的返回可以通过process.getErrorStream()得到
优点
你在A服务器ssh 登陆B服务器后, 能正常执行的命令, 按道理都可以通过这种方式用java代码实现, 验证起来十分方便
开发简单, 输入返回都可以由你的服务进行一定程度的控制和处理
可以自动加载目标服务器上的环境变量.
缺点
部分命令可能需要跟终端有所交互(不是指输入一些参数的交互, 而是有些命令会输出结果到特定位置例如输出到 /dev/tty了), 通过这种方式会导致无法正常返回, 需要特别处理
每一次请求代表一个命令, 代表新建一条ssh链接, 结束后断开, 无法保持链接, 因此不适用于一次连接执行多条命令或者高并发的情况.
利用jsch工具建立链接
如果期望建立一次链接, 执行多条命令的情况, 就要借助一些第三方依赖包来实现了, 我这里选用的是 com.jcraft.jsch包, 类似功能的包还有几个, 可以根据需要选用
核心思路没有什么变化, 只不过在建立连接和执行命令的时候 是通过jsch包提供的功能
maven依赖
<dependency> <groupId>com.jcraft</groupId> <artifactId>jsch</artifactId> <version>0.1.53</version> </dependency> 复制代码
java代码实现如下
public void jsch() throws JSchException, IOException { List<String> stdout = new ArrayList<>(); JSch jsch = new JSch(); Session session = jsch.getSession("user", "host", 222); session.setPassword("password"); session.connect(5000); //打开通道,设置通道类型,和执行的命令 Channel channel = session.openChannel("exec"); ChannelExec channelExec = (ChannelExec)channel; channelExec.setCommand("ls"); channelExec.setInputStream(null); BufferedReader input = new BufferedReader(new InputStreamReader(channelExec.getInputStream())); channelExec.connect(); //接收远程服务器执行命令的结果 String line; while ((line = input.readLine()) != null) { stdout.add(line); } input.close(); //关闭通道 channelExec.disconnect(); //关闭session session.disconnect(); LOGGER.info("执行命令返回 :" + stdout.toString()); } 复制代码
优点
ssh连接可以通过工具保持, 适合命令频繁执行的情况, 可以减少不必要的ssh链接建立关闭的消耗
各种api接口功能比较齐全, 复杂度不高
支持拉取服务器文件
缺点
在认证方面有一些坑, 需要根据遇见的情况自己填一下
执行时无法获取到目标服务器的环境变量, 因此执行命令的时候 需要用命令的全路径. 例如xxxx/xxx/xxx/bin/java -jar , 直接使用java -jar 是不行的, 可以通过type命令获得命令的路径
文章分类
作者:用自己的话说 链接:https://juejin.cn/post/6921594936005656590
精彩评论