Shell, Exec or Subsystem Channel
The channel types shell, exec and subsystem are the main channels for execution and interaction with some remote process.
- Create, setup and connect your Session object
- create the channel with
session.openChannel(type)(where type is one of
- The result will be of one of the subclasses of Channel mentioned below, depending on the type, and you can cast it to this class.
- Do some initialization (depending on the channel).
- Setup the input and output streams, enable X and/or authentication agent forwarding, setup a pseudo-terminal.
- Interact with the remote process using the streams (and sendSignal), wait until the process finishes (or close it yourself)
You can try to pass environment variables to the remote process by channel.setEnv(name, value). It will depend on the server configuration which of these variables can actually be seen by the process.
You can allocate a pseudo terminal for the remote process by channel.setPty(true). With setTerminalMode, setPtySize and setPtyType you can configure this terminal further.
X11 and Agent forwarding
With setXForwarding(true) you can enable X11 forwarding - this means, the remote process will have the DISPLAY environment variable set, and if it tries to connect to this display, the connection will be forwarded to the local X server. Also, the X11 authentication will be handled.
You should only use this if you actually locally have an X server. If you are on a non-X windowing system, you might want to use a Java implementation of an X server, like WeirdX or WiredX (from the same author as JSch).
For this to work, you need to have set the details of your local server with the
setX11...() methods of Session. Most important (because it does not have a sensible default) is setX11Cookie(...), needed to set the X11 authorization cookie (e.g. the output of
xauth list $DISPLAY | egrep -o '[0-9a-f]*$', where $DISPLAY is the display we actually want to connect to).
JSch can only connect to the X server using TCP sockets, not using unix-domain sockets or other local means. If your X server is not reachable by TCP, you can use (on unixoid systems, at least) the socat program to forward it:
socat TCP-LISTEN:6000,fork,bind=localhost UNIX-CONNECT:/tmp/.X11-unix/X0
With setAgentForwarding(true) you can enable forwarding of the SSH authentication agent. This allows using your local private keys for ssh connections from the remote host (without giving the key to this host).
There are three byte streams for each Channel:
- input (from client to server). Use getOutputStream or setInputStream.
- output (from server to client). Use getInputStream or setOutputStream.
- error output (from server to client). Use setErrStream or getErrStream (alternatively setExtOutputStream and getExtInputStream).
Each of these support a polling and a pushing variant:
- For the input you can either provide an InputStream from which the library will read (and pass the data to remote process) or obtain an OutputStream to which your application can write.
- For output and error output, you in each case can either provide an OutputStream to which the library will write, or obtain an InputStream from which your application can read.
If you don't supply/obtain one of these streams before channel.connect(), the arriving data will be silently discarded (in the case of (error) output), or the remote process will get "end of file" (in the case of input).
The individual channel types
A shell channel starts the default shell of the remote user, and allows interacting with it by the streams. The shell will use its input stream for both commands and input to these commands. In JSch, an shell channel is represented by the ChannelShell class.
There is no additional setup necessary.
Note: There is no sure way for the client to recognize when one of the commands executed inside the shells is finished and you can give the next one, if you don't know what the commands are doing. For this reason, a shell channel is mostly useful for interactive use by human users, not for executing multiple commands in sequence programmatically. For this, better use one or multiple exec channels (see below).
An exec channel will pass a command (given as a string) to the remote user's default shell, which should the execute it. The streams are passed to this command. In JSch, an exec channel is represented by the ChannelExec class.
You indicate the command to be executed with the setCommand method (either as a string or a UTF-8 byte array).
Depending on the user's default shell you can usually provide multiple commands by separating them with
The basic "exec" example is in Exec, with a swing dialogs to obtain the command to execute. It also demonstrates reading the output and waiting on the closing of the channel.
The common unix scp command is often also implemented by an exec channel (when using the SSH 2 protocol), using scp -t ... or scp -f ... as commands. The examples ScpTo (and its variant ScpToNoneCipher) and ScpFrom show a Java version of the client side of this. The article How the SCP protocol works explains what is read/written here to the channel.
A subsystem channel executes some command as a subsystem of the server. The conceptual difference to the exec channel is that the server configuration defines the meaning of the command, not the user's default shell. In JSch, a generic subsystem channel is represented by the ChannelSubsystem class.
You indicate the subsystem to be used with the setSubsystem method.
One commonly available subsystem is sftp, implementing the Secure File Transfer Protocol - for this, JSch has a specialized Sftp Channel.
The example Subsystem connects to a generic subsystem, the name given by the user in a Swing dialog.