1.引入jar包
<!-- 连接linux服务器 -->
<dependency>
<groupId>ch.ethz.ganymed</groupId>
<artifactId>ganymed-ssh2</artifactId>
<version>262</version>
</dependency>
2.application.properties配置
#shell调度服务器命
linux.shell.ip=192.168.0.1
linux.shell.userName=root
linux.shell.userPwd=root
3.linux服务器接收配置参数类
public interface Constant {
String REMOTE_SHELL_IP_CONFIG_PARAM = "${linux.shell.ip}";
String REMOTE_SHELL_USER_NAME_CONFIG_PARAM = "${linux.shell.userName}";
String REMOTE_SHELL_USER_PWD_CONFIG_PARAM = "${linux.shell.userPwd}";
String REMOTE_SHELL_DEFAULT_CHART = "UTF-8";
}
@Configuration
public class RemoteShellConfig implements Serializable {
private static String ip;
private static String userName;
private static String userPwd;
//获取 remote shell ip
@Value(Constant.REMOTE_SHELL_IP_CONFIG_PARAM)
public void setFindIp(String linuxIp) {
ip = linuxIp;
}
//获取 remote shell userName
@Value(Constant.REMOTE_SHELL_USER_NAME_CONFIG_PARAM)
public void setFindUserName(String name) {
userName = name;
}
//获取 remote shell userPwd
@Value(Constant.REMOTE_SHELL_USER_PWD_CONFIG_PARAM)
public void setFindUserPwd(String passwd) {
userPwd = passwd;
}
public static String getIp() {
return ip;
}
public static String getUserName() {
return userName;
}
public static String getUserPwd() {
return userPwd;
}
}
4.远程登录执行shell脚本(★★重点执行方法executeSuccess★★★)
public class RemoteShellUtils {
private static final Logger logger = LogManager.getLogger(RemoteShellUtils.class);
private Connection conn;
private static final int TIME_OUT = 1000 * 60 * 20;//超时时间,0表示不超时
//private static RemoteShellUtils instance = new RemoteShellUtils();
//private RemoteShellUtils() {
//
//}
//public static RemoteShellUtils getInstance() {
// return instance;
//}
/**
* 远程登录linux的主机
*
* @return 登录成功返回true,否则返回false
* @author Ickes
* @since V0.1
*/
public Boolean login() {
boolean flg = false;
try {
conn = new Connection(RemoteShellConfig.getIp());
conn.connect();//连接
flg = conn.authenticateWithPassword(RemoteShellConfig.getUserName(), RemoteShellConfig.getUserPwd());//认证
} catch (IOException e) {
e.printStackTrace();
}
return flg;
}
/**
* @param cmd 即将执行的命令
* @return 命令执行完后返回的结果值
* @author Ickes
* 远程执行shll脚本或者命令
* @since V0.1
*/
public String execute(String cmd) {
String result = "";
try {
if (login()) {
Session session = conn.openSession();//打开一个会话
session.execCommand(cmd);//执行命令
result = processStdout(session.getStdout(), Constant.REMOTE_SHELL_DEFAULT_CHART);
//如果为得到标准输出为空,说明脚本执行出错了
if (StringUtils.isBlank(result)) {
result = processStdout(session.getStderr(), Constant.REMOTE_SHELL_DEFAULT_CHART);
}
conn.close();
session.close();
}
} catch (IOException e) {
e.printStackTrace();
}
return result;
}
/**
* @param cmd 即将执行的命令
* @return 命令执行成功后返回的结果值,如果命令执行失败,返回空字符串,不是null
* @author Ickes
* 远程执行shll脚本或者命令
* @since V0.1
*/
public String executeSuccess(String cmd) {
int ret = 0;
String result = "";
try {
boolean login = login();//是否远程登录成功
int num = 0;
while (!login && num < 3){//若远程登录不成功,重试3次
num++;
login = login();
}
if (login) {
logger.warn(num + SHELL_LOGIN_SUCCESS + cmd);
Session session = conn.openSession();//打开一个会话
// 使用session.execCommand(cmd);来执行命令会出现一个问题,就是还没有加载完成服务器的环境变量就开始执行命令了,导致了很多情况是找不到命令
// session.execCommand(cmd);//执行命令
// 解决的办法
// 建立虚拟终端
session.requestPTY("bash");
// 打开一个Shell
session.startShell();
// 准备输入命令
PrintWriter out = new PrintWriter(session.getStdin());
// 输入待执行命令
out.println(cmd);
out.println("exit");
// 关闭输入流
out.close();
// 等待,除非1.连接关闭;2.输出数据传送完毕;3.进程状态为退出;4.超时
session.waitForCondition(ChannelCondition.CLOSED | ChannelCondition.EOF | ChannelCondition.EXIT_STATUS , TIME_OUT);
// 获取执行结果
result = processStdout(session.getStdout(), Constant.REMOTE_SHELL_DEFAULT_CHART);
ret = session.getExitStatus();
session.close();
} else {
logger.warn(num + SHELL_LOGIN_FAILED + cmd);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (null != conn) {
conn.close();
}
}
return result;
}
/**
* 解析脚本执行返回的结果集
*
* @param in 输入流对象
* @param charset 编码
* @return 以纯文本的格式返回
* @author Ickes
* @since V0.1
*/
private String processStdout(InputStream in, String charset) {
InputStream stdout = new StreamGobbler(in);
StringBuffer buffer = new StringBuffer();
BufferedReader br = null;
try {
br = new BufferedReader(new InputStreamReader(stdout, charset));
String line = null;
while ((line = br.readLine()) != null) {
buffer.append(line + "\n");
}
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (null != br) {
br.close();
}
if (null != stdout) {
stdout.close();
}
} catch (IOException e1) {
e1.printStackTrace();
}
}
return buffer.toString();
}
public Connection getConn() {
return conn;
}
public void setConn(Connection conn) {
this.conn = conn;
}
}
5.方法调用demo
t1.sh内容如下
#!/bin/bash
param1=$0
param2=$1
echo $param1
echo $param2
echo '123'
echo 'shell executed successfully'
public static void main(String[] args) {
//调用shell脚本(可传参数)
String taskId = "test id";
//路径最好是全路径,脚本里面的路径也最好是全路径(楼主在这shell脚本里面被相对路径坑了)
//多一个空格,方便传参,t1.sh为避免出问题,赋予777权限。 chmod 777 /root/temp/t1.sh
String REMOTE_SHELL_PATH = "/root/temp/t1.sh ";
logger.warn(taskId + SHELL_START_TIME);
//由于多线程调用此单例对象会引发回调问题,所以每次都重新new一个客户端登录
//RemoteShellUtils remoteShellUtils = RemoteShellUtils.getInstance();
RemoteShellUtils remoteShellUtils = new RemoteShellUtils();
String str = remoteShellUtils.executeSuccess(REMOTE_SHELL_PATH + taskId);
logger.warn(taskId + SHELL_TASK_END + str);
}