gpt4 book ai didi

java - JSch ChannelExec OutputStream 不显示程序输出。但是它适用于 shell 脚本

转载 作者:塔克拉玛干 更新时间:2023-11-03 02:04:08 24 4
gpt4 key购买 nike

我在本地机器上有一个用 java 编写的程序。该程序使用 JSch 连接到远程计算机,并在用户界面的 MessageConsole 上显示输出。

我可以更新 UI 中的 MessageConsole,即使我启动的脚本没有终止并输出随机数。我可以读取 OutputStream 并将其显示在 MessageConsole 上。它工作得很好。

我的问题是启动 C 程序后的输出。 OutputStream 上没有任何内容。仅当程序完全终止时才会出现输出。所有输出要么完成

printf

std::cout

如果我手动登录远程机器并手动启动程序,我的终端会立即显示所有输出。

我使用 ChannelExec 来启动远程机器上的程序:

String program = "sudo ./foo/bar.out";
String continousOutput = "sh ~/foo/bar.sh";
//ProcessWorker(String command, SSHSession ssh, GUI gui)
pw = new ProcessWorker(program, ssh, this);
pw.execute();

ProcessWorker pw 是一个 SwingWorker 类,用于在后台保持连接打开并在不锁定的情况下更新 GUI。

这段代码完成了所有脏活。 SSH 连接已经建立并且可以正常工作。

protected Void doInBackground() throws Exception {
try {
exec = ssh.session.openChannel("exec");
//command is the String program or continousOutput
((ChannelExec)exec).setCommand(command);

exec.setInputStream(null);

((ChannelExec)exec).setErrStream(System.err);
InputStream in = exec.getInputStream();
exec.connect();

byte [] tmp = new byte[1024];
while(true) {
while(in.available()>0) {
int i = in.read(tmp, 0, 1024);
if(i<0)break;
String response = new String(tmp, 0, i);
check(response); //parse response
System.out.println(response);
//this.publish(); //desperate try to get something
}
if(exec.isClosed()) {
if(in.available() > 0) continue;
System.out.println("exit-status: " + exec.getExitStatus());
break;
}
try {Thread.sleep(1000);} catch(Exception ee) {}
}

exec.disconnect();
} catch (JSchException | IOException e) {
e.printStackTrace();
}

return null;
}

我不知道问题出在哪里。我的意思是它与脚本完美配合。

有什么想法吗?

最佳答案

简短的回答是为远程 session 分配 PTY(伪 TTY)。这可能会导致远程进程在运行时发出其输出,而不是在最后发出所有输出:

exec.setPty(true);

当您通过 unix 命令行运行程序时,您是通过 TTY 设备与该程序通信。当您通过 SSH 为 session 请求 PTY (TTY) 启动程序时,您是通过一组管道与程序通信,每个管道用于标准输入、输出和错误。

Unix 程序通常缓冲它们的输出。缓冲行为内置于大多数 C 程序使用的标准 I/O 逻辑中(也被 perl、python 等使用或复制)。写入 TTY 时,典型的行为是缓冲输出数据,直到写入整行(即程序写入换行符),然后将整行立即写入 TTY。这就是您以交互方式运行程序时的体验。

当写入管道或文件时,默认行为是缓冲直到缓冲区被填满。缓冲区的大小可能为 8 KB。此行为基于以下假设:输出不会发送给人类,因此程序应尽可能以最有效的方式运行。

你的描述听起来像是程序正在对其输出进行 block 缓冲,并且它没有产生足够的输出来在程序完成之前刷新缓冲区。您希望程序对其输出进行行缓冲(或完全取消缓冲)。有几种方法可以做到这一点:

  1. 您说当您以交互方式运行该程序时,它可以正常工作。正如我所指出的,为 ssh session 请求 PTY 可能会产生这种行为。
  2. 你可以看看是否像stdbuf这样的程序或 unbuffer在系统上可用。这些可用于改变进程的缓冲行为。
  3. 如果您有相关程序的源代码,您可以将逻辑添加到 alter the default buffering behavior , 或到 flush the buffer在程序执行的某些时刻。

关于java - JSch ChannelExec OutputStream 不显示程序输出。但是它适用于 shell 脚本,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48193390/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com