Взаимодействовать с ребенком ребенка - PullRequest
0 голосов
/ 28 февраля 2019


Мне нужно напрямую взаимодействовать с stdin и stdout процесса, который я порождаю с subprocess.Я могу сделать это с помощью:

proc = subprocess.Popen("/bin/bash", stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
proc.stdin.write(b"whoami\n")
print(proc.stdout.readline())

Однако, как только процесс разветвляется, я больше не могу взаимодействовать с ним.У меня есть эта тестовая программа:

// child.c
#include <unistd.h>
int main() {
    execve("/bin/bash", NULL, NULL);
}

, с которой я компилирую:

gcc -o child child.c

и когда я пытаюсь использовать приведенный выше код Python с child вместо /bin/bash в Popen вызов, я получаю broken pipe ошибку.

Что я пробовал:
Поскольку файловые дескрипторы, созданные python, по умолчанию не наследуются, я попытался изменить это:

inr, inw = os.pipe()
outr, outw = os.pipe()
os.set_inheritable(inr, True)
os.set_inheritable(inw, True)
os.set_inheritable(outr, True)
os.set_inheritable(outw, True)

proc = subprocess.Popen("./child", stdin=inr, stdout=outw, stderr=outw)
proc.stdin.write(b"whoami\n")
print(proc.stdout.readline())

os.close(inr)
os.close(inw)
os.close(outr)
os.close(outw)

Но я все еще получаю ту же ошибку.Я думаю, что это должно быть легкой задачей, и я, вероятно, что-то упустил.Любая помощь приветствуется.

[EDIT] До того, как я отредактировал свой пост, я использовал test вместо child в качестве имени моего тестового c исполняемого файла.Я узнал, что это действительно программа в моем PATH, расположенная по адресу /usr/bin/test.
. Изменение имени исполняемого файла на child успешно решило мою проблему.После нескольких часов проб и ошибок я знал, что ответ будет очень простым ...
Большое спасибо Barmar за то, что указал на это!

1 Ответ

0 голосов
/ 28 февраля 2019

Когда вы звоните test, вы звоните /bin/test, а не своей программе.

Либо переименуйте вашу программу на C, чтобы она не конфликтовала со стандартной командой, либо обращайтесь к ней с помощью пути, чтобыон не ищет $PATH.

proc = subprocess.Popen("./test", stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
...