我有一个连接SSH shell的程序。我能够执行命令并从中读取输出。
但我有一个新要求。现在,如果成功执行下一个命令,我需要执行一个命令并读取输出。
我使用过这个问题的程序:JSch issue - Cannot retrieve full command output
public class SshConnectionManager {
private static Session session;
private static ChannelShell channel;
private static String username = "";
private static String password = "";
private static String hostname = "";
private static Session getSession(){
if(session == null || !session.isConnected()){
session = connect(hostname,username,password);
}
return session;
}
private static Channel getChannel(){
if(channel == null || !channel.isConnected()){
try{
channel = (ChannelShell)getSession().openChannel("shell");
channel.setPty(false);
channel.connect();
}catch(Exception e){
System.out.println("Error while opening channel: "+ e);
}
}
return channel;
}
private static Session connect(String hostname, String username, String password){
JSch jSch = new JSch();
try {
session = jSch.getSession(username, hostname, 22);
Properties config = new Properties();
config.put("StrictHostKeyChecking", "no");
session.setConfig(config);
session.setPassword(password);
System.out.println("Connecting SSH to " + hostname + " - Please wait for few seconds... ");
session.connect();
System.out.println("Connected!");
}catch(Exception e){
System.out.println("An error occurred while connecting to "+hostname+": "+e);
}
return session;
}
private static void executeCommands(List<String> commands){
try{
Channel channel=getChannel();
System.out.println("Sending commands...");
sendCommands(channel, commands);
readChannelOutput(channel);
System.out.println("Finished sending commands!");
}catch(Exception e){
System.out.println("An error ocurred during executeCommands: "+e);
}
}
private static void sendCommands(Channel channel, List<String> commands){
try{
PrintStream out = new PrintStream(channel.getOutputStream());
out.println("#!/bin/bash");
for(String command : commands){
out.println(command);
}
out.println("exit");
out.flush();
}catch(Exception e){
System.out.println("Error while sending commands: "+ e);
}
}
private static void readChannelOutput(Channel channel){
byte[] buffer = new byte[1024];
try{
InputStream in = channel.getInputStream();
String line = "";
while (true){
while (in.available() > 0) {
int i = in.read(buffer, 0, 1024);
if (i < 0) {
break;
}
line = new String(buffer, 0, i);
System.out.println(line);
}
if(line.contains("logout")){
break;
}
if (channel.isClosed()){
break;
}
try {
Thread.sleep(1000);
} catch (Exception ee){}
}
}catch(Exception e){
System.out.println("Error while reading channel output: "+ e);
}
}
public static void close(){
channel.disconnect();
session.disconnect();
System.out.println("Disconnected channel and session");
}
public static void main(String[] args){
List<String> commands = new ArrayList<String>();
commands.add("ls -l");
executeCommands(commands);
close();
}
}
我需要使用&#34; shell&#34;频道代替&#34; exec&#34;因为服务器不允许&#34; exec&#34;渠道: http://www.tembria.com/forums/viewtopic.php?t=477&sid=8f2a82ec30e89ba44d184a3b2a65ec69
答案 0 :(得分:0)
一般来说,你应该使用&#34; exec&#34;这个渠道。 &#34; shell&#34; channel不应该用于自动执行命令。
但我知道你的服务器不支持&#34; exec&#34;渠道。 我已经为其他读者添加了上述评论,而不是尝试使用此解决方案,除非他们确实需要。
正如@Yair Harel已经评论过的,如果你必须使用&#34; shell&#34;通道,你必须使用shell技术。
因此,在您的特定情况下,您可能希望远程shell在命令完成后打印一些唯一的字符串和退出代码:
out.println(command + " ; echo Command-has-finished-with-code-$?");
然后你继续阅读输出,直到你发现一行开始"Command-has-finished-with-code-"
。您解析退出代码并决定如何继续。
请注意,命令语法(特别是命令分隔符;
和退出代码变量$?
)是特定于操作系统和shell的。由于您的服务器不是标准类型,因此语法可能不同。
附注:
"#!/bin/bash"
纯粹是胡说八道。 shell忽略所有以#
开头的命令(它的评论)。发送它没有意义。 StrictHostKeyChecking=no
。请参阅JSch SFTP security with session.setConfig("StrictHostKeyChecking", "no");