上一篇博客中已经介绍过,如何使用SSH-2实现Java远程连接服务器,以及实现了四个操作:
1、创建目录结构,执行服务器命令python create_files.py
2、在faceS下建立一个以照片名为文件名的文件夹,上传人脸照片到该文件夹下,用于第三阶段人脸检测算法
3、上传本地文件(视频)到服务器
4、下载服务器的文件到本地(返回给用户)
除了这四个操作,我们还需要实现一个操作:通过Java远程连接服务器来执行算法,我们仍然打算使用SSH2来实现,由于在 Connection_to_Sever 类中实现了一个远程执行shell脚本或者命令的函数:
//远程执行shell脚本或者命令,命令执行成功后返回的结果值,如果命令执行失败,返回空字符串,不是null
public static String executeSuccess(String cmd){
String result = "";
//int ret=-1;
try {
Session session = conn.openSession();// 打开一个会话
session.execCommand(cmd);// 执行命令
result = processStdout(session.getStdout(), DEFAULTCHARTSET);
//ret = session.getExitStatus();
conn.close();
session.close();
} catch (IOException e) {
e.printStackTrace();
}
return result;
}
所以一开始我直接在这个函数的基础上来编写调用算法的接口(服务器端算法的python接口文件为 algorithm_run.py):
public class CallAlgorithm {
public static void call_three_algorithm(String ID,String ID_VideoName,String VideoName){
String commandStr="cd ../opt/data/private/xuyunyang/2022419/SceneSeg/lgss/;python algorithm_run.py "+ID+" "+ID_VideoName+" "+VideoName;
Boolean result=Connection_to_Sever.connectLinux("222.206.4.160",25935,"root","shixun123",commandStr);
}
public static void main(String [] args){
call_three_algorithm("ID","ID_VideoName","S01E01.mp4");
}
}
写完后运行发现服务器端没有反应,也就是无法成功执行,而且也没有在控制台报任何错,对服务端的python程序接口一句一句地调试,发现是因为引入了第三方包,问题出在下面两个地方:
问题出现的原因:
当执行session.execcommand()这个命令的时候,会出现在远程机器上环境变量丢失或者错误的问题,在与Linux主机建立连接的时候会默认读取环境变量等信息,可能是因为session刚刚建立还没有读取完默认信息的时候,execCommand就执行了Shell命令。
解决方法:
不用session.execCommand(),而是用获取pty(虚拟终端)和启动shell命令来代替,(use Session.requestPTY() and Session.startShell()):
// 1、建立虚拟终端
session.requestPTY("bash");
// 2、打开一个Shell
session.startShell();
// 3、准备输入命令
PrintWriter out = new PrintWriter(session.getStdin());
// 4、输入待执行命令
out.println(cmd);
out.println("exit")
// 5、 关闭输入流
out.close();
// 6、等待,除非1.连接关闭;2.输出数据传送完毕;3.进程状态为退出;4.超时
session.waitForCondition(ChannelCondition.CLOSED | ChannelCondition.EOF | ChannelCondition.EXIT_STATUS , 30000);
用这种方式执行Shell命令,会避免环境变量读取不全的问题,第6步里有许多标识可以用,比如当exit命令执行后或者超过了timeout时间,则session关闭。
需要注意的是,当一个Shell命令执行时间过长时,会遇到ssh连接超时的问题,解决办法:
通过把Linux主机的sshd_config的参数ClientAliveInterval设为60,同时将第6步中timeout时间设置很大,来保证命令执行完毕,因为我们执行后端三个算法,耗时比较长(这也是我们需要优化的地方)。
代码实现:
在 Connection_to_Sever 类中再写一个使用 Session.requestPTY() 和 Session.startShell() 执行命令的函数:
//通过Session.requestPTY() 和 Session.startShell()来执行python脚本
public static void executePython(String ip,int port,String userName,String password,String cmd1,String cmd2,String cmd3){
logger.info("ConnectLinuxCommand scpGet===" + "ip:" + ip +" port:"+port+ " userName:" + userName + " commandStr:"
+ cmd1+","+cmd2);
RemoteConnect remoteConnect = new RemoteConnect();
remoteConnect.setIp(ip);
remoteConnect.setPort(port);
remoteConnect.setUserName(userName);
remoteConnect.setPassword(password);
if (login(remoteConnect)) {
try {
Session session = conn.openSession();// 打开一个会话
session.requestPTY("bash");
session.startShell();
//获取Shell命令执行结果
InputStream stdout = new StreamGobbler(session.getStdout());
InputStream stderr = new StreamGobbler(session.getStderr());
BufferedReader stdoutReader = new BufferedReader(new InputStreamReader(stdout));
BufferedReader stderrReader = new BufferedReader(new InputStreamReader(stderr));
PrintWriter out =new PrintWriter(session.getStdin());
out.println(cmd1);
out.println(cmd2);
out.println(cmd3);
out.println("exit");//后来加上,未测试
out.close();
session.waitForCondition(ChannelCondition.CLOSED | ChannelCondition.EOF | ChannelCondition.EXIT_STATUS, 30000);
while (true) {
String line = stdoutReader.readLine();
System.out.println(line);
if (line.equals("END ALL"))
break;
}
System.out.println("ExitCode: " + session.getExitStatus());
session.close();
conn.close();
} catch (IOException e){
e.printStackTrace(System.err);
System.exit(2);
}
}
}
1、调用智能剪辑(人脸+场景约束)算法的接口函数:
public class CallAlgorithm {
public static void call_three_algorithm(String ID,String ID_VideoName,String VideoName){
String command1="source activate pyt37";
String command2="cd ../opt/data/private/xuyunyang/2022419/SceneSeg/lgss/";
String command3="python algorithm_run.py "+ID+" "+ID_VideoName+" "+VideoName;
Connection_to_Sever.executePython("222.206.4.160",25935,"root","shixun123",command1,command2,command3);
}
public static void main(String [] args){
//运行失败
call_three_algorithm("ID","ID_VideoName","S01E01.mp4");
}
}
经过测试,算法执行成功:
2、调用智能预览(场景视频聚类)算法的接口函数:
public static void call_clustering_algorithm(String ID,String ID_VideoName,String VideoName){
String command1="cd ../opt/data/private/xuyunyang/2022419/SceneSeg/lgss";
String command2="source activate pyt37";
String command3="python algorithm2_run.py "+ID+" "+ID_VideoName+" "+VideoName;
Connection_to_Sever.executePython("222.206.4.160",25935,"root","shixun123",command1,command2,command3);
}
测试:
public static void main(String [] args){
call_clustering_algorithm("10","10_demoChangan","demoChangan.mp4");
}
执行结果:



