基于ssh
根据业务需求有的项目中可能会需要java执行linux命令
用springboot整合一下
maven依赖
<dependency><groupId>ch.ethz.ganymed</groupId><artifactId>ganymed-ssh2</artifactId><version>build210</version></dependency>
yml配置文件
在配置文件中自定义服务器的ip,账号,密码,方便修改
ssh:
ip: 192.168.12.103
user: root
pass: 1234
配置类
先要连接获取connection对象
@Configuration
@Slf4j
public class SshConfig {
@Value("${ssh.ip}")
private String ip;
@Value("${ssh.user}")
private String user;
@Value("${ssh.pass}")
private String pass;
@Bean
public Connection getConnection() {
Connection conn = new Connection(ip);
try {
conn.connect();
//账号,密码验证
boolean isAuthenticated = conn.authenticateWithPassword(user, pass);
if (!isAuthenticated) {
throw new IOException("密码不正确!");
}
} catch (
IOException e) {
log.error("连接异常====>{}", e.getMessage());
}
return conn;
}
}
执行命令
封装一个方法,执行命令并返回执行结果,execCommand方法来执行命令
一个session对象只能执行一次execCommand方法
/**
* 执行命令并返回执行结果
*
* @param command 命令
* @return java.lang.String
* @author YangYudi
* @date 2021/1/8 9:04
*/
public String execCommand(String command) {
StringBuilder result = new StringBuilder();
try {
Session session = connection.openSession();
session.execCommand(command);
//获取返回信息
InputStream stdout = new StreamGobbler(session.getStdout());
BufferedReader stdoutReader = new BufferedReader(new InputStreamReader(stdout));
InputStream stderr = new StreamGobbler(session.getStderr());
BufferedReader stderrReader = new BufferedReader(new InputStreamReader(stderr));
//一直读到流结束 逐行读取
String line;
//标准输出
while ((line = stdoutReader.readLine()) != null) {
result.append(line).append("\n");
}
//标准错误输出
while ((line = stderrReader.readLine()) != null) {
result.append(line).append("\n");
}
//等待收到远程进程的退出码
session.waitForCondition(ChannelCondition.EXIT_STATUS, 10000);
stdoutReader.close();
stderrReader.close();
session.close();
} catch (IOException e) {
log.error("ssh执行出错:{}", e.getMessage());
}
return result.toString();
}
测试方法
@Test
void saltTestMinion() {
//执行minion节点上的脚本
String result = sshCommandUtils.execCommand("salt '*' --out=json cmd.run_all 'cat /usr/local/hello.txt'");
System.out.println(result);
}
需要考虑的问题
这里把connection作为单例对象使用,在多线程情况下,可能不太适用
多线程情况下执行命令connection最好不要用单例
在本机执行命令
maven依赖
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-exec</artifactId>
<version>1.1</version>
</dependency>
api使用
封装一个方法,根据传入的命令返回执行结果
public static String execCommand(String command) {
CommandLine cmd = CommandLine.parse(command);
OutputStream outputStream = new ByteArrayOutputStream();
DefaultExecutor executor = new DefaultExecutor();
PumpStreamHandler streamHandler = new PumpStreamHandler(outputStream);
ShutdownHookProcessDestroyer processDestroyer = new ShutdownHookProcessDestroyer();
executor.setStreamHandler(streamHandler);
executor.setProcessDestroyer(processDestroyer);
try {
executor.execute(cmd);
} catch (Exception e) {
log.error("{}", e);
}
return outputStream.toString();
}
