I'm trying to execute a remote script on an Oracle ZFS array. The way they've designed the CLI is that you can send it a javascript "script" via SSH. This script is supposed to have the word "script" in the first line which will invoke a sub-shell which waits for a period on it's own line before executing
Example:
script
run('shares');
var projects = list();
dump(projects);
.
which if you use it like this:
$ ssh array < above_script
outputs a nice list of the projects in a JSON readable format.
I'd like to get this to work with paramiko ssh in a python script but so far I'm not having much luck. After successfully connecting and getting an SSHClient instance I'm trying this:
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))
The problem is that it never returns, it just sits there. I can't even ctrl-c stop it, I have to ctrl-z and kill it.
If I remove the attempts to read stderr, and stdout it returns but nothing is captured, so it seems like there's an issue reading from the socket:
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
Any insights would be appreciated.
small update (this is going to look ugly): Invoking the Channel with ssh.invoke_shell() allowed me to send the script and then running shell.recv(1024) returned the messy output below:
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 '
Not a TON of help here because it's obviously not structured. Ideally I'd like to send the script to the shell, and receive the structured response to I can parse it as JSON.