我希望能够将Java应用程序中表示为字符串的许多连续命令发送到SSH服务器以供执行。我应该用途:
Channel channel = session.openChannel("shell");
字符串
Channel channel = session.openChannel("exec");
型
5t7ly7z51#
有关这些流之间的差异和相似性的概述,您可以在JSch wiki的» Shell, Exec or Subsystem Channel «中找到。下面是您的用例的一些详细信息。在exec channel中,命令来自您在setCommand()中给予的命令字符串。SSH服务器将立即将它们传递给shell(使用类似bash -c '<command>'的东西)。如果shell由于某种原因没有以某种方式退出,它们都将被执行。(如果需要的话,你可以在这里发送一个完整的shell脚本,它使用if和类似的东西实现一些逻辑。因此,要执行多个命令,您可以通过使用;或换行符(\n)将它们分隔开来将它们传递到exec通道。由于在给出所有命令之前不能等待结果,因此在这里只能使用多个exec通道(但是由于每个通道都会产生一个新的shell,因此它们不会保存它们之间的状态,例如工作目录或shell变量)。在shell channel中,shell将从流中读取输入,并将第一行解释为一个命令(或多个命令)。然后它将执行此命令。如果需要,命令本身可以从流中读取更多输入。然后shell将读取下一行,将其解释为命令并执行。(In在某些情况下,shell必须读取不止一行,例如对于长字符串或复合命令,如if或loops。这将继续直到流的结束(例如,close())或执行显式退出命令。如果您没有通过channels输入/输出流向shell发送任何输入,shell将简单地等待,直到您发送更多或关闭流。因此,您可以安静地读取一个命令的输出,在客户端进行一些计算,然后决定下一个发送哪个命令。只要确保不要将一个命令的输入与下一个命令的文本混合在一起-最好不要使用任何将从标准输入读取的命令。
exec
setCommand()
bash -c '<command>'
if
;
\n
shell
pu82cl6c2#
使用shell通道,shell(在Unix上是sh或bash或类似的东西,在Windows上通常是cmd.exe)被启动并创建控制台(如果您在本地运行它们,您会在屏幕上看到相同的内容)。您有一个提示符,可以解析或使用它来检测命令的完成。使用命令通道,为每个命令启动一个shell示例(实际上为每个命令打开通道),并将命令作为shell的参数传递(在Windows上看起来像“cmd.exe /c <your command here>”)。使用命令通道更容易,因为你不需要处理命令提示符。
sh
bash
cmd.exe
cmd.exe /c <your command here>
mm5n2pyu3#
好吧,我发现这是可行的,如果你想像普通shell一样保存状态,这真的很方便:
Session session = jsch.getSession(user, host, 22); Channel channel = session.openChannel("shell"); OutputStream inputstream_for_the_channel = channel.getOutputStream(); PrintStream commander = new PrintStream(inputstream_for_the_channel, true); channel.setOutputStream(System.out, true); channel.connect(); commander.println("ls -la"); commander.println("cd folder"); commander.println("ls -la"); commander.println("exit"); commander.close(); do { Thread.sleep(1000); } while(!channel.isEOF()); session.disconnect();
字符串你可以改变
channel.setOutputStream(System.out, true);
型至
InputStream outputstream_from_the_channel = channel.getInputStream(); BufferedReader br = new BufferedReader(new InputStreamReader(outputstream_from_the_channel)); String line; while ((line = br.readLine()) != null) System.out.print(line+"\n");
编辑:跟进为什么有时我通过PrintStream发送的命令会随机出现在输出中。即以下代码:
shell[0].println("cd .."); shell[0].println("cd .."); shell[0].println("ls -la"); shell[0].println("exit");
型产生这个:(用{thing}标记的是不应该在那里的东西!)最后登录:Thu Jul 21 21:49:13 2011 from gateway舱单:trunk-latest[host~]$ cd ..{cd..}[host home]$[host Home]$ cd..[host/]$[host/]$ ls -la{退出}共9999
0x6upsns4#
这跟JSch没什么关系它是关于服务器如何实现这两个通道的。
在正常情况下,shell通道显然由SSH终端客户端(如OpenSSH ssh或PuTTY)使用。shell通道是一个具有输入和输出的黑盒子。输入和输出没有结构。例如,如果您通过将命令发送到输入端来执行命令,则永远无法知道它何时结束。如果您向输入队列发送两个命令,您将无法区分哪个输出来自哪个命令。
ssh
exec通道的用途是自动执行命令。因此,通常您不希望使用终端仿真,以避免命令执行分页、着色和主要是交互式确认等花哨的操作。当您在OpenSSH ssh或PuTTY plink的命令行上指定要执行的命令时,exec通道将由OpenSSH ssh或PuTTY plink使用:
plink
ssh user@host command
字符串对于不太常见的SSH服务器,这种差异可能更加显著。有些服务器甚至可能不支持其中一个通道。同样常见的是,它们似乎同时支持这两种功能,但其中一种(通常是exec)完全损坏了。Python/Paramiko也有类似的问题:What is the difference between exec_command and send with invoke_shell() on Paramiko?
4条答案
按热度按时间5t7ly7z51#
有关这些流之间的差异和相似性的概述,您可以在JSch wiki的» Shell, Exec or Subsystem Channel «中找到。下面是您的用例的一些详细信息。
在
exec
channel中,命令来自您在setCommand()
中给予的命令字符串。SSH服务器将立即将它们传递给shell(使用类似bash -c '<command>'
的东西)。如果shell由于某种原因没有以某种方式退出,它们都将被执行。(如果需要的话,你可以在这里发送一个完整的shell脚本,它使用
if
和类似的东西实现一些逻辑。因此,要执行多个命令,您可以通过使用
;
或换行符(\n
)将它们分隔开来将它们传递到exec通道。由于在给出所有命令之前不能等待结果,因此在这里只能使用多个exec通道(但是由于每个通道都会产生一个新的shell,因此它们不会保存它们之间的状态,例如工作目录或shell变量)。在
shell
channel中,shell将从流中读取输入,并将第一行解释为一个命令(或多个命令)。然后它将执行此命令。如果需要,命令本身可以从流中读取更多输入。
然后shell将读取下一行,将其解释为命令并执行。
(In在某些情况下,shell必须读取不止一行,例如对于长字符串或复合命令,如if或loops。
这将继续直到流的结束(例如,close())或执行显式退出命令。
如果您没有通过channels输入/输出流向shell发送任何输入,shell将简单地等待,直到您发送更多或关闭流。因此,您可以安静地读取一个命令的输出,在客户端进行一些计算,然后决定下一个发送哪个命令。
只要确保不要将一个命令的输入与下一个命令的文本混合在一起-最好不要使用任何将从标准输入读取的命令。
pu82cl6c2#
使用shell通道,shell(在Unix上是
sh
或bash
或类似的东西,在Windows上通常是cmd.exe
)被启动并创建控制台(如果您在本地运行它们,您会在屏幕上看到相同的内容)。您有一个提示符,可以解析或使用它来检测命令的完成。使用命令通道,为每个命令启动一个shell示例(实际上为每个命令打开通道),并将命令作为shell的参数传递(在Windows上看起来像“
cmd.exe /c <your command here>
”)。使用命令通道更容易,因为你不需要处理命令提示符。
mm5n2pyu3#
好吧,我发现这是可行的,如果你想像普通shell一样保存状态,这真的很方便:
字符串
你可以改变
型
至
型
如果你想要更多的控制输出。
编辑:跟进
为什么有时我通过PrintStream发送的命令会随机出现在输出中。即以下代码:
型
产生这个:(用{thing}标记的是不应该在那里的东西!)
最后登录:Thu Jul 21 21:49:13 2011 from gateway
舱单:trunk-latest
[host~]$ cd ..
{cd..}[host home]$
[host Home]$ cd..
[host/]$
[host/]$ ls -la
{退出}
共9999
---------- 1 root root 3550 May 14 2010 .bash_history
d-2 root root 4096 Apr 26 04:02 put
d- 5 root root 4024 Apr 25 19:31 Boot
[m[host /]$
[host/]$ exit
注销
0x6upsns4#
这跟JSch没什么关系它是关于服务器如何实现这两个通道的。
shell
通道执行登录shell(就像您使用SSH终端客户端登录一样)。然后,shell将显示命令提示符,并等待客户端/用户键入命令。shell
通道的用途是实现交互式shell会话。这是一个人很少会做的事情。如果这样做,通常需要使用终端仿真。在正常情况下,
shell
通道显然由SSH终端客户端(如OpenSSHssh
或PuTTY)使用。shell
通道是一个具有输入和输出的黑盒子。输入和输出没有结构。例如,如果您通过将命令发送到输入端来执行命令,则永远无法知道它何时结束。如果您向输入队列发送两个命令,您将无法区分哪个输出来自哪个命令。exec
命令将命令作为“参数”,并在隔离的环境中执行它-仍然通过用户的默认shell,但不作为“登录”shell,这可能会导致命令执行的显著差异。exec
通道的用途是自动执行命令。因此,通常您不希望使用终端仿真,以避免命令执行分页、着色和主要是交互式确认等花哨的操作。当您在OpenSSH
ssh
或PuTTYplink
的命令行上指定要执行的命令时,exec
通道将由OpenSSHssh
或PuTTYplink
使用:字符串
对于不太常见的SSH服务器,这种差异可能更加显著。有些服务器甚至可能不支持其中一个通道。同样常见的是,它们似乎同时支持这两种功能,但其中一种(通常是
exec
)完全损坏了。Python/Paramiko也有类似的问题:
What is the difference between exec_command and send with invoke_shell() on Paramiko?