Насколько я понимаю, если я наберу следующее ...
python -i
... интерпретатор python теперь будет читать из stdin, ведя себя (очевидно) так:
>>> print "Hello"
Hello
Я ожидал бы, что это сделает то же самое, если я сделаю это:
echo 'print "Hello"' > /proc/$(pidof python)/fd/0
Но это вывод (фактически пустая строка):
>>> print "Hello"
<empyline>
Это мне кажется, он просто взял print "Hello"\n
и написал это stdout
, но не интерпретировал это. Почему это не работает и что я должен сделать, чтобы это работало?
proc
file-descriptors
Sheppy
источник
источник
Ответы:
Отправка входных данных оболочкам / интерпретаторам таким образом очень проблематична и очень трудно заставить работать любым надежным способом.
Правильным способом является использование сокетов, поэтому они были изобретены, вы можете сделать это в командной строке, используя
ncat
nc
илиsocat
связать процесс Python с простым сокетом. Или напишите простое приложение на python, которое связывается с портом и прослушивает команды для интерпретации в сокете.сокеты могут быть локальными и не подвергаться никакому веб-интерфейсу.
Проблема в том, что если вы запускаете
python
из командной строки, он обычно подключен к вашей оболочке, которая подключена к терминалу, на самом деле мы можем видетьпоэтому, когда вы пишете в
stdin
python, вы фактически пишете вpty
psuedo-терминал, который является устройством ядра, а не простым файлом. Онioctl
не используетread
иwrite
, поэтому вы увидите вывод на вашем экране, но он не будет отправлен в порожденный процесс (python
)Один из способов повторить то, что вы пытаетесь, - с помощью
fifo
илиnamed pipe
.Вы также можете использовать
screen
только для вводаисточник
sleep 300 > python_i.pipe &
), другая сторона не закроется иpython
будет продолжать принимать команды вниз по трубе. EOF как таковое не отправленоecho
.|
труб, однако, верно?echo something > fifo
заставил его получить EOF, который остановит многие приложения.sleep infinity > fifo
Обходной путь не пересек мою середину , хотя, спасибо!python -i <> fifo
что также предотвратит EOFДоступ не обращается к дескриптору 0 файла PID процесса , он обращается к файлу, который PID открыл в дескрипторе файла 0. Это тонкое различие, но оно имеет значение. Файловый дескриптор - это соединение, которое процесс имеет с файлом. Запись в файловый дескриптор пишет в файл независимо от того, как файл был открыт.
/proc/PID/fd/0
Если это обычный файл, запись в него изменяет файл. Данные не обязательно должны читаться следующим процессом: они зависят от позиции, прикрепленной к дескриптору файла, который процесс использует для чтения файла. Когда процесс открывается , он получает тот же файл, что и другой процесс, но позиции файла независимы.
/proc/PID/fd/0
/proc/PID/fd/0
Если это канал, то запись в него добавляет данные в буфер канала. В этом случае процесс, который читает из канала, будет читать данные.
/proc/PID/fd/0
Если это терминал, то запись в него выводит данные на терминал. Файл терминала является двунаправленным: запись в него выводит данные, т.е. терминал отображает текст; считывание с терминала вводит данные, т.е. терминал передает пользовательский ввод.
/proc/PID/fd/0
Python читает и пишет в терминал. Когда вы бежите
echo 'print "Hello"' > /proc/$(pidof python)/fd/0
, вы пишетеprint "Hello"
в терминал. Терминал отображаетсяprint "Hello"
в соответствии с инструкциями. Процесс Python ничего не видит, он все еще ждет ввода.Если вы хотите передать входные данные процессу Python, вам нужно получить терминал для этого. См . Ответ Крэстика, чтобы узнать, как это сделать.
источник
Основываясь на том, что сказал Жиль , если мы хотим записать в stdin процесса, который подключен к терминалу, нам фактически нужно отправить информацию в терминал. Тем не менее, поскольку терминал служит как формой ввода, так и вывода, при записи в него терминал не может знать, что вы хотите записать в выполняющийся в нем процесс, а не на «экран».
Однако в Linux есть не-posix способ имитации пользовательского ввода через запрос ioctl, называемый
TIOCSTI
(Terminal I / O Control - Simulate Terminal Input), который позволяет нам отправлять символы на терминал, как если бы они были набраны пользователем.Я только поверхностно осознаю, как это работает, но исходя из этого ответа, должно быть возможно сделать это с чем-то вроде
Некоторые внешние ресурсы:
http://man7.org/linux/man-pages/man2/ioctl.2.html
http://man7.org/linux/man-pages/man2/ioctl_tty.2.html
источник