“外壳”和“外壳”有什么区别?通道和“exec”; JSch 中的频道
我希望能够将 Java 应用程序中表示为字符串的许多连续命令发送到 SSH 服务器以供执行。我应该使用:
Channel channel = session.openChannel("shell");
-或-
Channel channel = session.openChannel("exec");
I want to be able to send many consecutive command represented as strings within a Java application to a SSH server for execution. Should I use:
Channel channel = session.openChannel("shell");
-or-
Channel channel = session.openChannel("exec");
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
有关这些流之间的差异和相似之处的概述,您可以在 » 找到JSch wiki 中的 Shell、Exec 或子系统通道«。这里有一些适合您的用例的详细信息。
在
exec< /code> 通道
,命令来自您使用' 的内容)。
setCommand()
给出的命令字符串。 SSH 服务器会将它们立即传递到 shell(使用类似 bash -c '如果 shell 由于某种原因之前没有退出,它们都会被执行。 (如果需要的话,您可以在此处发送一个完整的 shell 脚本,该脚本使用
if
和类似的方法实现一些逻辑。)因此,要执行多个命令,您可以通过将它们分隔开来将它们传递到 exec 通道
;
或换行符 (\n
)。由于在给出所有命令之前您无法等待结果,因此这里您只能使用多个 exec 通道(但当每个通道生成一个新的 shell 时,它们不会在它们之间保存状态,例如工作目录或 shell 变量)。在
shell< /code> 通道
,shell 将从流中读取输入,并将第一行解释为一个命令(或多个命令)。
然后它就会执行这个命令。如果需要,命令本身可能会从流中读取更多输入。
然后 shell 将读取下一行,将其解释为命令并执行。
(在某些情况下,shell 必须读取多行,例如长字符串或组合命令(如 if 或循环)。)
这将一直持续到流的末尾(例如您这边的 stream.close() )或执行显式退出命令。
如果您不通过通道输入/输出流向 shell 发送任何输入,shell 将只是等待,直到您发送更多输入或关闭流。因此,您可以安静地读取一个命令的输出,在客户端进行一些计算,然后决定下一个发送哪个命令。
只需确保不要将一个命令的输入与下一个命令的文本混合 - 最好不要使用将从标准输入读取的任何命令。
An overview about the differences and similarities between these streams you can find at »Shell, Exec or Subsystem Channel« in the JSch wiki. Here some details for your use case.
In the
exec
channel, the commands come from the command string you did give withsetCommand()
. The SSH server will pass them at once to the shell (using something likebash -c '<command>'
).They will all be executed, if the shell does not somehow exit before for some reason. (You could send a whole shell script here which implements some logic using
if
and similar, if this is wanted.)So, to execute multiple commands, you could pass them to the exec channel by separating them with
;
or newline (\n
). As you can't wait for the results before giving all the commands, here you can only use multiple exec channels (but as each channel spawns a new shell, they don't conserve state between them, like working directory or shell variables).In the
shell
channel, the shell will read input from the stream, and interpret the first line as a command (or several ones).Then it will execute this command. The command itself might read more input from the stream, if it wants.
Then the shell will read the next line, interpret it as a command, and execute.
(In some cases the shell has to read more than one line, for example for long strings or composed commands like if or loops.)
This will go on until either the end of the stream (e.g. stream.close() at your side) or executing an explicit exit command.
If you don't send any input to the shell via the channels input/output stream, the shell will simply wait until you either send more or close the stream. Thus you can quietly read the output of one command, do some calculations on the client side and then decide which command to send next.
Just make sure you don't mix input to one command with the text of the next command - preferably don't use any commands which will read from standard input.
通过 shell 通道,shell(在 Unix 上是
sh
或bash
或类似的东西,在 Windows 上通常是cmd.exe
)启动并控制台已创建(如果您在本地运行它们,则与您在屏幕上看到的相同)。您有一个可以解析或用于检测命令完成情况的提示。使用命令通道,将为每个命令启动一个 shell 实例(实际上为每个命令打开通道),并将命令作为 shell 的参数传递(在 Windows 上,它看起来像“
cmd.exe /c <你的命令在这里>
”。使用命令通道更容易,因为你不需要处理命令提示符。
With shell channel the shell (on Unix it's
sh
orbash
or something like that, on Windows it's usuallycmd.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 <your command here>
".It's easier to use command channel cause you don't need to deal with command prompt.
好吧,我发现这是可行的,如果您想像常规 shell 一样保留状态,它真的很方便:
您可以更改
为
如果您想对输出进行更多控制,
。 =================================================== ===========================
编辑:跟进
为什么有时我通过 PrintStream 发送的命令随机出现在输出中。 IE
下面的代码:
产生这样的结果:
(标有{thing}的是不应该存在的东西!)
well, I found out that this works and it's really convenient if you want to preserve state like a regular shell would:
You could change
to
if you want more control over the output.
=============================================================================
EDITED: follow up
why sometimes the commands I send through the PrintStream appear randomly in the output. i.e.
the following code:
produces this:
(marked with {thing} are things that shouldnt be there!)
与 JSch 无关。是关于服务器如何实现这两个通道的。
在常见的 *nix OpenSSH 服务器中:
shell
通道执行登录 shell(就像使用 SSH 终端客户端登录一样)。然后 shell 将显示命令提示符并等待客户端/用户键入命令。shell
通道的目的是实现交互式 shell 会话。这是人们很少会做的事情。如果这样做,您通常希望使用终端仿真。正常情况下,
shell
通道显然由 SSH 终端客户端(例如 OpenSSHssh
或 PuTTY)使用。shell
通道是一个带有输入和输出的黑匣子。输入和输出没有结构。例如,如果您通过将命令发送到输入来执行命令,您将永远无法知道它何时结束。如果您向输入队列发送两个命令,您将无法区分哪个输出来自哪个命令。exec
命令将命令作为“参数”并在隔离环境中执行它 - 仍然通过用户的默认 shell,但不是作为“登录”shell,这可能会导致显着差异命令执行。exec
通道的目的是自动执行命令。因此,通常您不想使用终端仿真,以避免使用命令执行分页、着色和主要交互式确认等花哨的操作。当您指定要在其命令行上执行的命令时,
exec
通道由 OpenSSHssh
或 PuTTYplink
使用:对于不太常见的 SSH 服务器,差异可能更加显着。有些服务器甚至可能不支持其中一个通道。还有一种很常见的情况是,它们似乎都支持两者,但其中一个(通常是 exec)完全被破坏了。
Python/Paramiko 有一个类似的问题:
Paramiko 上的 exec_command 和使用 invoke_shell() 发送有什么区别?
It's not so much about JSch. It's about how the server implements the two channels.
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. That is something one will do very very rarely. If you do, you typically want to use 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.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.exec
channel is used by OpenSSHssh
or PuTTYplink
, when you specify a command to execute on its command line: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.There's a similar question for Python/Paramiko:
What is the difference between exec_command and send with invoke_shell() on Paramiko?