web-dev-qa-db-fra.com

commande linux exécutée par popen sur du code C

J'ai le code ci-dessous sur lequel je réfère le fil ici pour utiliser la fonction popen

int main(int argc,char *argv[]){    
    FILE* file = popen("ntpdate", "r");
    char buffer[100];
    fscanf(file, "%100s", buffer);
    pclose(file);
    printf("buffer is :%s\n", buffer);
    return 0;
}

Il génère:

21 Apr 03:03:03 ntpdate[4393]: no server can be used, exiting
buffer is:

pourquoi printf ne produit rien? Si j'utilise ls comme commande, alors printf sort la sortie ls. qu'est-ce que je fais mal ntpdate en cours d'exécution?

Si j'exécute le code ci-dessous (en se référant à la page Web )

#define COMMAND_LEN 8
#define DATA_SIZE 512

int main(int argc,char *argv[]){


    FILE *pf;
       char command[COMMAND_LEN];
       char data[DATA_SIZE];

       // Execute a process listing
       sprintf(command, "ntpdate");

       // Setup our pipe for reading and execute our command.
       pf = popen(command,"r");

       if(!pf){
         fprintf(stderr, "Could not open pipe for output.\n");
         return;
       }

       // Grab data from process execution
       fgets(data, DATA_SIZE , pf);

       // Print grabbed data to the screen.
       fprintf(stdout, "-%s-\n",data);

       if (pclose(pf) != 0)
           fprintf(stderr," Error: Failed to close command stream \n");

       return 0;
}

Je reçois

21 Apr 03:15:45 ntpdate[5334]: no servers can be used, exiting
-�2}�����"|�4#|�-
 Error: Failed to close command stream 

quels sont les torts sur les codes ci-dessus?

8
sven

Puisque la sortie va à stderr vous devez rediriger stderr comme ceci:

FILE* file = popen("ntpdate 2>&1", "r");

cela redirigera stderr vers stdout et vous verrez donc la sortie des deux. Le deuxième problème fscanf s'arrêtera au premier espace afin que vous puissiez le remplacer par fgets:

fgets(buffer, 100, file);
17
Shafik Yaghmour

Comme Shafik Yaghmour correctement diagnostiqué, la sortie que vous voyez à partir de ntpdate est écrite (correctement) dans son erreur standard, qui est la même que l'erreur standard de votre programme.

Pour obtenir les messages d'erreur envoyés dans le tuyau, utilisez:

FILE *file = popen("ntpdate 2>&1", "r");

Cela envoie la sortie d'erreur standard de ntpdate à la sortie standard de la commande, qui est le canal à partir duquel vous lisez.

Bien sûr, il semble que l'utilisation de ntpdate ne fonctionnera pas tant que vous n'aurez pas configuré quelque chose.

2
Jonathan Leffler
FILE *popen(const char *command, const char *type);
0
nitai