Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/webpack/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
ruby:以原始模式向PTY发送击键_Ruby_Pty - Fatal编程技术网

ruby:以原始模式向PTY发送击键

ruby:以原始模式向PTY发送击键,ruby,pty,Ruby,Pty,我正在尝试向ruby newt模块添加一些更自动化的测试。我的代码似乎有效,但仍然需要在终端手动点击ENTER,才能完成 例如,在下面的代码中,\t将切换到下一个按钮,\r将按下该按钮,两个命令都成功执行,但仍需要在终端手动按下ENTER键,否则程序将无限期挂起 如果行wr.write“\t\r”被注释掉,则程序将超时并在10秒后成功退出。我试过wr.flush,但是没有用。我还尝试在命令中包含\n 在write命令中是否应该包含任何其他内容,以确保子程序成功接收到它 需要“newt” 需要“p

我正在尝试向
ruby newt
模块添加一些更自动化的测试。我的代码似乎有效,但仍然需要在终端手动点击
ENTER
,才能完成

例如,在下面的代码中,
\t
将切换到下一个按钮,
\r
将按下该按钮,两个命令都成功执行,但仍需要在终端手动按下
ENTER
键,否则程序将无限期挂起

如果行
wr.write“\t\r”
被注释掉,则程序将超时并在10秒后成功退出。我试过
wr.flush
,但是没有用。我还尝试在命令中包含
\n

write
命令中是否应该包含任何其他内容,以确保子程序成功接收到它

需要“newt”
需要“pty”
def newt_运行
开始
纽特:Screen.new
纽特:屏幕。居中的窗口(20,15,‘按钮’)
b1=Newt::Button.new(1,1,‘Button1’)
b2=Newt::Button.new(1,6,‘Button2’)
b=Newt::Button.new(1,11,“退出”)
f=Newt::Form.new
f、 设置定时器(10000)
f、 添加(b1、b2、b)
rv=f.run
确保
纽特:屏幕。完成
结束
结束
主,从=PTY.open
rd,wr=IO管道
如果fork.nil?然后
大师,闭嘴
关闭
$stdin.重新开放(rd)
$stdout.重新打开(从属)
$stderr.重新打开(从属)
纽特伦
其他的
关闭
道口
wr.write“\t\r”
等等
结束

问题是newt C-library在默认情况下会打开
/dev/tty
进行输入。它不使用标准输入法。这就是为什么你发送的东西似乎都不起作用。它不是在读你的管道,而是在读
/dev/tty

下面是更详细的问题:

  • Ruby newt在C-lib中调用
    newinit()
  • newinit()
    调用
    SLang\u init\u tty
  • 默认情况下,
    俚语init\tty
    总是将输入附加到
    /dev/tty
  • 如果使用
    SLang\u init\u tty
    ,您会发现变量
    SLang\u TT\u Read\u FD
    确定是否使用了
    /dev/tty

    解决方案1

    在从Ruby调用
    newinit()
    之前,需要将
    SLang\u TT\u Read\u FD
    设置为
    stdin

    解决方案2:

    使用
    setsid
    ioctl(TIOCSCTTY)
    在分叉过程中重新分配控制终端(请参阅)

    工作示例:

    TIOCSCTTY = 0x540E
    master, slave = PTY.open
    
    if fork.nil? then
      # Child process
      # Make group leader. Required for aquiring controlling TTY.
      Process.setsid
    
      master.close               # Close master side    
      STDIN.reopen(slave)        # Reassign STDIN
      STDIN.ioctl(TIOCSCTTY, 0)  # Reassign controlling TTY (important part)
    
      # Ensure master is ready
      slave.gets
    
      # Now we can run the UI
      newt_run
    else
      # Parent process
      slave.close
    
      # Sync up with slave
      master.puts 'hello'
    
      # Allow for UI setup
      sleep 1
    
      master.write "\e[B" # Arrow down
      master.write "\e[B" # Arrow down
      master.write "\t"   # Tab
      master.write "\r"   # Enter
    
      Process.wait 
    end
    

    注意:在
    def
    中,您只需
    确保
    ,无需明确的
    开始
    。谢谢,我相信解决方案2适合我的情况。