1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142
|
import java.io.IOException;
import java.io.InputStream;
import com.trilead.ssh2.ChannelCondition;
import com.trilead.ssh2.Connection;
import com.trilead.ssh2.Session;
/**
* This example shows how to use the Session.waitForCondition
* method to implement a state machine approach for
* proper stdout/stderr output handling in a single thread.
*
* @author Christian Plattner, plattner@trilead.com
* @version $Id: SingleThreadStdoutStderr.java,v 1.6 2007/10/15 12:49:57 cplattne Exp $
*/
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);
}
}
}
|