我正在使用JSch exec频道登录多个服务器并运行一些命令。然后我需要捕获输出并将其存储在名为log
的文件中。由于某些奇怪的原因,执行后文件仍然是空白。
try (OutputStream log = new BufferedOutputStream(new FileOutputStream(outputFilePath))) {
ArrayList<String> lists = new ArrayList<String>();
lists.add("hostname");
lists.add("df -l");
String host ="localhost";
JSch jsch = new JSch();
try {
String user = "user";
String password = "pass";
Session session = jsch.getSession(user, host, 22);
session.setPassword(password);
session.setConfig(getProperties());
session.setTimeout(20 * 1000);
System.out.println(session.getTimeout());
session.connect();
if (session.isConnected()) {
System.out.println(host + " Session Established ");
}
for (String elem : lists) {
Channel channel = session.openChannel("exec");
channel.setOutputStream(log);
((ChannelExec) channel).setCommand(elem);
channel.setInputStream(null);
((ChannelExec) channel).setErrStream(System.err);
InputStream in = channel.getInputStream();
channel.connect();
byte[] tmp = new byte[1024];
while (true) {
while (in.available() > 0) {
int i = in.read(tmp, 0, 1024);
if (i < 0) {
break;
}
System.out.print(new String(tmp, 0, i));
}
if (channel.isClosed()) {
if (in.available() > 0) {
continue;
}
System.out.println("exit-status: " + channel.getExitStatus());
break;
}
try {
Thread.sleep(1000);
} catch (Exception ee) {
}
}
channel.disconnect();
}
session.disconnect();
程序通过IDE控制台显示输出,但输出文件已创建但仍保持空白。
然后我将system.setOut
设置为文件,这会阻止控制台显示更多数据,但output.txt
文件仍为空白。
System.setOut(new PrintStream(new BufferedOutputStream(new FileOutputStream("output.txt"))));
答案 0 :(得分:2)
这是因为getInputStream
会覆盖setOutputStream
来电。
了解这些方法如何在JSch中实现(最终都调用io.setOutputStream
):
public void setOutputStream(OutputStream out){
io.setOutputStream(out, false);
}
public InputStream getInputStream() throws IOException {
int max_input_buffer_size = 32*1024;
try {
max_input_buffer_size =
Integer.parseInt(getSession().getConfig("max_input_buffer_size"));
}
catch(Exception e){}
PipedInputStream in =
new MyPipedInputStream(
32*1024, // this value should be customizable.
max_input_buffer_size
);
boolean resizable = 32*1024<max_input_buffer_size;
io.setOutputStream(new PassiveOutputStream(in, resizable), false);
return in;
}
我假设您实际上不需要基于InputStream in
的输出读取块。只需删除它,日志文件写入应该开始工作。
旁注:默认情况下,输出流将与频道关闭。当您为多个频道重复使用相同的流时,您应该阻止它。
使用setOutputStream
覆盖dontclose
参数:
public void setOutputStream(OutputStream out, boolean dontclose)
像这样:
channel.setOutputStream(log, true);