我想检查exit
命令在 ssh 会话中是否执行成功。
我的第一次尝试是使用命令:
exit && echo $? || echo $?`.The `echo $? || echo $?
0
如果退出成功,它应该打印。问题是echo
如果执行成功则永远不会执行,exit
因为连接断开并且后面的命令丢失。
我的第二次尝试是将命令拆分为两个命令,如下所示:
$ exit
$ echo $?
echo $?
0
如果exit
执行成功应该是。但另一个问题echo $?
可能会被吞掉,因为它发送得太快,以至于在exit
执行之前就到达了远程 ssh 主机。
那么,如何确保exit
在发送下一个命令之前在远程主机上执行?
更新#1
使用阶段是我以程序语言执行shell命令并通过ssh管道流发送消息。所以,我不知道exit
命令执行的时间。如果exit
命令未完成,我的后续命令将被吞没,因为它们发送到退出主机。
这就是为什么我关心exit
执行的命令。
更新#2
1.我在哪个阶段遇到了问题?
一开始,我想尽可能简单地描述问题,但似乎更令人困惑。我正在用 Scala 语言编写一个 SSH 库,位于git 库。
它不是交互式终端。来自远程主机的响应消息是网络IO流,由程序保存,将结果解析为字符串。这意味着,我必须处理每个字符代码,并最终决定命令执行的成功或失败。
一些示例代码如下所示:
//create a ssh by JSch library which is a SSH implement by Java Language.
val shell = Shell(Auth("host", "username", 22, "mypassword"))
//execute shell command as we do at terminal for example.
val rst1 = shell.exc("ls")
//create a new shell based on this shell.
val newShell = shell.newShell(Auth("xxx.xxx.xxx.xxx", "username2", 22, "mypassword"))
//do something on the new shell
val rst2 = newShell.exc("touch somefile")
//exit from new shell
newShell.exit()
是由 发送的正常命令newShell
创建的,所以它不是什么魔法。就像发送普通命令一样,例如. sshpass -p 'password' ssh -T username@hostname
JSch
ls
问题出在exit()
方法的实现上,如果我们忽略Scala代码,它就会变成那些shell命令:
$ echo '' && echo 'some-splitter-string' && exit
$ echo $? && echo 'some-splitter-string'
将该命令发送到远程主机后,我期望的响应是这样的,但实际上它没有,我显式附加一个\n
字符以便直接读取:
\n
some-splitter-string\n
0\n
some-splitter-string\n
这意味着,我可以将 IO 流分割成两倍some-splitter-string
,并让内部0
(也许是其他)来决定exit
命令执行完成,这是我解码 shell 命令结果的协议。
2. 到底是什么问题?
实际上,该exit()
命令只是回应我:
\n
some-splitter-string\n
第二条命令echo $? && echo 'some-splitter-string'
丢失了!那是因为该命令$ echo $? && echo 'some-splitter-string'
也发送到 newShell 主机。
但exit
完成后,该命令被newShell主机吞掉。简单地考虑一下这个命令exit && touch somefile
。后者touch somefile
永远无法被处决。
我目前的解决方案是发送命令后睡眠1秒echo '' && echo 'some-splitter-string' && exit
,它应该更优雅。所以我想找到一种方法来确保exit
执行,然后我将发送第二个命令来完成我的协议。
3.一些需要澄清的问题:
exit的“执行”怎么会失败呢?
此时不完全关注失败或成功。这意味着,如果exit
不能失败,只要让我知道它执行完成就可以了。我们在这里讨论的是 shell 退出吗?
是的,问题的目的是找到一种方法来决定在 ssh 管道环境中执行完整的退出命令。