I need to run an interactive Bash instance in a separated process in Python with it’s own dedicated TTY (I can’t use pexpect). I used this code snippet I commonly see used in similar programs:
master, slave = pty.openpty() p = subprocess.Popen(["/bin/bash", "-i"], stdin=slave, stdout=slave, stderr=slave) os.close(slave) x = os.read(master, 1026) print x subprocess.Popen.kill(p) os.close(master)
But when I run it I get the following output:
$ ./pty_try.py bash: cannot set terminal process group (10790): Inappropriate ioctl for device bash: no job control in this shell
Strace of the run shows some errors:
... readlink("/usr/bin/python2.7", 0x7ffc8db02510, 4096) = -1 EINVAL (Invalid argument) ... ioctl(3, SNDCTL_TMR_TIMEBASE or SNDRV_TIMER_IOCTL_NEXT_DEVICE or TCGETS, 0x7ffc8db03590) = -1 ENOTTY (Inappropriate ioctl for device) ... readlink("./pty_try.py", 0x7ffc8db00610, 4096) = -1 EINVAL (Invalid argument)
The code snippet seems pretty straightforward, is Bash not getting something it needs? what could be the problem here?
Advertisement
Answer
This is the solution that worked for me at the end (as suggested by qarma) :
libc = ctypes.CDLL('libc.so.6') master, slave = pty.openpty() p = subprocess.Popen(["/bin/bash", "-i"], preexec_fn=libc.setsid, stdin=slave, stdout=slave, stderr=slave) os.close(slave) ... do stuff here ... x = os.read(master, 1026) print x