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.
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.
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.