What is the difference between the 'shell' channel and the 'exec' channel in JSch
With shell channel the shell (on unix it's sh or bash or something like that, on Windows it's usually cmd.exe) is started and console is created (the same you see on the screen if you run them locally). You have a prompt which you can parse or use for detection of completion of command.
With command channel a shell instance is started for each command (actually the channel is opened for each command) and a command is passed as a parameter for the shell (on Windows it would look like "cmd.exe /c ".
It's easier to use command channel cause you don't need to deal with command prompt.
what's the exact differences between jsch ChannelExec and ChannelShell?
The shell and exec channels are quite similar - both execute commands with the remote shell (at least, conceptually - the server might be configured to treat them differently, of course). RFC 4254 groups them in the section "Interactive Sessions", and they both (as well as subsystem, see below) use the channel type "session" in the SSH protocol.
There is one important difference:
For
ChannelShell
, the input stream provides both the commands and input to these commands. This is like using an interactive shell on your local computer. (And it is normally used just for that: interactive use.)For
ChannelExec
, the commands are given with setCommand() beforeconnect()
, and the input stream will be forwarded to these commands as input. (Most often, you will have only one command, but you can provide multiple ones using the normal shell separators&
,&&
,|
,||
,;
, newline, and compound commands.) This is like executing a shell script on your local computer. (Of course, if one of the commands itself is an interactive shell, this will behave like aChannelShell
.)There is a third similar one,
ChannelSubsystem
, which executes a subsystem of the ssh server - here the server's configuration decides what to do, not the remote user's shell. (The most often used subsystem issftp
, but for this JSch provides a specialized channel, which understands the protocol.)
Note that what I call "input stream" here is the stream of data in the channel from the local to the remote host – that can be actually be done by passing a Java InputStream to the setInputStream
method, or by getting a Java OutputStream from the getOutputStream
method and writing to it.
Performance takes a hit while using Java JSch exec vs shell to run multiple commands?
Yes, that's quite likely. The "exec" channel runs the command in an isolated environment (typically a new shell instance).
Setting up the environment on the server will likely take some time.
So it most likely has nothing to do with your Java code.
Why does reading from a shell channel output in JSch never end with -1?
The "shell" channel opens a shell.
We do not know what your code actually does. But I'd assume that you send some command to the shell to be executed and then you try to read the command output. And you probably expect to get -1 once the command output ends. You won't.
The shell output stream ends, only when the shell ends. And for that you need to send some command like exit
.
In general, you should not use the "shell" channel. It's intended for implementing an interactive shell session (like if you are implementing your own SSH terminal). That's something you rarely do.
To automate a command execution, use the "exec" channel.
See also What is the difference between the 'shell' channel and the 'exec' channel in JSch.
Executing multiple commands over SSH exec channel on firewall device with Java JSch does not work
The "exec" channel on your device seems to be implemented incorrectly. So you cannot use your code with the "exec" channel. As you can "ssh" to the device, it seems that the "shell" channel is fully working. Try talking to your server administrator, to get the server fixed.
If fixing the server is not feasible, you will have to revert to using the "shell" channel, although it is generally not the correct way to implement command automation.
See What is the difference between the 'shell' channel and the 'exec' channel in JSch
JSch by default enables terminal emulation for the "shell" channel, what will bring lot of unwanted side effects (see Getting unwanted characters when reading command output from SSH server using JSch). You may need to disable that by calling setPty
.
ChannelShell channel = (ChannelShell) session.openChannel("shell");
InputStream in = channel.getInputStream();
outStream = channel.getOutputStream();
channel.setPty(false);
channel.connect();
outStream.write('configure\n'.getBytes());
outStream.write('move shared pre-rulebase security rules TEST top\n'.getBytes());
Get output of a specific command only in JSch shell channel
You have to read the output to some buffer/string. Then parse out and print only the part you want.
See How to get jsch shell command output in String.
There's no other way to separate output of individual commands. From an SSH client perspective, the shell is just a black box with input/output. There's no structure. The "shell" should not be use to automate command execution. You should use the "exec" channel. See also What is the difference between the 'shell' channel and the 'exec' channel in JSch.
In the "exec" channel, you execute each command independently, so you won't have problems separating their output. See How to read JSch command output?
Anyway, if you want to stick with your suboptimal "shell" solution, it helps, when you print some delimiter before and after the script like:
echo ---begin---
/.../myscript.sh
echo ---end---
What is the difference between exec_command and send with invoke_shell() on Paramiko?
The difference is that invoke_shell
uses SSH shell
channel, while exec_command
uses SSH exec
channel.
What that really means to you as a user/developer really depends on the SSH server, not on Paramiko itself.
In common *nix OpenSSH server:
The
shell
channel executes a login shell (as if you login with SSH terminal client). The shell will then present a command prompt and wait for client/user to type the commands. The purpose of theshell
channel is to implement an interactive shell session. So basically it's legitimate use is an implementation of an SSH terminal client. That is something one will do very very rarely. If you do, you typically want to use terminal emulation (Paramikoinvoke_shell
does that unconditionally, but actually it's possible to open theshell
channel without the terminal emulation).The
shell
channel is obviously used by SSH terminal clients (like OpenSSHssh
or PuTTY), under normal circumstances.The
shell
channel is a black box with an input and output. The input and output have no structure. If you for example execute a command by sending it to the input, you will never be able to tell when it ended. If you send two commands to input queue, you won't be able to distinguish what output comes from what command.The
exec
command takes a command as an "argument" and executes it in an isolated environment – still via user's default shell, but not as a "login" shell, what may cause significant differences in the command execution.For a typical example of such difference, see Some Unix commands fail with "<command> not found", when executed using Python Paramiko exec_command.
The purpose of the
exec
channel is automating a command execution. So typically you do not want to use a terminal emulation, to avoid the command to do fancy stuff like pagination, coloring and mainly interactive confirmations. That's why the default value ofget_pty
isFalse
.The
exec
channel is used by OpenSSHssh
or PuTTYplink
, when you specify a command to execute on its command line:ssh user@host command
With less common SSH servers, the difference can be even more significant. Some servers may even not support one of the channels. It is also quite common that they seemingly support both, but one of them (typically the exec
) is completely broken.
See Executing command using Paramiko exec_command on device is not working.
There's a similar question for Java/JSch:
What is the difference between the 'shell' channel and the 'exec' channel in JSch
Implementing SSH shell terminal in webapp using JSch
If you want to implement an interactive shell, you have to use the "shell" channel, not the "exec" channel. The "exec" channel is intended for automating individual commands.
Some references:
- What is the difference between the 'shell' channel and the 'exec' channel in JSch
- JSch
Shell.java
example
Executing sudo using SSH exec channel in JSch
Your code executes each command in an isolated environment. So your second whoami
does not run within pbrun su
, as you probably hoped for.
The pbrun su
executes a new shell.
To provide a command to the shell you either:
specify the command on
su
command-line, like the official JSchSudo.java
example shows:((ChannelExec)channel).setCommand("pbrun su - fclaim -c whoami");
or feed the command to the shell using its standard input:
OutputStream out = channel.getOutputStream();
out.write(("whoami\n").getBytes());See also:
Executing multiple bash commands using a Java JSch program after sudo login and
Running command after sudo login.
In general, I recommend the first approach as it uses a better defined API (command-line argument).
JSch Channel.getExitStatus does not return status of command executed in shell channel
Do not execute commands in "shell" channel in the first place. The "shell" is a black box with an input and output only. See What is the difference between the 'shell' channel and the 'exec' channel in JSch
Use the "exec" channel. In the "exec" channel, the Channel.getExitStatus
works.
For a code example, see: How to read JSch command output?
Obligatory warning: Do not use StrictHostKeyChecking=no
to blindly accept all host keys. That is a security flaw. You lose a protection against MITM attacks. For the correct (and secure) approach, see: How to resolve Java UnknownHostKey, while using JSch SFTP library?
Related Topics
"Main Method Not Found" Error When Starting Program
Do We Need Volatile When Implementing Singleton Using Double-Check Locking
Add Jlabel with Image to Jlist to Show All the Images
Scanner Only Reads File Name and Nothing Else
How to Draw a Crisp, Opaque Hairline in Javafx 2.2
Using Spring Resttemplate in Generic Method with Generic Parameter
How to Create a Delay in Swing
Using Variables Outside of an If-Statement
How to Load Files into My Java Application
Convert Between Localdate and SQL.Date
How to Change the Color of Specific Words in a Jtextpane
Jaxb :Need Namespace Prefix to All the Elements
Java - Scroll to Specific Text Inside Jtextarea
How to Get the Parent Base Class Object Super.Getclass()
Why Functional Interfaces in Java 8 Have One Abstract Method