Home | History | Annotate | Download | only in examples
      1 /*
      2  * Copyright (c) 2006-2011 Christian Plattner. All rights reserved.
      3  * Please refer to the LICENSE.txt for licensing details.
      4  */
      5 import java.io.IOException;
      6 import java.io.InputStream;
      7 
      8 import ch.ethz.ssh2.ChannelCondition;
      9 import ch.ethz.ssh2.Connection;
     10 import ch.ethz.ssh2.Session;
     11 
     12 public class SingleThreadStdoutStderr
     13 {
     14 	public static void main(String[] args)
     15 	{
     16 		String hostname = "127.0.0.1";
     17 		String username = "joe";
     18 		String password = "joespass";
     19 
     20 		try
     21 		{
     22 			/* Create a connection instance */
     23 
     24 			Connection conn = new Connection(hostname);
     25 
     26 			/* Now connect */
     27 
     28 			conn.connect();
     29 
     30 			/* Authenticate */
     31 
     32 			boolean isAuthenticated = conn.authenticateWithPassword(username, password);
     33 
     34 			if (isAuthenticated == false)
     35 				throw new IOException("Authentication failed.");
     36 
     37 			/* Create a session */
     38 
     39 			Session sess = conn.openSession();
     40 
     41 			sess.execCommand("echo \"Huge amounts of text on STDOUT\"; echo \"Huge amounts of text on STDERR\" >&2");
     42 
     43 			/*
     44 			 * Advanced:
     45 			 * The following is a demo on how one can read from stdout and
     46 			 * stderr without having to use two parallel worker threads (i.e.,
     47 			 * we don't use the Streamgobblers here) and at the same time not
     48 			 * risking a deadlock (due to a filled SSH2 channel window, caused
     49 			 * by the stream which you are currently NOT reading from =).
     50 			 */
     51 
     52 			/* Don't wrap these streams and don't let other threads work on
     53 			 * these streams while you work with Session.waitForCondition()!!!
     54 			 */
     55 
     56 			InputStream stdout = sess.getStdout();
     57 			InputStream stderr = sess.getStderr();
     58 
     59 			byte[] buffer = new byte[8192];
     60 
     61 			while (true)
     62 			{
     63 				if ((stdout.available() == 0) && (stderr.available() == 0))
     64 				{
     65 					/* Even though currently there is no data available, it may be that new data arrives
     66 					 * and the session's underlying channel is closed before we call waitForCondition().
     67 					 * This means that EOF and STDOUT_DATA (or STDERR_DATA, or both) may
     68 					 * be set together.
     69 					 */
     70 
     71 					int conditions = sess.waitForCondition(ChannelCondition.STDOUT_DATA | ChannelCondition.STDERR_DATA
     72 							| ChannelCondition.EOF, 2000);
     73 
     74 					/* Wait no longer than 2 seconds (= 2000 milliseconds) */
     75 
     76 					if ((conditions & ChannelCondition.TIMEOUT) != 0)
     77 					{
     78 						/* A timeout occured. */
     79 						throw new IOException("Timeout while waiting for data from peer.");
     80 					}
     81 
     82 					/* Here we do not need to check separately for CLOSED, since CLOSED implies EOF */
     83 
     84 					if ((conditions & ChannelCondition.EOF) != 0)
     85 					{
     86 						/* The remote side won't send us further data... */
     87 
     88 						if ((conditions & (ChannelCondition.STDOUT_DATA | ChannelCondition.STDERR_DATA)) == 0)
     89 						{
     90 							/* ... and we have consumed all data in the local arrival window. */
     91 							break;
     92 						}
     93 					}
     94 
     95 					/* OK, either STDOUT_DATA or STDERR_DATA (or both) is set. */
     96 
     97 					// You can be paranoid and check that the library is not going nuts:
     98 					// if ((conditions & (ChannelCondition.STDOUT_DATA | ChannelCondition.STDERR_DATA)) == 0)
     99 					//	throw new IllegalStateException("Unexpected condition result (" + conditions + ")");
    100 				}
    101 
    102 				/* If you below replace "while" with "if", then the way the output appears on the local
    103 				 * stdout and stder streams is more "balanced". Addtionally reducing the buffer size
    104 				 * will also improve the interleaving, but performance will slightly suffer.
    105 				 * OKOK, that all matters only if you get HUGE amounts of stdout and stderr data =)
    106 				 */
    107 
    108 				while (stdout.available() > 0)
    109 				{
    110 					int len = stdout.read(buffer);
    111 					if (len > 0) // this check is somewhat paranoid
    112 						System.out.write(buffer, 0, len);
    113 				}
    114 
    115 				while (stderr.available() > 0)
    116 				{
    117 					int len = stderr.read(buffer);
    118 					if (len > 0) // this check is somewhat paranoid
    119 						System.err.write(buffer, 0, len);
    120 				}
    121 			}
    122 
    123 			/* Close this session */
    124 
    125 			sess.close();
    126 
    127 			/* Close the connection */
    128 
    129 			conn.close();
    130 
    131 		}
    132 		catch (IOException e)
    133 		{
    134 			e.printStackTrace(System.err);
    135 			System.exit(2);
    136 		}
    137 	}
    138 }
    139