aboutsummaryrefslogtreecommitdiff
path: root/examples/SingleThreadStdoutStderr.java
blob: 10a4d960d6ac110e6119a5d16240861a2a94e592 (plain)
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
/*
 * 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);
		}
	}
}