这个问题的初衷是寻找一种通过Python脚本启动交互式ssh
会话的方法。我之前尝试过subprocess.call()
,并在所有内容输出到终端之前都得到了Killed
响应。我只是认为这是subprocess
模块的问题/局限性,而不是其他地方的问题。当我在非资源受限的计算机上运行脚本时,情况并非如此,并且运行良好。
然后,问题变成了:如何在资源受限的情况下运行交互式ssh
会话?
向查尔斯·达菲(Charles Duffy)大喊大叫,他在尝试诊断所有这些方面都提供了巨大帮助。
以下是原始问题:
所以我有一个当前用bash编写的脚本。它解析一些控制台功能的输出,然后基于这些解析的输出打开ssh会话。
它目前可以正常工作,但是我想通过添加一些标志参数来扩展它的功能。我之前曾与argparse
合作,并且非常喜欢它。我尝试用bash做一些标志工作,而我们只说这还有很多不足之处。
是否可以让python在控制台 中进行处理,然后将用户置于该控制台中?
类似于使用subprocess
在当前查看的控制台上运行一系列命令吗?这与subprocess
的正常运行方式相反,在正常情况下,该命令运行命令,然后关闭中间控制台
所以这是我想要的功能的基本清单:
运行以下命令:
ssh -t $correctnode "cd /local_scratch/pbs.$jobid; bash -l"
此命令将SSH到$correctnode
,更改目录,然后在该节点中打开bash窗口。
我已经知道如何做第1部分和第2部分。这是我不知道的第三部分。任何帮助将不胜感激。
编辑:与this question不同,我不是只是尝试运行命令。我正在尝试显示由命令创建的外壳。具体来说,我想显示通过ssh
命令创建的bash shell。
答案 0 :(得分:1)
这绝不是真正的答案,只是我的评论的一个例证。
假设您有一个Python脚本 test.py :
import argparse
if __name__ == '__main__':
parser = argparse.ArgumentParser()
parser.add_argument('myarg', nargs="*")
args = parser.parse_args()
print("echo Hello world! My arguments are: " + " ".join(args.myarg))
因此,您可以围绕它创建一个bash包装器, test.sh
set -e
$(python test.py $*)
这就是你得到的:
$ bash test.sh
Hello world! My arguments are:
$ bash test.sh one two
Hello world! My arguments are: one two
这是怎么回事:
ssh blabla
$(...)
部分)的输出,并传递其所有参数($*
部分)set -e
标志而停止答案 1 :(得分:1)
OP在非常受资源限制(尤其是受过程限制)的Jumphost框上运行,在其中,ssh
的子过程开始的python
进程超出了相关限制(可能有多少个进程?)
使用exec*()
系列的系统调用会导致您的原始进程不再在内存中(不同于用于在保持父进程运行的同时启动子进程的fork()+exec*()
组合),因此不会不会计入帐户的限额。
import argparse
import os
try:
from shlex import quote
except ImportError:
from pipes import quote
parser = argparse.ArgumentParser()
parser.add_argument('node')
parser.add_argument('jobid')
args = parser.parse_args()
remote_cmd_str = 'cd /local_scratch/pbs.%s && exec bash -i' % (quote(args.jobid))
local_cmd = [
'/usr/bin/env', 'ssh', '-tt', node, remote_cmd_str
]
os.execv("/usr/bin/env", local_cmd)
如果我们使用Python生成shell命令,则只有在Python进程退出后,shell才能调用该命令,这样我们就不会受到外部强制的进程限制。
首先,一种更可靠的方法来生成可eval
的输出:
import argparse
try:
from shlex import quote
except ImportError:
from pipes import quote
parser = argparse.ArgumentParser()
parser.add_argument('node')
parser.add_argument('jobid')
args = parser.parse_args()
remoteCmd = ['cd', '/local_scratch/pbs.%s' % (args.jobid)]
remoteCmdStr = ' '.join(quote(x) for x in remoteCmd) + ' && bash -l'
cmd = ['ssh', '-t', args.correctnode, remoteCmdStr]
print(' '.join(pipes.quote(x) for x in cmd)
如果上面的名称为genSshCmd
,则要从shell运行此命令:
#!/bin/sh
eval "$(genSshCmd "$@")"
请注意,这里有两个单独的引用层:一层用于运行eval
的本地shell,第二层用于由SSH启动的远程shell。这很关键-您不希望$(rm -rf ~)
的Jobid实际调用rm
。