O ile rozumiem, jeśli wpisuję następujące ...
python -i
... interpreter Pythona będzie teraz czytał ze standardowego wejścia, zachowując się (oczywiście) w następujący sposób:
>>> print "Hello"
Hello
Spodziewałbym się, że zrobi to samo, jeśli to zrobię:
echo 'print "Hello"' > /proc/$(pidof python)/fd/0
Ale to jest wynik (wypełnienie rzeczywistej pustej linii):
>>> print "Hello"
<empyline>
To mi wygląda, po prostu wziąłem print "Hello"\n
i napisałem stdout
, ale nie zinterpretowałem. Dlaczego to nie działa i co musiałbym zrobić, aby to działało?
proc
file-descriptors
Sheppy
źródło
źródło
Odpowiedzi:
Przesyłanie danych wejściowych do powłok / tłumaczy w ten sposób jest bardzo podatne na problemy i bardzo trudno jest uzyskać niezawodne działanie.
Właściwym sposobem jest użycie gniazd, dlatego zostały one wynalezione, możesz to zrobić w wierszu poleceń, używając
ncat
nc
lub wsocat
celu powiązania procesu Pythona z prostym gniazdem. Lub napisz prostą aplikację pythonową, która łączy się z portem i nasłuchuje poleceń interpretowanych na gnieździe.gniazda mogą być lokalne i nie mogą być narażone na żaden interfejs WWW.
Problem polega na tym, że jeśli zaczynasz
python
z wiersza poleceń, zwykle jest on dołączony do powłoki, która jest podłączona do terminala, w rzeczywistości możemy zobaczyćwięc kiedy piszesz do
stdin
Pythona, w rzeczywistości piszesz napty
terminalu psuedo, który jest urządzeniem jądra, a nie prostym plikiem. Używaioctl
nieread
iwrite
, więc zobaczysz wynik na ekranie, ale nie zostanie wysłany do odrodzonego procesu (python
)Jednym ze sposobów replikacji tego, co próbujesz, jest za pomocą
fifo
lubnamed pipe
.Możesz także użyć
screen
tylko do wprowadzania danychźródło
sleep 300 > python_i.pipe &
), Druga strona się nie zamknie ipython
będzie nadal akceptować polecenia w rurce. EOF nie jest wysyłany jako takiecho
.|
rur, prawda?echo something > fifo
spowodowałoby to uzyskanie EOF, który zatrzymałby wiele aplikacji. Tosleep infinity > fifo
obejście nie przeszło mi przez środek, dziękuję!python -i <> fifo
co również zapobiegnie EOFDostęp nie ma dostępu do deskryptora pliku 0 PID procesu , uzyskuje dostęp do pliku, który PID otworzył na deskryptorze pliku 0. Jest to subtelne rozróżnienie, ale ma znaczenie. Deskryptor pliku to połączenie procesu z plikiem. Zapis do deskryptora pliku zapisuje do pliku niezależnie od tego, jak plik został otwarty.
/proc/PID/fd/0
Jeśli jest to zwykły plik, zapis do niego modyfikuje plik. Dane niekoniecznie będą dalej czytane przez proces: zależy to od pozycji dołączonej do deskryptora pliku, którego proces używa do odczytu pliku. Po otwarciu procesu otrzymuje ten sam plik co drugi proces, ale pozycje plików są niezależne.
/proc/PID/fd/0
/proc/PID/fd/0
Jeśli jest potokiem, wówczas zapis do niego dołącza dane do bufora potoku. W takim przypadku proces odczytujący z potoku odczyta dane.
/proc/PID/fd/0
Jeśli jest to terminal, wówczas zapis do niego wyprowadza dane na terminal. Plik terminala jest dwukierunkowy: zapis do niego wyprowadza dane, tzn. Terminal wyświetla tekst; odczyt z terminala wprowadza dane, tj. terminal przesyła dane użytkownika.
/proc/PID/fd/0
Python zarówno odczytuje, jak i pisze do terminala. Kiedy biegniesz
echo 'print "Hello"' > /proc/$(pidof python)/fd/0
, piszeszprint "Hello"
do terminala. Terminal wyświetla sięprint "Hello"
zgodnie z instrukcją. Proces python nic nie widzi, wciąż czeka na dane wejściowe.Jeśli chcesz wprowadzić dane wejściowe do procesu Python, musisz uzyskać terminal, który to zrobi. Zobacz odpowiedź crasic, aby dowiedzieć się, jak to zrobić.
źródło
Opierając się na tym, co powiedział Gilles , jeśli chcemy napisać do standardowego wejścia procesu podłączonego do terminala, faktycznie musimy wysłać informacje do terminala. Ponieważ jednak terminal służy zarówno jako forma wejścia, jak i wyjścia, podczas pisania do niego terminal nie ma możliwości dowiedzenia się, że chcesz pisać do uruchomionego procesu, a nie „ekranu”.
Linux ma jednak nie posiksowy sposób symulowania danych wprowadzanych przez użytkownika za pomocą żądania ioctl o nazwie
TIOCSTI
(Terminal I / O Control - Simulate Terminal Input), który pozwala nam wysyłać znaki do terminala tak, jakby zostały wpisane przez użytkownika.Jestem tylko pozornie świadomy tego, jak to działa, ale na podstawie tej odpowiedzi powinno być możliwe zrobienie tego za pomocą czegoś podobnego do
Niektóre zasoby zewnętrzne:
http://man7.org/linux/man-pages/man2/ioctl.2.html
http://man7.org/linux/man-pages/man2/ioctl_tty.2.html
źródło