本文介绍了如何获取PTY.spawn子退出代码?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述 我正在尝试通过PTY模块管理与网络设备的SSH连接,代码类似于:I'm trying to manage a SSH connection to a network device via the PTY module, with a code similar to this: cmd_line = "ssh [email protected]"begin PTY.spawn(cmd_line) do |r_f,w_f,pid| ...rescue PTY::ChildExited => cended ...end整个I / O运行良好,但是我不知道如何获得子进程的退出状态。The whole I/O works pretty well, however I don't know how to get the exit status of the child process.例如,如果连接中断或只是超时,则生成的进程将以错误代码终止,但似乎没有在 $?特殊变量中返回此代码。 For instance, if the connection is broken or simply times out, the spawned process will terminate with an error code, but this code does not seem to be returned in the $? special variable. 推荐答案 TLDR 使用1.9.2并等待PTY过程正确设置$?TLDRUse 1.9.2 and wait on the PTY process to correctly set $?PTY.spawn(command) do |r,w,pid| # ... Process.wait(pid)end 全文 在1.9.2上,您可以通过在PTY pid上调用wait来捕获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,w,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,w,pid| Process.wait(pid) end assert_equal 0, status status = pty("false") do |r,w,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,w,pid| Process.wait(pid) end assert_equal 1, status end def test_pty_with_kill status = pty("sleep 10") do |r,w,pid| Process.kill(9, pid) Process.wait(pid) end assert_equal nil, status endend现在运行测试:$ ruby -vruby 1.9.2p290 (2011-07-09 revision 32553) [x86_64-darwin10.8.0]$ ruby example.rbLoaded suite exampleStarted....Finished in 1.093349 seconds.4 tests, 9 assertions, 0 failures, 0 errors, 0 skipsTest run options: --seed 31924在1.8.7上你需要多做一点。在较旧的rubies中,即使你等待PTY进程完成,PTY也常常会以PTY :: ChildExited错误退出。因此,如果您按照编写的方式运行测试,则得到以下结果:On 1.8.7 you need to do a bit more. In older rubies PTY would often exit with PTY::ChildExited errors, even when you wait for the PTY process to finish. As a result, if you run the tests as written you get this:$ ruby -vruby 1.8.7 (2010-08-16 patchlevel 302) [i686-darwin10.4.0]$ ruby example.rbLoaded suite exampleStartedEE.EFinished 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, 0 failures, 3 errors注意几乎所有的测试都有一个ChildExited错误炸弹,但是一个(顺便说一下,代表最真实的PTY使用的那个)成功按预期成功。当然,这种不稳定的行为是一个错误,如上所示,它已在1.9.2中得到修复。Notice ALMOST all the tests bomb with a ChildExited error, but one (incidentally the one representing the most realistic use of PTY) succeeds as expected. Surely this erratic behavior is a bug and, as already shown, it has been fixed in 1.9.2.然而,有一个部分解决方法。您可以使用以下内容专门处理ChildExited错误:There is a partial workaround, however. You can specifically handle the ChildExited errors using something like this:def pty(cmd, &block) begin PTY.spawn(cmd, &block) $?.exitstatus rescue PTY::ChildExited $!.status.exitstatus endend插入,再次运行测试,得到的结果与1.9.2一致, BIG警告说$?将无法正确设置(与1.9.2不同)。具体来说,如果你要添加这个测试:Insert that, run the tests again, and you get results consistent with 1.9.2, with the BIG caveat that $? will not be set correctly (unlike 1.9.2). Specifically if you were to add this test:def test_setting_of_process_status system "true" assert_equal 0, $?.exitstatus begin PTY.spawn("false") do |r,w,pid| Process.wait(pid) end rescue PTY::ChildExited end assert_equal 1, $?.exitstatusend你在1.9.2上取得成功,你在1.8.7上失败了。在1.8.7的情况下,PTY通过ChildExited错误完成 - Process.wait永远不会被调用,因此永远不会设置$?。相反,$?从'systemtrue'继续,你得到0而不是1作为退出状态。You get success on 1.9.2 and you get failure on 1.8.7. In the 1.8.7 case the PTY completes via the ChildExited error -- the Process.wait never gets called and thus never sets $?. Instead the $? from the 'system "true"' persists and you get 0 instead of 1 as the exit status. $的行为?很难遵循,并有更多的警告,我不会进入(即有时PTY 将通过Process.wait完成)。 The behavior of $? is hard to follow and has more caveats that I won't get into (ie sometimes the PTY will complete via the Process.wait). 这篇关于如何获取PTY.spawn子退出代码?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!
09-16 06:49