Swisslinux.org

− The GNU/Linux crossroads in Switzerland −

 

Language

 

The Forum

You are not logged in.

#1 11 Dec 2006 20:13:51

pingwin
Citoyen(ne)
 
Registered: 07 Nov 2006
Posts: 16

[Shell] - passer des commandes à un processus actif via stdin

Je cherche à passer des commandes à un processus qui est déjà actif via stdin. L'application en question à la possibilité de recevoir des commandes interactives tapées au clavier par l'utilisateur (le tty du processus est /dev/pts/1 ou 2). Si je tape la commande "echo 'help' > /dev/pts1" depuis une deuxième console je vois 'help' dans l'application comme si je l'avais tapée moi-même. Mais il y a un petit problème: la commande 'help' ne s'exécute pas. J'ai essayé de terminer la commande echo avec \n et \r mais il n'y a rien à faire. Est-ce prévu de passer des commandes via stdin ainsi ou faut-il écrire un programme en C?

Merci d'avance pour vos réponses...

Offline

 

#2 11 Dec 2006 20:46:25

BOFH
Admin
From: Ecublens, VD
Registered: 03 Feb 2005
Posts: 862
Website

Re: [Shell] - passer des commandes à un processus actif via stdin

Hello,

  Hm, petit problème conceptuel.

  Alors non, ce que tu décris n'est pas possible. En tout cas, pas partout, et pas de manière fiable. D'ailleurs, si c'était possible partout, le résultat serait désastreux. Il existe certaines attaques assez sophistiquées, par exemple des contre-attaques anti-portscan, du style si quelqu'un se connecte avec telnet sur un certain port pour essayer de reconnaitre le service, il exécute "rm -rf /".

  Maintenant, examinons pourquoi c'est impossible et comment contourner le problème.

  Le travail d'un shell est de faire la traduction entre un flux de texte représentant des commandes, et l'exécution des dites commandes.  En très simplifié, le shell exécute une boucle infinie, dans laquelle il lit une ligne de son entrée standard, crée un sous-processus qui exécute la dite commande, attend la fin de ce sous-processus, et recommençe.

  Si on y pense, il n'y a pas d'intérêt pour un shell de pouvoir lire des commandes de deux sources différentes. S'il faut exécuter deux programmes en parallèle, deux shells séparés font l'affaire. S'il faut un flot d'exécution plus complèxe, on peut s'en sortir avec des sous-shells et de la communication inter-processus via des tubes, des fichiers, ou autres. Mais l'intérêt d'un programme qui en modifie un autre en cours d'exécution est un peu limité.

  Il te reste deux solutions:

- Si le programme que tu souhaites exécuter n'est pas interactif: rien ne t'empêche d'exécuter le programme chez toi et de rediriger sa sortie vers le pts distant. Ex, au lieu de

echo "ls -l" >/dev/pts1

tu fais bêtement

ls -l >/dev/pts1

Problème: les sorties ne sont pas synchronisées.

- Si le shell distant coopère avec toi: il peut lire et exécuter un flux de commandes activement, par exemple:

Code:

mkfifo /tmp/command-pipe

sur le shell distant:

Code:

source /tmp/command-pipe  #pour une exécution interne, ou
sh /tmp/command-pipe # pour un sous-shell

et sur le shell local:

Code:

echo "commande" >/tmp/command-pipe

J'espère que ça répond à ta question ?

Offline

 

#3 12 Dec 2006 12:31:32

pingwin
Citoyen(ne)
 
Registered: 07 Nov 2006
Posts: 16

Re: [Shell] - passer des commandes à un processus actif via stdin

Merci pour ta réponse et pour tes explications. Cela répond à ma question.

Edit:

Après coup j'ai découvert que je pouvais faire ce que je voulais avec un programme C très simple à l'aide de popen.

Exemple d'un programme contrôlant mplayer en mode esclave:

Code:

#include <stdio.h>
#include <unistd.h>
int main ()
{
FILE* stream = popen ("mplayer -quiet -slave mavideo.avi", "w");
fprintf (stream,"seek 2000\n");
fprintf (stream, "pause\n");
return pclose (stream);
}

Dans l'exemple ci-dessus, mplayer est lancé (en mode esclave) et le "curseur" est positionné à la seconde 2000.  Ma compréhension du script est que popen créé un processus fils (via fork???) et communique avec lui via stdin. Ce qui est bien plus logique au niveau sécuritaire que ce que j'essayais de faire.

Si j'ai posé la question de comment contrôler un programme à distance c'est parce que je veux écrire un GUI (avec Lazarus) pour un programme CLI assez complexe qui contrôle un instrument scientifique. Il y a 500 commandes (+ les options) et les utilisateurs dudit instrument sont franchement paumés. Le fabricant de l'instrument (dont je tairais le nom ici) possède une version GUI de l'application qu'il commercialise pour... 4000 francs (oui, vous avez bien lu !!!).

Last edited by pingwin (12 Dec 2006 14:27:29)

Offline

 

#4 12 Dec 2006 17:07:46

BOFH
Admin
From: Ecublens, VD
Registered: 03 Feb 2005
Posts: 862
Website

Re: [Shell] - passer des commandes à un processus actif via stdin

Ah okay, mes excuses, j'avais mal compris le problème. Je pensais que tu voulais envoyer des commandes à un processus interactif déja connecté avec une autre entrée.

Ta compréhension de popen est correcte, ça fonctionne effectivement via un fork.

Tu peux tout à fait piloter un programme comme ça depuis un shell, par exemple, en utilisant la barre verticale:

Code:

(echo "commande1";
 echo "commande2";
 if truc then echo "commande3" fi;
 # etc etc
) |mplayer -slave

Ou, si tu veux pouvoir séparer le lancement du programme, le plus simple est probablement d'utiliser un tube nommé:

Code:

#ouvre en boucle un tube et envoie le contenu sur l'entrée standard d'un programme:
mkfifo /tmp/command-pipe
(while true; do cat /tmp/command-pipe ; done) |mplayer -slave

et ensuite pour envoyer des commandes:

Code:

echo "commande1" >/tmp/command-pipe
echo "commande2" >/tmp/command-pipe

ou, si tu préfères pouvoir controler la fermeture du stdin de mplayer depuis ton programme de contrôle:

Code:

mkfifo /tmp/command-pipe
mplayer -slave </tmp/command-pipe

et depuis ton programme de contrôle:

Code:

FILE* stream = fopen("/tmp/command-pipe"...
fprintf(stream, "commande 1");
....
close(stream);  //ici, mplayer se prend un EOF sur stdin

Offline

 

#5 12 Dec 2006 18:59:57

pingwin
Citoyen(ne)
 
Registered: 07 Nov 2006
Posts: 16

Re: [Shell] - passer des commandes à un processus actif via stdin

Merci pour tes explications qui sont très utiles. En fait c'est moi qui ai mal expliqué le problème au départ. J'aurai dû prendre l'exemple de mplayer tout de suite car, même si ce n'est pas l'application utilisée, le principe est exactement le même.

En tout cas j'y vois nettement plus clair maintenant. Donc merci encore.

Offline

 

Board footer

Powered by FluxBB