stillhq.com : Mikal, a geek from Canberra living in Silicon Valley http://www.stillhq.com The life, times, travel and software of Michael Still en Copyright (c) Michael Still 2000 - 2006 blosxom simplerss20 v20050208hh 180 http://blogs.law.harvard.edu/tech/rss Calculating a SSH host key with paramiko /python/paramiko Mon, 05 Jan 2009 16:28:00 PST I needed to compare a host key from something other than a known_hosts file with what paramiko reports as part of the SSH connection today. If you must know, the host keys for these machines are retrieved a XMLRPC API... It turned out to be a lot easier than I thought. Here's how I produced the host key entry as it appears in that API (as well as in the known_hosts file): <br/><br/> <ul><pre> #!/usr/bin/python # A host key calculation example for Paramiko. # Args: # 1: hostname import base64 import os import paramiko import socket import sys # Socket connection to remote host sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.connect((sys.argv[1], 22)) # Build a SSH transport t = paramiko.Transport(sock) t.start_client() key = t.get_remote_server_key() print '%s %s' %(key.get_name(), base64.encodestring(key.__str__()).replace('\n', '')) t.close() sock.close() </pre></ul> <br/><br/> Note that I could also have constructed a paramiko key object based on the output of the XMLRPC API and then compared those two objects, but I prefer the human readable strings. <br/><br/><i>Tags for this post: python(<a href="http://www.stillhq.com/python"><img src="http://www.stillhq.com/tagicon.cgi?post=/python/paramiko/000005&tag=python&format=.png" border="0" alt="S"></a>) paramiko(<a href="http://www.stillhq.com/paramiko"><img src="http://www.stillhq.com/tagicon.cgi?post=/python/paramiko/000005&tag=paramiko&format=.png" border="0" alt="S"></a>) </i> <a href="http://www.stillhq.com/python/paramiko/000005.commentform.html">Comment</a> http://www.stillhq.com/python/paramiko/000005.html http://www.stillhq.com/python/paramiko/000005.html paramiko exec_command timeout /python/paramiko Sun, 05 Oct 2008 12:20:00 PST I have a paramiko program which sshs to a large number of machines, and sometimes it hits a machine where Channel.exec_command() doesn't return. I know this is a problem with the remote machine, because the same thing happens when I try to ssh to the machine from the command line. However, I don't have any way of determining which machines are broken beforehand. <br/><br/> Paramiko doesn't support a timeout for exec_command(), so I am looking for a generic way of running a function call with a timeout. I can see sample code which does this using threads, but that's pretty ugly. I can't use SIGALARM because I am not running on the main thread. <br/><br/> Can anyone think of a better way of doing this? <br/><br/><i>Tags for this post: python(<a href="http://www.stillhq.com/python"><img src="http://www.stillhq.com/tagicon.cgi?post=/python/paramiko/000004&tag=python&format=.png" border="0" alt="S"></a>) paramiko(<a href="http://www.stillhq.com/paramiko"><img src="http://www.stillhq.com/tagicon.cgi?post=/python/paramiko/000004&tag=paramiko&format=.png" border="0" alt="S"></a>) </i> <a href="http://www.stillhq.com/python/paramiko/000004.commentform.html">Comment</a> http://www.stillhq.com/python/paramiko/000004.html http://www.stillhq.com/python/paramiko/000004.html Weird paramiko problem /python/paramiko Tue, 16 Sep 2008 11:41:00 PST I had a strange paramiko problem the other day. Sometimes executing a command through a channel (via the exec_command() call) would result in an exit code being returned, but no stdout or stderr. This was for a command I was absolutely sure always returns output, and it wasn't consistent -- I'd run batches of commands and about 10% of them would fail, but not always on the same machine and not always at the same time. I spent ages looking at my code, and the code for the command running at the other end of the channel. <br/><br/> Then it occurred to me that this seemed a lot like a race condition. I started looking at the code for the paramiko Channel class, and ended up deciding that the answer was to check that the eof_received member variable was true before trying to close the channel. <br/><br/> It turns out this just works. I've my code running commands for a couple of days now and have had zero more instances of the "no output, but did exit" error. So, there you go. Its a shame that member variable doesn't have accessors and isn't documented though. I guess that makes my code a little more fragile than I would be happy with. <br/><br/><i>Tags for this post: python(<a href="http://www.stillhq.com/python"><img src="http://www.stillhq.com/tagicon.cgi?post=/python/paramiko/000003&tag=python&format=.png" border="0" alt="S"></a>) paramiko(<a href="http://www.stillhq.com/paramiko"><img src="http://www.stillhq.com/tagicon.cgi?post=/python/paramiko/000003&tag=paramiko&format=.png" border="0" alt="S"></a>) </i> <a href="http://www.stillhq.com/python/paramiko/000003.commentform.html">Comment</a> http://www.stillhq.com/python/paramiko/000003.html http://www.stillhq.com/python/paramiko/000003.html Executing a command with paramiko /python/paramiko Wed, 03 Sep 2008 15:11:00 PST I wanted to provide a simple example of how to execute a command with paramiko as well. This is quite similar to the scp example, but is nicer than executing a command in a shell because there isn't any requirement to do parsing to determine when the command has finished executing. <br/><br/> <ul><pre> #!/usr/bin/python # A simple command example for Paramiko. # Args: # 1: hostname # 2: username # 3: command to run import getpass import os import paramiko import socket import sys # Socket connection to remote host sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.connect((sys.argv[1], 22)) # Build a SSH transport t = paramiko.Transport(sock) t.start_client() t.auth_password(sys.argv[2], getpass.getpass('Password: ')) # Start a cmd channel cmd_channel = t.open_session() cmd_channel.exec_command(sys.argv[3]) data = cmd_channel.recv(1024) while data: sys.stdout.write(data) data = cmd_channel.recv(1024) # Cleanup cmd_channel.close() t.close() sock.close() </pre></ul> <br/><br/><i>Tags for this post: python(<a href="http://www.stillhq.com/python"><img src="http://www.stillhq.com/tagicon.cgi?post=/python/paramiko/000002&tag=python&format=.png" border="0" alt="S"></a>) paramiko(<a href="http://www.stillhq.com/paramiko"><img src="http://www.stillhq.com/tagicon.cgi?post=/python/paramiko/000002&tag=paramiko&format=.png" border="0" alt="S"></a>) </i> <a href="http://www.stillhq.com/python/paramiko/000002.commentform.html">Comment</a> http://www.stillhq.com/python/paramiko/000002.html http://www.stillhq.com/python/paramiko/000002.html Implementing SCP with paramiko /python/paramiko Wed, 03 Sep 2008 13:28:00 PST Regular readers will note that I've been <a href="http://www.stillhq.com/blather/20080902.html">interested in how scp works</a> and <a href="http://www.stillhq.com/blather/20080903.html">paramiko</a> for the last couple of days. There are <a href="http://www.lag.net/pipermail/paramiko/2007-May/000489.html">previous examples of how to do scp with paramiko out there</a>, but the code isn't all on one page, you have to read through the mail thread and work it out from there. I figured I might save someone some time (possibly me!) and note a complete example of scp with paramiko... <br/><br/> <ul><pre> #!/usr/bin/python # A simple scp example for Paramiko. # Args: # 1: hostname # 2: username # 3: local filename # 4: remote filename import getpass import os import paramiko import socket import sys # Socket connection to remote host sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.connect((sys.argv[1], 22)) # Build a SSH transport t = paramiko.Transport(sock) t.start_client() t.auth_password(sys.argv[2], getpass.getpass('Password: ')) # Start a scp channel scp_channel = t.open_session() f = file(sys.argv[3], 'rb') scp_channel.exec_command('scp -v -t %s\n' % '/'.join(sys.argv[4].split('/')[:-1])) scp_channel.send('C%s %d %s\n' %(oct(os.stat(sys.argv[3]).st_mode)[-4:], os.stat(sys.argv[3])[6], sys.argv[4].split('/')[-1])) scp_channel.sendall(f.read()) # Cleanup f.close() scp_channel.close() t.close() sock.close() </pre></ul> <br/><br/><i>Tags for this post: python(<a href="http://www.stillhq.com/python"><img src="http://www.stillhq.com/tagicon.cgi?post=/python/paramiko/000001&tag=python&format=.png" border="0" alt="S"></a>) paramiko(<a href="http://www.stillhq.com/paramiko"><img src="http://www.stillhq.com/tagicon.cgi?post=/python/paramiko/000001&tag=paramiko&format=.png" border="0" alt="S"></a>) </i> <a href="http://www.stillhq.com/python/paramiko/000001.commentform.html">Comment</a> http://www.stillhq.com/python/paramiko/000001.html http://www.stillhq.com/python/paramiko/000001.html