Python 使用paramiko向具有交互元素的打开shell发送命令
我正在尝试在Oracle ZFS阵列上执行远程脚本。他们设计CLI的方式是,您可以通过SSH向其发送javascript“脚本”。这个脚本应该在第一行中有“script”一词,它将调用一个子shell,在执行之前在它自己的行上等待一段时间 例如:Python 使用paramiko向具有交互元素的打开shell发送命令,python,ssh,paramiko,Python,Ssh,Paramiko,我正在尝试在Oracle ZFS阵列上执行远程脚本。他们设计CLI的方式是,您可以通过SSH向其发送javascript“脚本”。这个脚本应该在第一行中有“script”一词,它将调用一个子shell,在执行之前在它自己的行上等待一段时间 例如: script run('shares'); var projects = list(); dump(projects); . 如果你这样使用它: $ ssh array < above_script 问题是它永远不会回来,它只是坐在那里。我甚
script
run('shares');
var projects = list();
dump(projects);
.
如果你这样使用它:
$ ssh array < above_script
问题是它永远不会回来,它只是坐在那里。我甚至不能按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
"script\n 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.163\r\r\n\r\x1b[1mciczfsa:>\x1b[m\x0f \x1b[m\x0fscript\n\r\r("." to run)> \x1b[m\x0f run(\'shares\');\n\r\r("." to run)> \x1b[m\x0f var projects = list();\n\r\r("." to run)> \x1b[m\x0f dump(projects);\n\r\r("." to run)> \x1b[m\x0f .\n\r[\'Project1\', \'Project_PoolA_2\', \'RBR_PROJECT\', \'SAS_501\', \'TestProject\', \'default\', \'reptest\', \'testproj1\', \'testproj2\']\r\n\r\x1b[1mciczfsa:>\x1b[m\x0f \x1b[m\x0f '
这里没有太多帮助,因为它显然不是结构化的。理想情况下,我希望将脚本发送到shell,并接收对脚本的结构化响应,我可以将其解析为JSON。来自原始海报: 解决办法是,我需要在每一条“新行”中发送一条新行(很有趣):
我不知道这是否重要,但以防万一:假设
ssh.exec_命令('script')
返回的w
的行为类似于标准文件,w.write
不会在字符串的末尾写换行符。也许可以尝试在用w.write
编写的字符串中添加一个换行符。沃伦,这正是我需要的。。。有关(愚蠢的)修复,请参见上文。您可以将line.lstrip().rstrip()
替换为line.strip()
。另外,您是否尝试过在一次调用中将整个字符串get_projects
发送到w.write
,而不是单独编写每一行?
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
"script\n 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.163\r\r\n\r\x1b[1mciczfsa:>\x1b[m\x0f \x1b[m\x0fscript\n\r\r("." to run)> \x1b[m\x0f run(\'shares\');\n\r\r("." to run)> \x1b[m\x0f var projects = list();\n\r\r("." to run)> \x1b[m\x0f dump(projects);\n\r\r("." to run)> \x1b[m\x0f .\n\r[\'Project1\', \'Project_PoolA_2\', \'RBR_PROJECT\', \'SAS_501\', \'TestProject\', \'default\', \'reptest\', \'testproj1\', \'testproj2\']\r\n\r\x1b[1mciczfsa:>\x1b[m\x0f \x1b[m\x0f '
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))