NicoKowe
NicoKowe

Reputation: 3417

python script: pexpect hangs on child.wait()?

I have a working script in Linux that creates ssh-keys. In macOS, it hangs on wait().

import os
import sys

import pexpect


passphrase = os.environ['HOST_CA_KEY_PASSPHRASE']

command = 'ssh-keygen'
child = pexpect.spawn(command, args=sys.argv[1:])
child.expect('Enter passphrase:')
child.sendline(passphrase)
child.wait()

Upvotes: 1

Views: 1538

Answers (1)

NicoKowe
NicoKowe

Reputation: 3417

Finally, I found the problem. It seems that the ssh-keygen binary is slightly different, and it outputs some things after.

because wait() is a blocking call.

This will not read any data from the child, so this will block forever if the child has unread output and has terminated. In other words, the child may have printed output then called exit(), but, the child is technically still alive until its output is read by the parent.

.wait() docs here

to solve this problem read_nonblocking reads at most size characters from the child application. If there are bytes available to read immediately, all those bytes will be read (up to the buffer size).

.read_nonblocking() docs here

working solution


import os
import sys

import pexpect


passphrase = os.environ['HOST_CA_KEY_PASSPHRASE']

command = 'ssh-keygen'
child = pexpect.spawn(command, args=sys.argv[1:])
child.expect('Enter passphrase:')
child.sendline(passphrase)

# Avoid Hang on macOS
# https://github.com/pytest-dev/pytest/issues/2022
while True:
    try:
        child.read_nonblocking()
    except Exception:
        break

if child.isalive():
    child.wait()

Upvotes: 2

Related Questions