通过SSH命令执行java远程脚本:如何知道是否正确执行
我需要通过SSH和Java执行Linux脚本,该脚本驻留在远程Linux机器上。 在运行时,我从DB中检索脚本的名称、主机和凭据,并尝试通过ssh启动脚本。这是好的,因为我得到了执行PID作为回报! 问题是我总是得到一个执行的PID,即使脚本是错误的,或者它不存在,或者它没有执行权限
有没有办法知道执行是否正确或命令是否错误?我需要知道是否可以在同一个ssh启动命令中使用。先谢谢你
我们使用的代码如下所示:
JSch jsch = new JSch();
String post_process_host="123.123.123.123";
Integer post_process_port=22;
String post_process_user="therock";
String post_process_pwd="XxXdfG$L";
//String command="testpp.sh";
String command="./export/home/therock/test/hello.bsh";
command=command + " > /dev/null 2>&1 & \n echo $!";
Session session = jsch.getSession(post_process_user, post_process_host, post_process_port.intValue());
UserInfo ui = new SUserInfo(post_process_pwd, null);
session.setUserInfo(ui);
session.setPassword(post_process_pwd);
session.connect();
int timeout=10; //timeout di 5 minuti
StringBuffer text = new StringBuffer();
int exitCode = -1;
try {
logger.info("Execution command: " + command);
Channel channel = session.openChannel("exec");
((ChannelExec) channel).setCommand(command);
channel.setInputStream(null);
((ChannelExec) channel).setErrStream(System.err);
InputStream in = channel.getInputStream();
InputStream err = ((ChannelExec) channel).getErrStream();
channel.connect(timeout);
byte[] tmp = new byte[1024];
while (true) {
timeout--;
while (in.available() > 0) {
int i = in.read(tmp, 0, 1024);
if (i < 0)
break;
String line = new String(tmp, 0, i, StandardCharsets.UTF_8);
text.append(line);
if (text.toString().contains("\n")) break;
}
while (err.available() > 0) {
int i = err.read(tmp, 0, 1024);
if (i < 0)
break;
String line = new String(tmp, 0, i, StandardCharsets.UTF_8);
text.append(line);
}
if (channel.isClosed()) {
if (in.available() > 0)
continue;
exitCode = channel.getExitStatus();
logger.info("Eseguito comando codice di ritorno: " + exitCode);
logger.debug("output comando: "+text.toString());
if (exitCode!=0) throw new Exception("Execution Command "+command+" error with Return Code="+exitCode);
break;
}
try {
Thread.sleep(1000);
} catch (Exception ee) {
throw ee;
}
}
channel.disconnect();
} catch (Exception e) {
throw e;
}
logger.debug("output command: "+text.toString());
# 1 楼答案
上面代码的突出部分在这2行:
它生成了一个具有以下值的
command
变量:要了解此命令的作用,您可能需要学习
bash
,但下面是我的快速解释:./export/home/therock/test/hello.bsh
的文件中执行一个命令(从扩展名来看,我假设它是一个shell脚本)> /dev/null
=然后将其STDOUT
重定向到/dev/null
(又名:放弃输出)2>&1
=然后将它的STDERR
重定向到STDOUT
去的任何地方(如上所述,它去了/dev/null或被丢弃)&
=在后台执行它\n echo $!
=然后回显(在标准输出中打印)生成的后台进程的PID(进程id)现在我不知道
./export/home/therock/test/hello.bsh
文件的内容,但是如果它写得很好,那么它应该返回一个退出代码,指示它是否成功运行(例如:使用exit 0
表示成功运行,exit 1
表示失败运行,exit 2
表示其他类型的错误)之后,我们可以通过
echo $?
看到最后一个命令的退出代码因此,您可能希望将代码重写为:
说明:
./export/home/therock/test/hello.bsh
的文件中执行一个命令(从扩展名来看,我假设它是一个shell脚本)> /dev/null
=然后将其STDOUT
重定向到/dev/null
(又名:放弃输出)2>&1
=然后将它的STDERR
重定向到STDOUT
去的任何地方(如上所述,它去了/dev/null或被丢弃);
=执行完此命令后,执行下一个命令\n echo $?
=然后回显(在标准输出中打印)最后一个命令的退出代码请注意,在进行此更改之后,您将没有进程的PID,而是有退出代码。这一更改也会使java程序等待bash脚本完成
因此,如果bash脚本运行5分钟,并且您在08:00:00开始执行java程序
编辑:
奥普说
您始终可以将退出代码保存到文件中,然后稍后读取该文件,例如:
在
./export/home/therock/test/hello.bsh
中,您可以不写exit 0
或exit 1
,而是写稍后,当您想要检查结果时,您只需要读取
./export/home/therock/test/result.txt
的最后一行(例如:tail -n1 ./export/home/therock/test/result.txt
)编辑2:
OP说他/她需要知道这个过程是否已经完成
简单的方法是创建一个锁文件(或反向锁文件)
在
./export/home/therock/test/hello.bsh
的开头添加:然后,不用写
exit 0
或exit 1
,而是可以写因此,您知道,如果文件
./export/home/therock/test/result.txt
不存在,bash脚本仍在运行。如果文件存在,则表示bash脚本已完成,您可以读取其内容以查看其结果另一种方法(更推荐)是编写一个锁文件,该文件在bash脚本进程启动时创建,退出时删除。这样还可以确保bash脚本一次只执行一次