• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 {
main(String[] args)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