我试图通过PTY模块pipe理到networking设备的SSH连接,代码类似于:
cmd_line = "ssh coltrane@love.supreme.com" begin PTY.spawn(cmd_line) do |r_f,w_f,pid| ... rescue PTY::ChildExited => cended ... end
整个I / O工作得很好,但我不知道如何获得subprocess的退出状态。
例如,如果连接中断或超时,生成的进程将终止一个错误代码,但是这个代码似乎没有被返回到$? 特殊variables。
用于监视/ proc / diskstats的Python库?
为什么CompletionKey在I / O完成端口中?
Shellredirect和文件I / O持续时间
使用asynchronousI / O和IOCP实现回显服务器的最佳方式是什么?
使用File I / O在Windows中遍历目录
我想将stdin解释为一个二进制文件。 为什么freopen在Windows上失败?
如何在Visual C ++中截断文件?
如何在Java中引用目录?
什么是Windows上最好的epoll / kqueue / select equvalient?
TLDR
使用1.9.2并等待PTY进程正确设置$?
PTY.spawn(command) do |r,w,pid| # ... Process.wait(pid) end
全文
在1.9.2上,您可以通过调用PTY pid上的等待来获取PTY的退出状态。 这几乎是所有的时间(AFAIK)。 我所知道的唯一例外情况是边缘情况,如立即退出或为命令发出空字符串(请参阅http://redmine.ruby-lang.org/issues/5253 )。
例如:
require 'pty' require 'test/unit' class PTYTest < Test::Unit::TestCase def setup system "true" assert_equal 0,$?.exitstatus end def pty(cmd,&block) PTY.spawn(cmd,&block) $?.exitstatus end def test_pty_with_wait_correctly_sets_exit_status_for_master_slave_io status = pty("printf 'abc'; exit 8") do |r,pid| while !r.eof? r.getc end Process.wait(pid) end assert_equal 8,status end def test_pty_with_wait_correctly_sets_exit_status_for_basic_commands status = pty("true") do |r,pid| Process.wait(pid) end assert_equal 0,status status = pty("false") do |r,pid| Process.wait(pid) end assert_equal 1,status end def test_pty_with_wait_sets_exit_status_1_for_immediate_exit status = pty("exit 8") do |r,status end def test_pty_with_kill status = pty("sleep 10") do |r,pid| Process.kill(9,pid) Process.wait(pid) end assert_equal nil,status end end
现在运行测试:
$ ruby -v ruby 1.9.2p290 (2011-07-09 revision 32553) [x86_64-darwin10.8.0] $ ruby example.rb Loaded suite example Started .... Finished in 1.093349 seconds. 4 tests,9 assertions,0 failures,0 errors,0 skips Test run options: --seed 31924
在1.8.7你需要做更多。 在较老的红宝石中,即使您等待PTY过程完成,PTY也会经常退出PTY :: ChildExited错误。 因此,如果您按照书面方式运行测试,则可以得到以下结果:
$ ruby -v ruby 1.8.7 (2010-08-16 patchlevel 302) [i686-darwin10.4.0] $ ruby example.rb Loaded suite example Started EE.E Finished in 1.170357 seconds. 1) Error: test_pty_with_kill(PTYTest): PTY::ChildExited: pty - exited: 35196 example.rb:11:in `test_pty_with_kill' example.rb:11:in `spawn' example.rb:11:in `pty' example.rb:45:in `test_pty_with_kill' 2) Error: test_pty_with_wait_correctly_sets_exit_status_for_basic_commands(PTYTest): PTY::ChildExited: pty - exited: 35198 example.rb:11:in `test_pty_with_wait_correctly_sets_exit_status_for_basic_commands' example.rb:11:in `spawn' example.rb:11:in `pty' example.rb:26:in `test_pty_with_wait_correctly_sets_exit_status_for_basic_commands' 3) Error: test_pty_with_wait_sets_exit_status_1_for_immediate_exit(PTYTest): PTY::ChildExited: pty - exited: 35202 example.rb:11:in `test_pty_with_wait_sets_exit_status_1_for_immediate_exit' example.rb:11:in `spawn' example.rb:11:in `pty' example.rb:38:in `test_pty_with_wait_sets_exit_status_1_for_immediate_exit' 4 tests,5 assertions,3 errors
通知几乎所有的测试都会弹出一个ChildExited错误,但是其中一个(顺便说一句代表最实际的PTY使用)会按预期成功。 当然,这种不稳定的行为是一个错误,正如已经表明的那样,它已经在1.9.2中修复了。
有一个部分的解决方法,但是。 你可以使用像这样的东西来具体处理ChildExited错误:
def pty(cmd,&block) begin PTY.spawn(cmd,&block) $?.exitstatus rescue PTY::ChildExited $!.status.exitstatus end end
插入,再次运行测试,并得到符合1.9.2的结果,与大警告$? 将不会正确设置(不像1.9.2)。 特别是如果你要添加这个测试:
def test_setting_of_process_status system "true" assert_equal 0,$?.exitstatus begin PTY.spawn("false") do |r,pid| Process.wait(pid) end rescue PTY::ChildExited end assert_equal 1,$?.exitstatus end
你在1.9.2上获得成功,在1.8.7上失败。 在1.8.7的情况下,PTY通过ChildExited错误完成 – Process.wait永远不会被调用,因此从不设置$ ?. 相反,$? 从“系统”真正的“”坚持,你得到0而不是1作为退出状态。
$的行为? 很难遵循,并有更多的警告,我不会进入(即有时PTY 将通过Process.wait完成)。
好的,下面是这个问题的一些可能的解决方案:
使用ruby 1.9.2 PTY.check()方法
将命令行包装在脚本中
不幸的是,我不能使用最新版本的红宝石,所以我用包装解决方案,回声$? 到包装脚本结尾的文件。 退出代码在产生的小孩退出时读取。
当然,如果有什么中断包装脚本本身的执行,那么我们永远不会得到结果文件…
但至少这个解决方法可以用于Ruby的1.8.7 / 1.9.1版本
摘要:在Linux中,父母应该等待()这个孩子知道他的孩子的退出状态。
C代码:
int状态;
等待(&状态)//在父代码部分
WEXITSTATUS(状态)//宏返回返回子项的退出码
对不起。我没有红宝石的经验,为您提供一些代码。 最好的祝愿 :)
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。