替换然后通过 ssh 打开 stdin/stdout

Posted

技术标签:

【中文标题】替换然后通过 ssh 打开 stdin/stdout【英文标题】:Replacing and then opening stdin/stdout over ssh 【发布时间】:2011-08-05 19:02:47 【问题描述】:

我正在开发一个使用管道与标准输入和标准输出的子进程通信的系统。子进程使用 api 库来促进这种通信,我需要为该库编写单元测试。我能弄清楚如何正确测试这些函数的唯一方法是用管道替换标准输入/标准输出,以便在调用函数时测试可以伪装成父系统。

/* replace stdin and stdout with pipes */
void setup(void) 
  pipe(in_sub);
  pipe(out_sub);

  dup2(out_sub[1], fileno(stdout));
  dup2( in_sub[0],  fileno(stdin));
  read_from = fdopen(out_sub[0], "rb");
  write_to  = fdopen( in_sub[1], "wb");

  stdout_t = fopen("/dev/tty", "wb");
  stdin_t  = fopen("/dev/tty", "rb");


/* reopen stdin and stdout for future test suites */
void teardown(void) 
  fclose(read_from);
  fclose(write_to);

  stdout = stdout_t;
  stdin  = stdin_t;

  close(in_sub[0]);
  close(in_sub[1]);
  close(out_sub[0]);
  close(out_sub[1]);

我尝试在临时文件中保存 stdin 和 stdout 并在它们上使用 fdopen() (应该可以工作,因为它们是 FILE*),但这不会导致将内容正确写入管道。当直接从主机的 shell 运行时,此代码确实可以完美运行。通过 ssh 运行时会出现此问题。单元测试完美执行,但是当我在这个测试套件之后向标准输出写入任何内容时,我收到了一个损坏的管道错误。

我能做些什么来避免使用 dup2 以便 stdin 和 stdout 永远不会关闭,或者我如何重新打开 stdin 和 stdout 以便它们在 shell 和 ssh 中正确工作?

【问题讨论】:

【参考方案1】:

标准输入、标准输出只是 FILE* 指向一个结构(对象),该结构(对象)在内部将其 fd 设置为 0(和 1)。因此,当您执行 dup2 时,文件 0 和 1 不再起作用。您需要做的是在执行 dup2之前从头开始创建一个新的文件对象,所以这可能就是您需要的所有修改;

void setup(void) 
  int dupin, dupout;

  dupin = dup(0);  // Create an extra fd to stdin
  dupout = dup(1);  // create an extra fd to stdout

  pipe(in_sub);
  pipe(out_sub);

  dup2(out_sub[1], fileno(stdout));
  dup2( in_sub[0],  fileno(stdin));
  read_from = fdopen(out_sub[0], "rb");
  write_to  = fdopen( in_sub[1], "wb");

  stdout_t = fdopen(dupout, "wb");
  stdin_t  = fdopen(dupin, "rb");

【讨论】:

以上是关于替换然后通过 ssh 打开 stdin/stdout的主要内容,如果未能解决你的问题,请参考以下文章

gitLab生成SSH私钥后上传代码及获取代码

git —— 远程仓库(创建)

通过SSH去连接 github 和bitbucket

生成电脑的ssh key值

通过 SSH 隧道访问 SQL Server

解决ubuntu安装ssh服务无法打开解析包问题