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
下面是更详细的问题:
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适合我的情况。