使用paramiko向具有交互元素的打开shell发送命令



我试图在Oracle ZFS数组上执行远程脚本。他们设计CLI的方式是,你可以通过SSH向它发送一个javascript"脚本"。这个脚本应该在第一行有"script"这个词,它将调用一个子shell,在执行

之前在它自己的行上等待一段时间。

的例子:

script
run('shares');
var projects = list();
dump(projects);
.

如果你像这样使用

$ ssh array < above_script

输出一个JSON可读格式的项目列表。

我想让这个工作与paramiko ssh在一个python脚本,但到目前为止,我没有太多的运气。在成功连接并获得SSHClient实例后,我正在尝试:

try:
    get_projects = """run('shares');
                    var projects = list();
                    dump(projects);"""
    w, r, e = ssh.exec_command('script')
    for line in get_projects.split('n'):
        w.write(line)
    w.write('.')
    pp.pprint(e.readlines())
    pp.pprint(r.readlines())
except paramiko.SSHException, e:
    logger.exception("Couldn't execute script on array %s: %s" % (array.name, e))

问题是它永远不会返回,它只是呆在那里。我甚至不能按ctrl-c停止它,我必须按ctrl-z结束它。

如果我删除读取stderr和stdout的尝试,它返回但没有捕获任何内容,因此似乎从套接字读取有问题:

INFO:paramiko.transport:Authentication (publickey) successful!
INFO:root:Not none
DEBUG:paramiko.transport:[chan 1] Max packet in: 34816 bytes
DEBUG:paramiko.transport:[chan 1] Max packet out: 32768 bytes
INFO:paramiko.transport:Secsh channel 1 opened.
DEBUG:paramiko.transport:[chan 1] Sesch channel 1 request ok
DEBUG:paramiko.transport:EOF in transport thread

请赐教。


小更新(这看起来很难看):使用ssh.invoke_shell()调用通道允许我发送脚本,然后运行shell.recv(1024)返回下面混乱的输出:

INFO:paramiko.transport:Authentication (publickey) successful!
>>> shell = ssh.invoke_shell()
DEBUG:paramiko.transport:[chan 1] Max packet in: 34816 bytes
DEBUG:paramiko.transport:[chan 1] Max packet out: 32768 bytes
INFO:paramiko.transport:Secsh channel 1 opened.
DEBUG:paramiko.transport:[chan 1] Sesch channel 1 request ok
DEBUG:paramiko.transport:[chan 1] Sesch channel 1 request ok
>>> get_projects = """script
...                             run('shares');
...                             var projects = list();
...                             dump(projects);
...                             .
...                             """
>>> get_projects
"scriptn                            run('shares');n                            var projects = list();n                            dump(projects);n                            .n                            "
>>> shell.send(get_projects)
203
>>> shell.recv(1024)
'Last login: Fri Mar  1 02:26:58 2013 from 10.91.134.163rrnrx1b[1mciczfsa:>x1b[mx0f x1b[mx0fscriptnrr("." to run)> x1b[mx0f                            run('shares');nrr("." to run)> x1b[mx0f                            var projects = list();nrr("." to run)> x1b[mx0f                            dump(projects);nrr("." to run)> x1b[mx0f                            .nr['Project1', 'Project_PoolA_2', 'RBR_PROJECT', 'SAS_501', 'TestProject', 'default', 'reptest', 'testproj1', 'testproj2']rnrx1b[1mciczfsa:>x1b[mx0f x1b[mx0f                            '

没有太多的帮助,因为它显然不是结构化的。理想情况下,我想将脚本发送到shell,并接收结构化响应,以便我可以将其解析为JSON。

原海报:

修复是,我需要发送一个换行与每个"新行"(有趣的是):

try:
    get_projects = """run('shares');
                    var projects = list();
                    dump(projects);
                    ."""
    w, r, e = ssh.exec_command('script')
    for line in get_projects.split('n'):
        w.write(line.lstrip().rstrip())
        w.write('n')
    pp.pprint(r.readline())

except paramiko.SSHException, e:
    logger.exception("Couldn't execute script on array %s: %s" % (array.name, e))

最新更新