IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C Discussion :

Utiliser ligne de commande Linux dans un programme C


Sujet :

C

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éclairé Avatar de zodd
    Profil pro
    Inscrit en
    Septembre 2005
    Messages
    276
    Détails du profil
    Informations personnelles :
    Âge : 46
    Localisation : France

    Informations forums :
    Inscription : Septembre 2005
    Messages : 276
    Par défaut Utiliser ligne de commande Linux dans un programme C
    Bonjour,

    Je cherche une solution pour utiliser une ligne de commande Linux directement dans mon programme.

    J'ai trouvé facilement comment lancer une commande avec:
    system("ma commande linux");

    Par contre je cherche à voir comment récupérer le résultat de la commande.

    J'ai entendu parlé d'utilisation de pipes avec fork() ou encore de socket mais je ne m'en suis jamais servi.

    De la même façon je compte lancer un démon qui en temps normal affiche des données lorsque nécessaire dans la console. J'aimerai donc aussi pouvoir "surveiller" ce démon pour récupérer les données renvoyées par celui-ci dans mon programme.

    J'ai bien pensé à faire un script qui renvoie les sorties de ces fonctions/programmes dans un fichier de log que je consulterai à intervalle régulier mais je trouve cette solution "capilotractée" ..

  2. #2
    Expert confirmé
    Avatar de Kannagi
    Homme Profil pro
    cyber-paléontologue
    Inscrit en
    Mai 2010
    Messages
    3 226
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : cyber-paléontologue

    Informations forums :
    Inscription : Mai 2010
    Messages : 3 226
    Par défaut
    c'est popen que tu recherche ?
    http://www.lix.polytechnique.fr/~lib...ONS/popen.html

    Genre un exemple utilisation pour récupérer ls
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
        FILE *fichier;
        char chaine[100];
     
        fichier = popen("ls","r");
     
     
        while(fgets(chaine, 100,fichier) != NULL)
            printf("%s",chaine);
     
     
     
        pclose(fichier);

  3. #3
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Chercheur d'emploi
    Inscrit en
    Septembre 2007
    Messages
    7 477
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Chercheur d'emploi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 477
    Par défaut
    Citation Envoyé par zodd Voir le message
    Je cherche une solution pour utiliser une ligne de commande Linux directement dans mon programme.

    J'ai trouvé facilement comment lancer une commande avec:
    system("ma commande linux");
    C'est à cela qu'elle sert, effectivement.

    Par contre je cherche à voir comment récupérer le résultat de la commande.
    Si c'est simplement le code de retour qui t'intéresse, il est renvoyé directement par system() (ou « -1 » en cas d'erreur), ce qui rend cette fonction extrêmement simple d'utilisation. Par contre, si c'est la sortie standard du programme lancé qui t'intéresse, il va falloir procéder autrement.

    J'ai entendu parlé d'utilisation de pipes avec fork() ou encore de socket mais je ne m'en suis jamais servi.
    Regarde du côté de popen(). Le principe est le même : la fonction appelle un shell et lui passe la commande en argument, ce qui permet à celle-ci d'être relativement complexe si nécessaire. En retour, tu obtiens en revanche un descripteur de fichier. C'est à toi de préciser si tu veux que ce descripteur, et donc ton programme, soit relié à l'entrée standard ou à la sortie.

    De la même façon je compte lancer un démon qui en temps normal affiche des données lorsque nécessaire dans la console. J'aimerai donc aussi pouvoir "surveiller" ce démon pour récupérer les données renvoyées par celui-ci dans mon programme.

    J'ai bien pensé à faire un script qui renvoie les sorties de ces fonctions/programmes dans un fichier de log que je consulterai à intervalle régulier mais je trouve cette solution "capilotractée" ..
    Le mieux est un socket UNIX.

    Tu peux également choisir de t'appuyer sur DBus s'il est en place.

  4. #4
    Membre éclairé Avatar de zodd
    Profil pro
    Inscrit en
    Septembre 2005
    Messages
    276
    Détails du profil
    Informations personnelles :
    Âge : 46
    Localisation : France

    Informations forums :
    Inscription : Septembre 2005
    Messages : 276
    Par défaut
    Merci pour vos réponses.

    popen() pourrait visiblement faire le boulot mais ça revient un peu au même que faire du log dans un fichier non? En gros je suis en train de comprendre que ouvrir un pipe revient à créer un fichier temporaire intermédiaire?

    Concernant systeme(), ce n'est pas que le code retour mais carrément la réponse complète de la commande. Par exemple dans le cas d'un ls -la , je voudrai récupérer ce qui s'affiche dans le terminal lorsque je fais cette commande. Cette méthode n'est donc pas suffisante d'après ce que je comprends et c'est là que popen() serait plus adapté je suppose..

    Je n'ai jamais mis en oeuvre de socket UNIX (mise à part ce de mes cartes réseaux), ni Dbus.. je vais essayer de me documenter à ce sujet..

    Juste au cas où, j'aimerai essayer de trouver une solution qui puisse être "portable", dans la mesure du possible, sous windows car la commande/démon que je souhaite utiliser sous Linux existe aussi sous forme de service sous windows.

    Edit: concernant le descripteur de fichier en retour de popen(), tu dis qu'on peut le relié à l'entrée standard ou à la sortie. Je n'ai pas bien compris ce que tu veux dire par là? Dans mon cas il s'agirait de la sortie stdout..?

  5. #5
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Chercheur d'emploi
    Inscrit en
    Septembre 2007
    Messages
    7 477
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Chercheur d'emploi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 477
    Par défaut
    Citation Envoyé par zodd Voir le message
    popen() pourrait visiblement faire le boulot mais ça revient un peu au même que faire du log dans un fichier non? En gros je suis en train de comprendre que ouvrir un pipe revient à créer un fichier temporaire intermédiaire?
    Pas tout-à-fait : quand tu disposes d'un descripteur de fichiers, celui correspond en temps normal à… un fichier, on s'en serait douté, mais il s'agit surtout d'un flux de données. Lorsque tu crées un tube avec pipe(), le système te renvoie une paire de descripteurs de fichiers, l'un en écriture, l'autre en écriture. Et tout ce qui est envoyé dans le premier est automatiquement redirigé vers le second sans passer par le disque, avec une mémoire tampon de 4 Kio par défaut.

    Quand tu utilises popen(), cette fonction crée un tube, puis « forke » pour créer un processus fils qui hérite de sa paire de descripteur et remappe l'un d'eux sur l'entrée ou la sortie standard, de sorte que le processus à lancer ne s'apercevra pas que c'est en fait dans ce tube qu'il écrit. Du côté du processus père, la fonction te rend la main en te renvoyant l'autre descripteur.

    Juste au cas où, j'aimerai essayer de trouver une solution qui puisse être "portable", dans la mesure du possible, sous windows car la commande/démon que je souhaite utiliser sous Linux existe aussi sous forme de service sous windows.
    Dans ce cas-là, tu peux définir une interface commune mais les infrastructures proposées par les deux systèmes sont assez différentes.

    Edit: concernant le descripteur de fichier en retour de popen(), tu dis qu'on peut le relié à l'entrée standard ou à la sortie. Je n'ai pas bien compris ce que tu veux dire par là? Dans mon cas il s'agirait de la sortie stdout..?
    Chaque fois que tu lances un programme, son processus naît avec trois fichiers déjà ouverts, qui portent les numéros 0, 1 et 2 dans la liste des descripteurs Unix et qui sont nommés « stdin », « stdout » et « stderr » dans la norme C (ces derniers référencent tous une structure FILE *). Ils correspondent aux fichiers qui sont lus ou écrits lorsque tu utilises une fonction sans passer de descripteur explicite. Chaque fois que tu écris « printf ("Bonjour"); », par exemple, la chaîne est en fait envoyée vers stdout.

    Il se trouve que ces fichiers peuvent être fermés s'ils sont inutiles, comme des fichiers ordinaires, et que leur descripteur peut éventuellement être remplacé par un autre. En le remplaçant justement par le descripteur d'un tube que l'on a préalablement ouvert, on redirige les entrées et sorties standards vers là où on veut qu'elles aillent. Et popen() se charge de faire tout cela pour toi.

    Le programme de Kannagi fait exactement ce que tu cherches à faire : il exécute « ls » puis récupère le résultat ligne par ligne avant de les afficher lui-même.

  6. #6
    Membre éclairé Avatar de zodd
    Profil pro
    Inscrit en
    Septembre 2005
    Messages
    276
    Détails du profil
    Informations personnelles :
    Âge : 46
    Localisation : France

    Informations forums :
    Inscription : Septembre 2005
    Messages : 276
    Par défaut
    Merci pour ta réponse. ça devient plus clair. Je vais approfondir ce sujet qui me semble incontournable sous Linux car c'est bien pratique^^
    Et je vais partir du code de kannagi et de son lien pour mettre tout ça en pratique

  7. #7
    Membre éclairé Avatar de zodd
    Profil pro
    Inscrit en
    Septembre 2005
    Messages
    276
    Détails du profil
    Informations personnelles :
    Âge : 46
    Localisation : France

    Informations forums :
    Inscription : Septembre 2005
    Messages : 276
    Par défaut
    Alors je viens de tester popen(), c'est vraiment excellent !

    Par contre comment ça se passe si je ne sais pas quand est ce que le retour est sensé arriver? Par exemple j'ouvre un pipe avec popen(), je lance un démon, et à partir de là je suis susceptible de recevoir des données sur ce pipe durant toute la durée d'exécution du programme; En gros je ne peut pas rester dans le while, comment récupérer le flux ailleurs?

    Pour l'instant ma seule idée est de faire une commande spéciale pour faire écrire ma commande dans un fichier un peut comme ça:

    system("ls >>foo");

    Mais là ça oblige à nouveau à consulter régulièrement le contenu du fichier.

    En gros ma nouvelle question est en fait comment récupérer la sortie d'un démon..

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 12
    Dernier message: 03/12/2010, 16h08
  2. Utiliser des commandes linux dans un shell
    Par Info_76 dans le forum Shell et commandes GNU
    Réponses: 4
    Dernier message: 20/03/2008, 12h03
  3. [Système] Commande Linux dans Programme PHP
    Par makohsarah dans le forum Langage
    Réponses: 3
    Dernier message: 10/09/2007, 12h36
  4. utilisation des commandes shell dans un programme C
    Par rasgueados dans le forum Linux
    Réponses: 15
    Dernier message: 03/08/2006, 17h25
  5. Réponses: 2
    Dernier message: 24/06/2003, 20h31

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo