2016-04-27 124 views
0

我正在從定製shell創建一個shell命令來執行從一個終端到另一個終端的ssh。 爲了做到ssh,我使用了linux的內置ssh命令。這是我的代碼,用於登錄ssh。 但是,我看到I/O緩衝區不同步。如何在管道linux中同步輸入和輸出?

這是我在終端上看到的。 SSH到另一個終端後。我在終端做了以下事情。

PRT# ssh 192.168.10.42 
PRT# Could not create directory '/root/.ssh'. 
[email protected]'s password: 
# screen -r 
-sh: cen-: not found 
# hello 
-sh: el: not found 
# 

我不是這裏的原因。這是代碼。

int sshLogin(chr *destIp) 
{ 
    char cmd[CMD_LEN]; 
    char readbuff[CMD_LEN]; 
    pid_t pid; 
    int ret = 0; 
    int fd[2]; 
    int result; 
    memset(cmd,'\0',sizeof(cmd)); 
    int status = 0; 

    /** --tt required to force pseudowire allocation because we are behind screen app **/ 
    sprintf(cmd,"/usr/bin/ssh -tt %s",destIp); 

    /** create a pipe this will be shared on fork() **/ 
    pipe(fd); 

    if((pid = fork()) == -1) 
    { 
     perror("fork:"); 
     return -1; 
    } 
    if(pid == 0) 
    { 
     /** Child Process of Main APP --Make this parent process for the command**/ 

     if((pid = fork()) == -1) 
     { 
      perror("fork:"); 
      return -1; 
     } 

     if(pid == 0) 
     { 
      /** basically Main APP grand child - this is where we running the command **/ 
      ret = execlp("ssh", "ssh", "-tt", destIp, NULL); 
      printf("done execlp\r\n"); 
     } 
     else 
     { 
      /** child of Main APP -- keep this blocked until the Main APP grand child is done with the job **/ 
      while((read(fd[0], readbuff, sizeof(readbuff)))) 
      { 
       printf("%s",readbuff); 
      } 

      waitpid(0,&status,0); 
      LOG_STRING("SSH CONNC CLOSED"); 
      exit(0); 
     } 
    } 
    else 
    { 
     /** Parent process APP MAIN-- **/ 
     /** no need to wait let APP MAIN run -- **/ 
    } 

    return 0; 
} 

基於Patrick的想法。

POST 2# - 看起來它在我們關閉父進程中的stdin時起作用。然而,它變得非常糟糕,我覺得我輸入鍵盤太慢了。系統變得太遲鈍了。另外,我從這個終端有一個網絡服務器。我發現我無法再訪問網絡。 所以,解決方案是圍繞標準輸入,但我不確定。

int sshLogin(chr *destIp) 
    { 
     char cmd[CMD_LEN]; 
     char readbuff[CMD_LEN]; 
     pid_t pid; 
     int ret = 0; 
     int fd[2]; 
     int result; 
     memset(cmd,'\0',sizeof(cmd)); 
     int status = 0; 

     /** --tt required to force pseudowire allocation because we are behind screen app **/ 
     sprintf(cmd,"/usr/bin/ssh -tt %s",destIp); 

     /** create a pipe this will be shared on fork() **/ 
     pipe(fd); 

     if((pid = fork()) == -1) 
     { 
      perror("fork:"); 
      return -1; 
     } 
     if(pid == 0) 
     { 
      /** Child Process of Main APP --Make this parent process for the command**/ 

      if((pid = fork()) == -1) 
      { 
       perror("fork:"); 
       return -1; 
      } 

      if(pid == 0) 
      { 
       /** basically Main APP grand child - this is where we running the command **/ 
       ret = execlp("ssh", "ssh", "-tt", destIp, NULL); 
       printf("done execlp\r\n"); 
      } 
      else 
      { 
       /** child of Main APP -- keep this blocked until the Main APP grand child is done with the job **/ 
       while((read(fd[0], readbuff, sizeof(readbuff)))) 
       { 
        printf("%s",readbuff); 
       } 

       waitpid(0,&status,0); 
       LOG_STRING("SSH CONNC CLOSED"); 
       exit(0); 
      } 
     } 
     else 
     { 
      /** Parent process APP MAIN-- **/ 
      /** no need to wait let APP MAIN run -- **/ 
      close(stdin); 
     } 

     return 0; 
    } 

基本上,我已經添加 - 關閉(stdin);

回答

1

您有2個不同的進程試圖從STDIN讀取。這導致進程1得到字符1,進程2得到字符2,進程1得到字符3,進程2得到字符4等等,來回交替。

你2個流程是:

  1. execlp("ssh", "ssh", "-tt", destIp, NULL);
  2. while((read(fd[0], readbuff, sizeof(readbuff))))

基本上你需要溝read(fd[0],...)

+0

我看到這個閱讀從來沒有被調用過,實際上,我現在已經評論了這個部分。 –

+0

噢,你也從程序中返回而沒有等待分支進程退出,所以你的父shell試圖從STDIN和分叉的'ssh'中讀取數據。 – Patrick

+0

現在已經重寫了這個問題。它似乎只適用於STDIN。 –

0

我最初的想法是,它可能是緩衝輸出:stdout被緩衝,所以除非你打印換行符,否則在打印一定數量的字符之前不會打印任何內容。這是因爲I/O操作很昂貴。你可以在這個here找到更多的細節。結果是由於您的程序正在等待打印而出現延遲。

我的建議:在你main函數,調用你sshLogin功能之前,請嘗試禁用緩存與這行代碼:

setbuf(stdout, NULL); 

您也可以撥打fflush(stdout);定期做同樣的事情,但上述方法效率更高。嘗試一下,看看是否能解決你的問題。

+0

沒有幫助。我看到了同樣的問題。 –