Как получить вывод команды jsch shell в строке
Я использую библиотеку JSCH-SSH для выполнения команды в канале "shell", но не могу найти способ делать 2 вещи:-
1) Как найти, полностью ли выполняется команда на удаленном Unix box ?
2) Как захватить вывод команды в строке , вместо того, чтобы печатать ее в системе.из консоли ?
ниже мой фрагмент кода, который отлично работает для отображения вывода команды оболочки в системе.вон!--2-->
примечание: Я не хочу использовать канал"exec, поскольку он запускает новый процесс для каждой команды и не помнит "сеансовые" переменные, которые были экспортированы. Я должен использовать канал "Шелл".
Ниже приведен фрагмент моего кода. Любая помощь приветствуется.Спасибо, что уделили мне время.
try{
String commandToRun = "ls /tmp/*.log n";
if(channel.isClosed())
channel=session.openChannel("shell");
byte[] bytes = commandToRun.getBytes();
ByteArrayInputStream bais=new ByteArrayInputStream(bytes);
channel.setInputStream(bais);
InputStream ins=channel.getInputStream();
channel.connect();
channel.setOutputStream(System.out);//This prints on console. Need 2 capture in String somehow?
//in-efficient way to allow command to execute completely on remote Unix machine
//DO NOT know a better way, to know when command is executed completely
Thread.sleep(5000L);
}
catch(Exception e){
System.out.println("Exception in executeCommand() --->"+ e.getMessage());
e.printStackTrace();
}
3 ответов
для 2) u может использовать ByteArrayOutputStream
final ByteArrayOutputStream baos = new ByteArrayOutputStream();
channel.setOutputStream(baos);
а затем создайте новую строку из new String(baos.toByteArray())
для 1 вы пытались использовать 2>&1 в конце вашей команды?
String commandToRun = "ls /tmp/*.log 2>&1 \n";
мое решение может больше не понадобиться для OP, но любой другой, кто ищет решение для покрытия обоих условий 1) ожидание завершения команд на удаленной машине; и 2) захват вывода в виде строки; вы можете попробовать это:
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.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();
}
}
Это решение также полезно, если вам нужно отправить несколько команд одновременно и держать канал открытым, чтобы использовать его позже.
взяв пример, предоставленный Михаилом, другую информацию о интернетах и обратную связь от Мартина, вот переработанное решение с использованием exec
. Обратите внимание, что открытие сеанса позволяет отправлять несколько команд, каждая из которых открывает собственный канал для ввода/вывода.
рант: мне очень не нравится получать процесс'выход поток для записи. Какая раздражающая парадигма (по крайней мере, для меня). То, что я хотел, - это входной поток процессов для записи мой выход, и было удивительно трудно понять,что он перевернут. Это только я или следующее (псевдокод) не имеет смысла??
channel.getInputStream().write("here's some text to write into my channel.");
String ret = channel.getOutputStream().getOutput();
в любом случае, спасибо Михаилу и Мартину за их комментарии / ввод.
public class SSHConnectionManager {
private Session session;
private String username = "user";
private String password = "password";
private String hostname = "myhost";
public SSHConnectionManager() { }
public SSHConnectionManager(String hostname, String username, String password) {
this.hostname = hostname;
this.username = username;
this.password = password;
}
public void open() throws JSchException {
open(this.hostname, this.username, this.password);
}
public void open(String hostname, String username, String password) throws JSchException{
JSch jSch = new JSch();
session = jSch.getSession(username, hostname, 22);
Properties config = new Properties();
config.put("StrictHostKeyChecking", "no"); // not recommended
session.setConfig(config);
session.setPassword(password);
System.out.println("Connecting SSH to " + hostname + " - Please wait for few seconds... ");
session.connect();
System.out.println("Connected!");
}
public String runCommand(String command) throws JSchException, IOException {
String ret = "";
if (!session.isConnected())
throw new RuntimeException("Not connected to an open session. Call open() first!");
ChannelExec channel = null;
channel = (ChannelExec) session.openChannel("exec");
channel.setCommand(command);
channel.setInputStream(null);
PrintStream out = new PrintStream(channel.getOutputStream());
InputStream in = channel.getInputStream(); // channel.getInputStream();
channel.connect();
// you can also send input to your running process like so:
// String someInputToProcess = "something";
// out.println(someInputToProcess);
// out.flush();
ret = getChannelOutput(channel, in);
channel.disconnect();
System.out.println("Finished sending commands!");
return ret;
}
private String getChannelOutput(Channel channel, InputStream in) throws IOException{
byte[] buffer = new byte[1024];
StringBuilder strBuilder = new StringBuilder();
String line = "";
while (true){
while (in.available() > 0) {
int i = in.read(buffer, 0, 1024);
if (i < 0) {
break;
}
strBuilder.append(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){}
}
return strBuilder.toString();
}
public void close(){
session.disconnect();
System.out.println("Disconnected channel and session");
}
public static void main(String[] args){
SSHConnectionManager ssh = new SSHConnectionManager();
try {
ssh.open();
String ret = ssh.runCommand("ls -l");
System.out.println(ret);
ssh.close();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}