My script has two loops:
ssh
-processes are launched, one for each remote machine;returncode
I see, that they all run in sequence -- confirmed by printed output of the date
-commands on each -- whereas I expected them to run in parallel... What am I doing wrong?
pipes = {}
myhostname = os.uname()[1].lower()
for node in Nodes:
if node.lower() == myhostname:
cmd = '/bin/bash'
else:
cmd = ('ssh -q '
'-o PasswordAuthentication=no '
'-o StrictHostKeyChecking=no '
'%s /bin/bash') % node
pipe = subprocess.Popen(cmd.split(' '),
stdin = subprocess.PIPE, stdout = subprocess.PIPE,
stderr = subprocess.PIPE, close_fds = True,
encoding = locale.getlocale()[1])
pipe.stdin.write("""
date
sleep 1
date
exit""")
pipes[node] = pipe
logging.info('%d processes spawn, collecting outputs', len(pipes))
errCount = 0
for (node, pipe) in pipes.items():
out, err = pipe.communicate()
if err:
logging.warn('%s stderr: %s', node, err.strip())
if out:
logging.info('%s stdout: %s', node, out.strip())
if pipe.returncode != 0:
errCount += 1
logging.error('Got exit code %d from %s, increasing '
'error-count to %d', pipe.returncode, node, errCount)
The commands you’re writing to each process are waiting in your process’s output buffers until you call communicate
on each, flushing and closing each one’s input. You do that in sequence, so the date
commands run in sequence, even though the ssh
processes are all running the entire time in parallel. With this little data, you can add pipe.stdin.flush()
immediately after the write
to get the desired effect. (See Allan Wind’s answer for the general case for more (bytes of) commands.)