2009-09-02 6 views
1

J'ai maintenant réduit cela à un cas de test minimal. Jusqu'à présent, j'ai été en mesure de déterminer que c'est un problème lié aux pseudo-terminaux qui se produisent avec le tuyau de SSH. L'ajout de '-t -t' à l'appel de ssh a amélioré les choses, en ce sens que maintenant, il faut un second appel à fgets() pour provoquer le problème. Je suspecte que la sortie stderr de la commande ssh fonctionne d'une manière ou d'une autre dans le problème, pour l'instant j'ai redirigé stderr vers stdout dans le code ssh pour l'exécuter. Je me demande si l'erreur "tcgetattr: Invalid argument" fait partie du problème, mais je ne suis pas sûr de savoir comment m'en débarrasser. Il semble provenir du -t -t étant présent. Je crois que -t -t va dans la bonne direction, mais je dois configurer le pseudo terminal pour stderr d'une manière ou d'une autre et peut-être que le test fonctionnera correctement?L'appel de fgets() sur popen() de 'ssh' vide le début de stdin du processus appelant (problème de ptty)

Le Makefile:

test: 
    gcc -g -DBUILD_MACHINE='"$(shell hostname)"' -c -o test.o test.c 
    gcc -g -o test test.o 

.PHONY: clean 
clean: 
    rm -rf test.o test 

Le fichier source test.c:

#include <unistd.h> 
#include <string.h> 
#include <stdio.h> 

int 
main(int argc, char *argv[]) 
{ 
    const unsigned int bufSize = 32; 
    char buf1[bufSize]; 
    char buf2[bufSize]; 
    int ssh = argv[1][0] == 'y'; 
    const char *cmd = ssh ? "ssh -t -t " BUILD_MACHINE " \"ls\" 2>&1" : "ls"; 

    FILE *fPtr = popen(cmd, "r"); 

    if (fPtr == NULL) { 
    fprintf(stderr,"Unable to spawn command.\n"); 
     perror("popen(3)"); 
     exit(1); 
    } 
    printf("Command: %s\n", cmd); 
    if (feof(fPtr) == 0 && fgets(buf2, bufSize, fPtr) != NULL) { 
    printf("First result: %s\n", buf2); 
    if (feof(fPtr) == 0 && fgets(buf2, bufSize, fPtr) != NULL) { 
     printf("Second result: %s\n", buf2); 
     int nRead = read(fileno(stdin), buf1, bufSize); 

     if (nRead == 0) { 
     printf("???? popen() of ssh consumed the beginning of stdin ????\n"); 
     } else if (nRead > 0) { 
     if (strncmp("The quick brown fox jumped", buf1, 26) != 0) { 
      printf("??? Failed ???\n"); 
     } else { 
      printf("!!!!!!! Without ssh popen() did not consume stdin !!!!!!!\n"); 
     } 
     } 
    } 
    } 
} 

Cela montre fonctionner comme passage:

> echo "The quick brown fox jumped" | ./test n 
Command: ls 
First result: ARCH.linux_26_i86 

Second result: Makefile 

!!!!!!! Without ssh popen() did not consume stdin !!!!!!! 

Cela montre fonctionner comme défaut :

> echo "The quick brown fox jumped" | ./test y 
Command: ssh -t -t hostname "ls" 2>&1 
First result: tcgetattr: Invalid argument 

Second result: %backup%~    gmon.out 

???? popen() of ssh consumed the beginning of stdin ???? 

Répondre

1

D'accord, j'ai enfin ce travail. Le secret était de fournir/dev/null comme l'entrée à ma commande ssh comme suit à partir du cas de test ci-dessus:

 const char *cmd 
     = ssh ? "ssh -t -t " BUILD_MACHINE " \"ls\" 2>&1 < /dev/null" : "ls"; 

Cependant, alors que le code fonctionne correctement, je reçois un message méchant qui, apparemment, je ne peux ignorer pour mes fins (bien que je voudrais faire disparaître le message):

tcgetattr: Inappropriate ioctl for device 
+0

essayez d'acheminer la sortie TO/dev/null au lieu de FROM. – GaZ

Questions connexes