实际背景
在日常工作中, 大家难免会遇到这样一种情况, 就是我需要先登陆一台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