blob: 10a4d960d6ac110e6119a5d16240861a2a94e592 [file] [log] [blame]
/*
* 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);
}
}
}