| /* |
| * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. |
| * Please refer to the LICENSE.txt for licensing details. |
| */ |
| import java.io.IOException; |
| import java.io.InputStream; |
| |
| import ch.ethz.ssh2.ChannelCondition; |
| import ch.ethz.ssh2.Connection; |
| import ch.ethz.ssh2.Session; |
| |
| public class SingleThreadStdoutStderr |
| { |
| public static void main(String[] args) |
| { |
| String hostname = "127.0.0.1"; |
| String username = "joe"; |
| String password = "joespass"; |
| |
| try |
| { |
| /* Create a connection instance */ |
| |
| Connection conn = new Connection(hostname); |
| |
| /* Now connect */ |
| |
| conn.connect(); |
| |
| /* Authenticate */ |
| |
| boolean isAuthenticated = conn.authenticateWithPassword(username, password); |
| |
| if (isAuthenticated == false) |
| throw new IOException("Authentication failed."); |
| |
| /* Create a session */ |
| |
| Session sess = conn.openSession(); |
| |
| sess.execCommand("echo \"Huge amounts of text on STDOUT\"; echo \"Huge amounts of text on STDERR\" >&2"); |
| |
| /* |
| * Advanced: |
| * The following is a demo on how one can read from stdout and |
| * stderr without having to use two parallel worker threads (i.e., |
| * we don't use the Streamgobblers here) and at the same time not |
| * risking a deadlock (due to a filled SSH2 channel window, caused |
| * by the stream which you are currently NOT reading from =). |
| */ |
| |
| /* Don't wrap these streams and don't let other threads work on |
| * these streams while you work with Session.waitForCondition()!!! |
| */ |
| |
| InputStream stdout = sess.getStdout(); |
| InputStream stderr = sess.getStderr(); |
| |
| byte[] buffer = new byte[8192]; |
| |
| while (true) |
| { |
| if ((stdout.available() == 0) && (stderr.available() == 0)) |
| { |
| /* Even though currently there is no data available, it may be that new data arrives |
| * and the session's underlying channel is closed before we call waitForCondition(). |
| * This means that EOF and STDOUT_DATA (or STDERR_DATA, or both) may |
| * be set together. |
| */ |
| |
| int conditions = sess.waitForCondition(ChannelCondition.STDOUT_DATA | ChannelCondition.STDERR_DATA |
| | ChannelCondition.EOF, 2000); |
| |
| /* Wait no longer than 2 seconds (= 2000 milliseconds) */ |
| |
| if ((conditions & ChannelCondition.TIMEOUT) != 0) |
| { |
| /* A timeout occured. */ |
| throw new IOException("Timeout while waiting for data from peer."); |
| } |
| |
| /* Here we do not need to check separately for CLOSED, since CLOSED implies EOF */ |
| |
| if ((conditions & ChannelCondition.EOF) != 0) |
| { |
| /* The remote side won't send us further data... */ |
| |
| if ((conditions & (ChannelCondition.STDOUT_DATA | ChannelCondition.STDERR_DATA)) == 0) |
| { |
| /* ... and we have consumed all data in the local arrival window. */ |
| break; |
| } |
| } |
| |
| /* OK, either STDOUT_DATA or STDERR_DATA (or both) is set. */ |
| |
| // You can be paranoid and check that the library is not going nuts: |
| // if ((conditions & (ChannelCondition.STDOUT_DATA | ChannelCondition.STDERR_DATA)) == 0) |
| // throw new IllegalStateException("Unexpected condition result (" + conditions + ")"); |
| } |
| |
| /* If you below replace "while" with "if", then the way the output appears on the local |
| * stdout and stder streams is more "balanced". Addtionally reducing the buffer size |
| * will also improve the interleaving, but performance will slightly suffer. |
| * OKOK, that all matters only if you get HUGE amounts of stdout and stderr data =) |
| */ |
| |
| while (stdout.available() > 0) |
| { |
| int len = stdout.read(buffer); |
| if (len > 0) // this check is somewhat paranoid |
| System.out.write(buffer, 0, len); |
| } |
| |
| while (stderr.available() > 0) |
| { |
| int len = stderr.read(buffer); |
| if (len > 0) // this check is somewhat paranoid |
| System.err.write(buffer, 0, len); |
| } |
| } |
| |
| /* Close this session */ |
| |
| sess.close(); |
| |
| /* Close the connection */ |
| |
| conn.close(); |
| |
| } |
| catch (IOException e) |
| { |
| e.printStackTrace(System.err); |
| System.exit(2); |
| } |
| } |
| } |