Pour autant que je comprends si je tape ce qui suit ...
python -i
... l'interpréteur python va maintenant lire à partir de stdin, se comportant (évidemment) comme ceci:
>>> print "Hello"
Hello
Je m'attendrais à ce qu'il fasse la même chose si je fais ceci:
echo 'print "Hello"' > /proc/$(pidof python)/fd/0
Mais c'est la sortie (étant une ligne vide réelle):
>>> print "Hello"
<empyline>
Cela ressemble à moi, il a juste pris le print "Hello"\n
et l'a écrit stdout
, mais ne l'a pas interprété. Pourquoi cela ne fonctionne-t-il pas et que dois-je faire pour que cela fonctionne?
proc
file-descriptors
Sheppy
la source
la source
Réponses:
L'envoi d' entrées aux shells / interprètes de cette manière est très sujet aux problèmes et très difficile à obtenir de manière fiable.
La bonne façon est d'utiliser des sockets, c'est pourquoi ils ont été inventés, vous pouvez le faire en ligne de commande en utilisant
ncat
nc
ousocat
pour lier un processus python à une simple socket. Ou écrivez une application python simple qui se lie au port et écoute les commandes à interpréter sur un socket.les sockets peuvent être locales et ne sont exposées à aucune interface Web.
Le problème est que si vous démarrez à
python
partir de la ligne de commande, il est généralement attaché à votre shell qui est attaché à un terminal, en fait, nous pouvons voirdonc quand vous écrivez sur
stdin
python, vous écrivez en fait sur lepty
psuedo-terminal, qui est un périphérique noyau, pas un simple fichier. Il n'utiliseioctl
pasread
etwrite
, vous verrez donc la sortie sur votre écran, mais il ne sera pas envoyé au processus généré (python
)Une façon de reproduire ce que vous essayez est d'utiliser un
fifo
ounamed pipe
.Vous pouvez également utiliser
screen
pour la saisie uniquementla source
sleep 300 > python_i.pipe &
), l'autre côté ne se fermera pas etpython
continuera à accepter les commandes sur le tuyau. Il n'y a pas d'EOF en tant que tel envoyé parecho
.|
tuyaux, cependant, n'est-ce pas?echo something > fifo
je lui ferais obtenir un EOF qui arrêterait de nombreuses applications. Lasleep infinity > fifo
solution de contournement n'a cependant pas traversé mon milieu, merci!python -i <> fifo
ce qui empêchera également l'EOFL'accès n'accède pas au descripteur de fichier 0 du processus PID , il accède au fichier que le PID a ouvert sur le descripteur de fichier 0. C'est une distinction subtile, mais c'est important. Un descripteur de fichier est une connexion qu'un processus a avec un fichier. L'écriture dans un descripteur de fichier écrit dans le fichier, quelle que soit la façon dont le fichier a été ouvert.
/proc/PID/fd/0
Si c'est un fichier normal, y écrire modifie le fichier. Les données ne sont pas nécessairement ce que le processus lira ensuite: cela dépend de la position attachée au descripteur de fichier que le processus utilise pour lire le fichier. Lorsqu'un processus s'ouvre , il obtient le même fichier que l'autre processus, mais les positions des fichiers sont indépendantes.
/proc/PID/fd/0
/proc/PID/fd/0
Si est un canal, alors y écrire ajoute les données au tampon du canal. Dans ce cas, le processus qui lit le tube lira les données.
/proc/PID/fd/0
Si est un terminal, alors y écrire génère les données sur un terminal. Un fichier de terminal est bidirectionnel: écrire dessus génère les données, c'est-à-dire que le terminal affiche le texte; la lecture à partir d'un terminal entre les données, c'est-à-dire que le terminal transmet l'entrée utilisateur.
/proc/PID/fd/0
Python lit et écrit à la fois sur le terminal. Lorsque vous exécutez
echo 'print "Hello"' > /proc/$(pidof python)/fd/0
, vous écrivezprint "Hello"
sur le terminal. Le terminal s'afficheprint "Hello"
comme indiqué. Le processus python ne voit rien, il attend toujours une entrée.Si vous souhaitez alimenter le processus Python, vous devez demander au terminal de le faire. Voir la réponse de crasic pour savoir comment procéder.
la source
À partir de ce que Gilles a dit , si nous voulons écrire sur la stdin d'un processus attaché à un terminal, nous devons en fait envoyer les informations au terminal. Cependant, comme un terminal sert à la fois d'entrée et de sortie, lors de l'écriture, le terminal n'a aucun moyen de savoir que vous voulez écrire dans un processus qui s'y déroule plutôt que sur "l'écran".
Linux a cependant une manière non posix de simuler l'entrée utilisateur via une requête ioctl appelée
TIOCSTI
(Contrôle d'E / S du terminal - Simuler l'entrée du terminal) qui nous permet d'envoyer des caractères à un terminal comme s'ils avaient été saisis par un utilisateur.Je ne suis que superficiellement conscient de la façon dont cela fonctionne, mais sur la base de cette réponse, il devrait être possible de le faire avec quelque chose comme
Quelques ressources externes:
http://man7.org/linux/man-pages/man2/ioctl.2.html
http://man7.org/linux/man-pages/man2/ioctl_tty.2.html
la source