在开发测试平台的时候,我遇到了一个问题,就是向远程服务器发送命令。但是我们需要知道命令执行的情况,也就是需要监控命令的输出。遇到问题,就去网上查找种解决办法嘛,后来才知道可以通过Jsch自身就能处理,不过当时也想到了另一种办法:在给远程机器发送命令后,另启一个线程监控着服务器的输出。
示例代码如下所示:
public static String exec(String host,String user,String psw,int port,String command) throws Exception{
String result="";
Session session =null;
try {
//建立远程连接,连接到服务器
JSch jsch=new JSch();
session = jsch.getSession(user, host, port);
java.util.Properties config = new java.util.Properties();
config.put("StrictHostKeyChecking", "no");
session.setConfig(config);
session.setPassword(psw);
session.connect();
openChannel = (ChannelExec) session.openChannel("exec");
openChannel.setCommand(command);
openChannel.connect();
//获取输出
InputStream in = openChannel.getInputStream();
reader = new BufferedReader(new InputStreamReader(in));
//添加定时读取操作
byte[] tmp = new byte[1024];
ScheduledExecutorService exec = Executors.newScheduledThreadPool(10);
exec.scheduleWithFixedDelay(new Runnable(){
public void run() {
try {
if(in.available() > 0){
int res = in.read(tmp, 0, 1024);
if (res<0) {
System.out.println("error="+res);
return ;
}
String content=new String(tmp,0,res);
if(content.contains("stop"))
{
System.out.println("Can be stopped!");
//exec.shutdownNow();
}
else
{
System.out.println("reader="+new String(tmp,0,res));
}
}
else
{
time++;
if(time==20)
{
exec.shutdownNow();
}
System.out.println("time="+time);
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}, 0, 100, TimeUnit.MILLISECONDS);
Thread.sleep(10000);
while(true)
{
if(time<20)
{
return "Program stop normally!";
}
else
{
return "Program stop unnormally!";
}
}
} catch (JSchException e) {
result+=e.getMessage();
}finally{
if(openChannel!=null&&!openChannel.isClosed()){
openChannel.disconnect();
}
if(session!=null&&session.isConnected()){
session.disconnect();
}
}
return "Good!";
}
代码解析:
(1)我们通过IP地址,用户名和密码连接到远程的服务器上。
(2)通过openChannel.setCommand()来给远程主机发送命令,通过openChannel.getInputStream()来获取命令的输出。
(3)启动线程exec来监控命令的输出,100毫秒读取一次,并判断读取的内容。如果内容中包含“stop”则输出“Can be stopped!!”,否则按读出的内容输出。
(4)如果没有输出则计时,2000毫秒如果没有任何输出,则中断监控进程,exec.shutdownNow()。
(5)在进程中断后,我们判断一下进程是不是正常退出的。
当然,这段代码没有什么具体的意思,只是给我们一个思路,我们可以通过这个思路来解决其他遇到的类似问题。后来又发现可以直接通过jsch来读取命令输出,并进行判断或是进行其他操作的。
示例代码如下:
package qataskclient;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.sql.Timestamp;
import java.util.Timer;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import com.jcraft.jsch.Channel;
import com.jcraft.jsch.ChannelExec;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.Session;
public class MonitorCmdRun {
//实时同步监控远程机器上命令的输出
private static JSch jsch;
private static Session session;
static String userName = "*******";
static String password = "********";
public static void connect(String host) throws JSchException {
jsch = new JSch();
session = jsch.getSession(userName, host, 22);
session.setPassword(password);
java.util.Properties config = new java.util.Properties();
config.put("StrictHostKeyChecking", "no");
session.setConfig(config);
session.connect();
}
//String command,
public static String exec(long outtime) throws Exception{
String result="";
ChannelExec openChannel = null;
try {
openChannel = (ChannelExec) session.openChannel("exec");
openChannel.setCommand("cd /root/sxftest ls sh merrychristmas.sh");
openChannel.connect();
InputStream in = openChannel.getInputStream();
//添加定时读取操作
byte[] tmp = new byte[1024];
int count=0;
long starttime = System.currentTimeMillis();
while(true)
{
while (in.available() > 0){
int res = in.read(tmp, 0, 1024);
if ( res < 0 ) break;
String content=new String(tmp,0,res);
if(content.contains("sucess"))
{
return "Program run sucessful!";
}
else
{
System.out.println(content);
}
}
long otime=System.currentTimeMillis()-starttime;
if(otime>outtime)
{
return "Program out of time!";
}
}
} catch (JSchException e) {
result+=e.getMessage();
}finally{
openChannel.disconnect();
}
return result;
}
public static void disconnect(){
session.disconnect();
System.out.println("结束连接");
}
public static void main(String args[]) throws Exception{
connect("XXX.XXX.XXX.XXX");
String exec = exec(10000);
System.out.println(exec);
disconnect();
}
}