2009-09-02 1 views
1

Теперь я сократил это до минимального тестового примера. До сих пор я мог определить, что это проблема, связанная с псевдотерминалами, которые возникают с трубой ssh. Добавление '-t -t' к вызову ssh улучшило ситуацию, в этом теперь требуется второй вызов функции fgets(), чтобы вызвать проблему. Я подозреваю, что вывод stderr команды ssh каким-то образом работает в этой проблеме, пока я перенаправил stderr на stdout в код ssh для выполнения. Я действительно задаюсь вопросом, является ли ошибка «tcgetattr: Invalid argument» частью проблемы, но я не уверен, как избавиться от этого. Кажется, это происходит от -t -t присутствия. Я считаю, что -t -t движется в правильном направлении, но мне нужно как-то настроить псевдотерминал для stderr, и, возможно, тест будет работать правильно?Вызов fgets() на popen() из 'ssh' сбрасывает начало stdin вызывающего процесса (проблема ptty)

Файл 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 

Источник 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"); 
     } 
     } 
    } 
    } 
} 

Это показывает, что он работает попутный путь:

> 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 !!!!!!! 

Это показывает, что работает ошибочный путь :

> 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 ???? 

ответ

1

Хорошо, у меня наконец-то это работает. Секрет в том, чтобы поставить/DEV/нуль в качестве входных данных для моей команды SSH, как следует из теста выше:

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

Однако, в то время как код работает правильно, я получаю противное сообщение, которое, по-видимому, я могу проигнорировать для мои цели (хотя я бы хотел, чтобы сообщение исчезло):

tcgetattr: Inappropriate ioctl for device 
+0

Попробуйте выполнить вывод TO/dev/null вместо него. – GaZ

Смежные вопросы