我可以通过 ssh 获取在子 shell 中执行的命令的退出代码吗?

发布于 2024-10-23 16:30:26 字数 612 浏览 1 评论 0原文

我正在尝试使用 Paramiko 编写部署脚本,但在运行命令的退出代码时遇到问题。我使用的代码类似于 这个答案,但有点复杂。基本上,从我们的开发盒中,我们必须经过一个跳转服务器,然后从那里到达一系列生产机器。一旦到达那里,我们必须切换到系统用户(sudo su - systemuser),然后我们可以运行命令。

问题是,据我了解,我有 3 个子 shell - ssh 会话、嵌套的 ssh 命令和 su 子 shell。我无法让 Paramiko 给我返回内部子 shell 中命令的退出代码 - 我猜它最终返回的退出代码将是 ssh 命令的退出代码。我怀疑这个问题实际上并不是 Paramiko 特有的 - SSH 协议是否支持这种用法?

我目前总是执行:

(my command); echo "Process terminated with exit code $?"

然后在客户端上解析它,但它非常丑陋 - 有更好的方法吗?

I'm trying to use Paramiko to write a deployment script, and I'm having trouble with exit codes from the commands I run. I'm using code similar to that in this answer, but it's a little more complicated. Basically, from our dev boxes we have to go through a jump server, and from there to a series of production machines. Once there we have to switch to a system user (sudo su - systemuser) and then we can run commands.

The problem is that as I understand it I have 3 subshells - the ssh session, the nested ssh command and then the su subshell. I can't get Paramiko to give me back the exit code of the commands in the inner subshell - I guess the exit code it will eventually return will be that of the ssh command. I suspect this problem is not actually specific to Paramiko - does the SSH protocol even support this kind of usage?

I'm currently always executing:

(my command); echo "Process terminated with exit code $?"

and then parsing this out on the client, but it's pretty ugly - is there a nicer way?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

渔村楼浪 2024-10-30 16:30:26

我猜它最终返回的退出代码将是 ssh 命令的退出代码。我怀疑这个问题实际上并不是 Paramiko 特有的 - SSH 协议是否支持这种用法?

是的,也不是。

退出状态总是会返回,但它可能不是来自您想象的地方。一旦调用 invoke_shell(),您的远程进程就是一个 shell,可能是 bash。您收到的 exit_status 将来自该 shell,而不是它运行的任何进程。 Paramiko(或任何 ssh 实现)都可以返回命令的退出状态,因为在远程 shell 之外永远看不到退出状态。由您决定退出状态应该是什么,并使用 exit $EXIT_STATUS 退出 shell(通常 exit $? 就足够了)

如果您可以分解命令,或者将它们包装在脚本中,然后使用 exec_command() 方法,您将可以直接访问正确的退出状态。

或者,您可以在远程 shell 中使用 shell 命令 exec,shell 的进程将被 exec 调用的命令替换,并返回其退出状态。

所有这三个方法都会按预期设置 channel.exit_status 属性。

I guess the exit code it will eventually return will be that of the ssh command. I suspect this problem is not actually specific to Paramiko - does the SSH protocol even support this kind of usage?

Yes, and no.

The exit status is always returned, but it may not be from where you think. Once you call invoke_shell(), your remote process is a shell, probably bash. The exit_status you receive will be the one from that shell, not any of the processes it ran. Paramiko (nor any ssh implementation) can ever return the exit status of your commands, because the exit statuses are never seen outside of that remote shell. It's up to you to determine what your exit status should be, and exit the shell with exit $EXIT_STATUS (often exit $? is enough)

If you can break up your commands, or wrap them in a script, then use the exec_command() method, you will have access to the correct exit status directly.

Alternatively, you can use shell command exec in the remote shell, and the shell's process will be replaced by the command called by exec, and its exit status will be returned.

All three of these methods will set the channel.exit_status attribute as expected.

巾帼英雄 2024-10-30 16:30:26

我遇到一个问题,“ssh”的手册页说它返回其运行的进程的退出代码,但我似乎无法让它返回非零错误代码。来自 ssh 手册页:

 The session terminates when the command or shell on the remote machine
 exits and all X11 and TCP/IP connections have been closed.  The exit sta‐
 tus of the remote program is returned as the exit status of ssh.

这似乎不是真的。

但我会尝试这样的事情,看看你的系统上会发生什么。

% ssh localhost bash -c "exit 3" ; echo $?
0

当我在本地运行类似的命令时,bash 返回退出代码。

% bash -c 'exit 3' ; echo $?
3

然而,在 ssh 出现命令之前,双引号将被删除。
因此,让我们尝试更多引用。

% ssh localhost bash -c "'exit 3'" ; echo $?
3

宾果游戏。 “exit 3”变成了“exit”,后面跟着一个被忽略的词
在 bash 命令行上。所以 bash 正在运行命令“exit”。

对我来说不幸的是,我认为整个答案都是题外话
来自最初的问题并且没有包含足够的优点
这本身就是一个问题。所以感谢大家帮助我
通过次要问题回答(与原始问题无关)。

I'm having a problem where the man page for 'ssh' says that it returns the exit code of the process it runs, but I can't seem to get it to return a non-zero error code. From the ssh man page:

 The session terminates when the command or shell on the remote machine
 exits and all X11 and TCP/IP connections have been closed.  The exit sta‐
 tus of the remote program is returned as the exit status of ssh.

That doesn't seem to be true.

But I would try something like this and see what happens on your system.

% ssh localhost bash -c "exit 3" ; echo $?
0

When I run a similar command locally, bash returns an exit code.

% bash -c 'exit 3' ; echo $?
3

The double quotes will be removed before ssh seems the commands however.
So let's try more quotes.

% ssh localhost bash -c "'exit 3'" ; echo $?
3

Bingo. The "exit 3" was turning into "exit" followed by an ignored word
on the bash command line. So bash was running the command "exit".

Unfortunately for me, I think this whole answer is a digression
from the original questions and doesn't contain enough merit as
a question in its own right. So thanks everyone for helping me
answer by secondary question (not related to the original question).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文