如何实现一个stdin、stdout包装器?

5
我有一个交互式程序,可以运行stdin和stdout。我需要创建一个包装器,将X发送到其stdin,检查它是否打印了Y,然后将包装器的stdin和stdout重定向到程序的stdin和stdout,就像直接执行程序一样。
如何实现这个?X和Y可以硬编码。Bash?Python?
编辑:我不能两次运行程序。它必须是一个实例。以下是伪代码:
def wrap(cmd, in, expected_out):
  p = exec(cmd)
  p.writeToStdin(in)
  out = p.readBytes (expected_out.size())
  if (out != expected_out) return fail;
  # if the above 4 lines would be absent or (in == "" and out == "")
  # then this wrapper would be exactly like direct execution of cmd
  connectpipe (p.stdout, stdout)
  connectpipe (stdin, p.stdin)
  p.continueExecution() 

2
哦,哇,就在几个月前我也在寻找这样的问题。 (脚本化仅限于 Telnet 会话的 Cisco 设备...)想要一个脚本来登录(可能是擦除)路由器,然后将控制台交给我。向您点赞。 - Thanatos
4个回答

3

Expect 是用来自动运行其他程序的工具- 你只需要用简单文本编写如下内容:

启动此程序。当它打印出“用户名”时,发送我的用户名。当它发送“密码”时,发送我的密码。

它非常适合驱动其他程序。


执行一些命令后,它能否将控制权交给标准输入/输出? - Łukasz Lew

1

假设X和Y是文件,并且您可以多次调用程序:

#!/bin/bash

test "`program <X`" = "`cat Y`" && program

或者更冗长地说,返回失败:

#!/bin/bash

if [[ `program <X` != `cat Y` ]]; then
    echo -e "Assertion that input X produces Y failed, exiting."
    exit 1
fi

program

如果您只需要调用程序一次,Expect比在运行时重新分配标准文件I/O要简单得多。

这个解决方案是错误的,因为程序的第二个实例将没有第一个程序的状态。 - Łukasz Lew
@Łukasz,请你编辑一下你的问题,加上这个要求好吗? - system PAUSE

0

您可以覆盖sys模块的stdin和stdout

import sys
sys.stdin, sys.stdout = wrapper.stdin, wrapper.stdout

这些需要分别以读取和写入方式打开的文件对象。 原始的标准输入和输出位于

sys.stdin, sys.stdout = sys.__stdin__, sys.__stdout__

包装器可以用Python编写,但程序不能被修改。 - Łukasz Lew

0

我有点困惑你到底想要实现什么;据我所知,您希望:

  1. 启动包装程序并指定输入X和期望输出Y。
  2. 让包装程序启动目标程序并将输入X附加到其stdin,并验证其输出是否与Y匹配。
  3. 在输出经过验证后,使目标程序返回,并从包装程序的同一实例中重新运行它,这次使用包装程序的stdin和stdout。

如果是这种情况,您需要执行以下操作:

  1. 让包装程序打开目标程序的stdin和stdout管道。
  2. 进行分叉,并关闭所述管道的适当端口。
  3. 父进程验证输出,而子进程exec()并执行目标程序。
  4. 等待子进程终止,当其stdout关闭时。
  5. 让包装程序exec()进入目标程序。
  6. 现在目标程序将正常执行。

如果正确,我可以提供一个约30行的C程序或约10行的Python程序来实现此目的。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接