通过 JSch 在 java 上运行 linux 命令
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/11532890/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Running linux commands on java through JSch
提问by Miguel ángel
I'm establishing a ssh connection through JSch on java and everything seemed to be working fine, until I tried to run this .sh file. The shell script's name is repoUpdate.shand it's very simple:
我正在通过 Java 上的 JSch 建立 ssh 连接,一切似乎都运行良好,直到我尝试运行这个 .sh 文件。shell 脚本的名称是repoUpdate.sh,它非常简单:
echo ' ****Repository update****'
echo ' Location: /home/cissys/repo/'
echo -e ' Command: svn update /home/cissys/repo/2.3.0'
svn update /home/cissys/repo/2.3.0
This is the output I get directly on the linux console with the proper response of the command:
这是我直接在 linux 控制台上通过正确响应命令获得的输出:
[cissys@dsatelnx5 ~]$ repoUpdate.sh
****Repository update****
Location: /home/cissys/repo/
Command: svn update /home/cissys/repo/2.3.0
At revision 9432.
Now, here's the java code of my method with the ssh connection that tries to call this same file
现在,这是我的方法的 java 代码,带有尝试调用同一个文件的 ssh 连接
public void cmremove()
{
try
{
JSch jsch = new JSch();
Session session = jsch.getSession(user, host, port);
UserInfo ui = new SUserInfo(pass, null);
session.setUserInfo(ui);
session.setPassword(pass);
session.connect();
ChannelExec channelExec = (ChannelExec)session.openChannel("exec");
InputStream in = channelExec.getInputStream();
channelExec.setCommand("./repoUpdate.sh");
channelExec.connect();
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
String line;
int index = 0;
while ((line = reader.readLine()) != null)
{
System.out.println(++index + " : " + line);
}
channelExec.disconnect();
session.disconnect();
System.out.println("Done!");
}
catch(Exception e)
{
System.err.println("Error: " + e);
}
}
And the response I get is the following:
我得到的回应如下:
run:
1 : ****Repository update****
2 : Location: /home/cissys/repo/
3 : Command: svn update /home/cissys/repo/2.3.0
Done!
BUILD SUCCESSFUL (total time: 2 seconds)
with no output or signs of execution on the svn command (At revision 9432) whatsoever.
在 svn 命令(修订版 9432)上没有任何输出或执行迹象。
I'm thinking it may be closing the session at some point, not letting the command execute properly. If the updateRepo.shfile would've had something like "cp test.txt test_2.txt", it would do it with no problem. But i only have this problem with this and some other specific .sh files.
我认为它可能会在某个时候关闭会话,而不是让命令正确执行。如果updateRepo.sh文件有类似“cp test.txt test_2.txt”的内容,它就可以毫无问题地完成。但我只有这个问题和其他一些特定的 .sh 文件。
Any help would be appreciated.
任何帮助,将不胜感激。
采纳答案by Miguel ángel
So here's what I did.
I added the exec 2>&1
at the top of the repoUpdate.shfile and added that piece of code to read the output error as @DanielMartin suggested, resulting on this:
所以这就是我所做的。
我exec 2>&1
在repoUpdate.sh文件的顶部添加了,并添加了那段代码来读取@DanielMartin 建议的输出错误,结果如下:
public void cmremove()
{
try
{
JSch jsch = new JSch();
Session session = jsch.getSession(user, host, port);
UserInfo ui = new SUserInfo(pass, null);
session.setUserInfo(ui);
session.setPassword(pass);
session.connect();
ChannelExec channelExec = (ChannelExec)session.openChannel("exec");
InputStream in = channelExec.getInputStream();
channelExec.setCommand("./repoUpdate.sh");
channelExec.connect();
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
String line;
int index = 0;
while ((line = reader.readLine()) != null)
{
System.out.println(++index + " : " + line);
}
int exitStatus = channelExec.getExitStatus();
channelExec.disconnect();
session.disconnect();
if(exitStatus < 0){
System.out.println("Done, but exit status not set!");
}
else if(exitStatus > 0){
System.out.println("Done, but with error!");
}
else{
System.out.println("Done!");
}
}
catch(Exception e)
{
System.err.println("Error: " + e);
}
}
So that actually helped a lot. It confirmed that the command was, in fact, not executing correctly as I thought. I was getting this on my java output:
所以这实际上有很大帮助。它确认该命令实际上并没有像我想象的那样正确执行。我在我的 java 输出中得到了这个:
run:
1 : ****Repository update****
2 : Location: /home/cissys/repo/
3 : Command: svn update /home/cissys/repo/2.3.0
4 : ./repoUpdate.sh[6]: svn: not found [No such file or directory]
Done!
BUILD SUCCESSFUL (total time: 2 seconds)
Then I tried modifying the repoUpdate.shfile, adding the absolute path for the svn command (Thank you, @ymnk)
然后我尝试修改repoUpdate.sh文件,添加 svn 命令的绝对路径(谢谢,@ymnk)
exec 2>&1
echo ' ****Repository update****'
echo ' Location: /home/cissys/repo/'
echo -e ' Command: svn update /home/cissys/repo/2.3.0'
/opt/subversion/bin/svn update /home/cissys/repo/2.3.0
For my java, I got just what I was looking for:
对于我的 java,我得到了我想要的东西:
run:
1 : ****Repository update****
2 : Location: /home/cissys/repo/
3 : Command: svn update /home/cissys/repo/2.3.0
4 : At revision 9443.
Done!
BUILD SUCCESSFUL (total time: 3 seconds)
I found out that the $PATH
I get from the session through java is not the same that I get directly on the linux console.
So adding the svn path actually did the trick. Thank you very much for your help!
我发现$PATH
我通过 java 从会话中获得的与我直接在 linux 控制台上获得的不同。所以添加 svn 路径实际上起到了作用。非常感谢您的帮助!
回答by Daniel Martin
I suspect that your shell command is erroring out for some reason - perhaps svn
isn't on your path, perhaps there are other weird environmental effects - but you're not getting the error output because you aren't looking for it. Normally, errors are sent on the stream you get from channelExec.getErrStream
but in your code you only read from the getOutputStream
stream.
我怀疑您的 shell 命令由于某种原因svn
出错- 可能不在您的路径上,也许还有其他奇怪的环境影响 - 但是您没有得到错误输出,因为您没有在寻找它。通常,错误会在您获得的流上发送,channelExec.getErrStream
但在您的代码中,您只能从getOutputStream
流中读取。
To diagnose this, you're going to need to get those error messages. It's probably easier to get linux to use one stream for both regular output and error messages than to have your java program pulling from two streams at once, so I'd add this line as the top line of repoUpdate.sh
:
要对此进行诊断,您将需要获取这些错误消息。让 linux 为常规输出和错误消息使用一个流可能比让 Java 程序一次从两个流中提取更容易,所以我将这一行添加为repoUpdate.sh
:
exec 2>&1
That'll then cause the rest of the script to use the one stream you're reading from as both output and error.
这将导致脚本的其余部分使用您正在读取的一个流作为输出和错误。
Also, right before you call chanelExec.disconnect
, in your java program you should record the exit status, and then change your "Done!" message based on what it was:
另外,在你调用之前chanelExec.disconnect
,在你的java程序中你应该记录退出状态,然后改变你的“完成!” 消息基于它是什么:
int exitStatus = channelExec.getExitStatus();
channelExec.disconnect();
session.disconnect();
if (exitStatus < 0) {
System.out.println("Done, but exit status not set!");
} else if (exitStatus > 0) {
System.out.println("Done, but with error!");
} else {
System.out.println("Done!");
}
If you do this, you should then get error messages that tell you why your command isn't working as you expect it should.
如果您这样做,您应该会收到错误消息,告诉您为什么您的命令没有按预期工作。