Reading JSch Command Output: Resolving Output Deadlock
This code consistently hangs while attempting to read from the Reader instance:
JSch jsch = new JSch(); jsch.setKnownHosts(dotSshDir + "/known_hosts"); jsch.addIdentity(dotSshDir + "/id_rsa"); Session session = jsch.getSession(userName, hostname, 22); session.connect(); ChannelExec channel = (ChannelExec) session.openChannel("exec"); channel.setCommand(command); channel.setInputStream(null); channel.setErrStream(System.err); Reader reader = new InputStreamReader(channel.getInputStream()); char[] buf = new char[1024]; int numRead; while ((numRead = reader.read(buf)) != -1) { String readData = String.valueOf(buf, 0, numRead); result.append(readData); buf = new char[1024]; }
Root Cause:
The problem arises because the code is not reading the output continuously while waiting for the command to complete. When the command generates sufficient output to fill the output buffer, the command halts, awaiting the consumption of the buffer. However, this never occurs, leading to a deadlock.
Solution:
To resolve this issue, it is crucial to read both the stdout and stderr streams continuously while monitoring the command status:
ChannelExec channel = (ChannelExec)session.openChannel("exec"); channel.setCommand( "for((i=1;i<=10000;i+=2)); do echo \"Long output - $i\"; done ; " + "echo error output >&2"); ByteArrayOutputStream outputBuffer = new ByteArrayOutputStream(); ByteArrayOutputStream errorBuffer = new ByteArrayOutputStream(); InputStream in = channel.getInputStream(); InputStream err = channel.getExtInputStream(); channel.connect(); byte[] tmp = new byte[1024]; while (true) { while (in.available() > 0) { int i = in.read(tmp, 0, 1024); if (i < 0) break; outputBuffer.write(tmp, 0, i); } while (err.available() > 0) { int i = err.read(tmp, 0, 1024); if (i < 0) break; errorBuffer.write(tmp, 0, i); } if (channel.isClosed()) { if ((in.available() > 0) || (err.available() > 0)) continue; System.out.println("exit-status: " + channel.getExitStatus()); break; } try { Thread.sleep(1000); } catch (Exception ee) { } } System.out.println("output: " + outputBuffer.toString("UTF-8")); System.out.println("error: " + errorBuffer.toString("UTF-8")); channel.disconnect();
This approach ensures that the output is read continuously, preventing the deadlock.
The above is the detailed content of How to Prevent JSch Command Output Deadlock and Ensure Continuous Reading?. For more information, please follow other related articles on the PHP Chinese website!