2016-04-27 104 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

没有帮助。我看到了同样的问题。 –