2012-04-19 8 views
12

Я пишу код, который берет файл, передает этот файл в один из нескольких исполняемых файлов для обработки и отслеживает процесс преобразования ошибок. Я написал и протестировал следующую процедуру на OSX, но linux не удалось по причинам, о которых я не понимаю.Ruby on Linux PTY уходит без EOF, поднимает Errno :: EIO

#run the command, capture the output so it doesn't display 
PTY.spawn(command) {|r,w,pid| 
    until r.eof? do 
     ##mark 
     puts r.readline 
    end 
} 

Команда, которая работает меняется довольно много, и код на отметке ## упрощен в локальное эхо в попытке отладить проблему. Команда выполняется, и сценарий печатает ожидаемый вывод в терминале и затем выдает исключение.

Ошибка производит на системах Debian является: Errno::EIO (Input/output error - /dev/pts/0):

Всего командных строк я могу придумать производить эту ошибку, и когда я запускаю код без локального блока эха он работает просто отлично:

PTY.spawn(command) {|r,w,pid|} 

В любом случае сама команда выполняется нормально, но, похоже, debian linux не отправляет eof по pty. Страницы документов для PTY и IO на ruby-doc, похоже, здесь не помогают.

Любые предложения? Благодарю.

-vox-

+0

Это всего лишь догадка, но правильно ли вычитаются строки в Ruby версии Debian? Если это проблема, и вы используете rvm, их заметки по этому вопросу могут быть полезны: [http://beginrescueend.com/packages/readline/] (http://beginrescueend.com/packages/readline/) – forforf

+0

Thats хорошая мысль. Я не использую rvm на этих серверах, но я скомпилировал ruby1.9.3 из исходного кода (и на другой сервер 1.9.2). Я не считал, что изменение библиотеки readline может сортировать ее. Спасибо за предложение. – voxobscuro

+0

libreadline связан с редактированием командной строки, историей и т. Д. (Например, в irb). Это не влияет на метод чтения IO # readline. Вы можете скомпилировать Ruby без поддержки libreadline, и IO будет работать как ожидалось (но irb будет неприятно использовать). –

ответ

15

Так что мне нужно было дойти до источника C для библиотеки PTY, чтобы получить действительно удовлетворение от того, что здесь происходит.

Документ Ruby PTY на самом деле не говорит, что говорят in the source code.

Моим решением было собрать метод обертки и называть это из моего сценария там, где это необходимо. Я также боксировал в метод ожидания на процесс наверняка выхода и ACCESSING статуса выхода из $?:

# file: lib/safe_pty.rb 

require 'pty' 
module SafePty 
    def self.spawn command, &block 

    PTY.spawn(command) do |r,w,p| 
     begin 
     yield r,w,p 
     rescue Errno::EIO 
     ensure 
     Process.wait p 
     end 
    end 

    $?.exitstatus 
    end 
end 

Это используется в основном так же, как PTY.spawn:

require 'safe_pty' 
exit_status = SafePty.spawn(command) do |r,w,pid| 
    until r.eof? do 
    logger.debug r.readline 
    end 
end 

#test exit_status for zeroness 

Я был немного расстроен, чтобы узнать, что это действительный ответ, поскольку он был полностью недокументирован в ruby-doc.

+0

Интересно. Просмотр src, я наткнулся на это в комментариях для pty_open: «Результат операции чтения, когда pty slave закрыт, зависит от платформы». На самом деле это тоже в rdoc, но я пропустил это. –

+0

@RichDrummond Yea, вот комментарий, о котором я говорил. Я также пропустил это в rdoc, но это потому, что я смотрел заметки на .spawn и не на что-то еще. : - / – voxobscuro

5

кажется действительным для Errno :: EIO быть поднята здесь (это просто означает, что дочерний процесс завершен и закрыл поток), так что вы должны ожидать, что и поймать его.

Например, см выбранного ответа в Continuously read from STDOUT of external process in Ruby и http://www.shanison.com/2010/09/11/ptychildexited-exception-and-ptys-exit-status/

BTW, я сделал некоторые испытания. На Ruby 1.8.7 на Ubuntu 10.04 я не получаю сообщение об ошибке. С Ruby 1.9.3, я делаю. С JRuby 1.6.4 на Ubuntu в режимах 1.8 и 1.9 я не получаю сообщение об ошибке. В OS X, с 1.8.7, 1.9.2 и 1.9.3, я не получаю сообщение об ошибке. Поведение, очевидно, зависит от вашей версии Ruby и платформы.

+0

Bounty награжден за то, что он единственный человек, у которого была идея, о чем я говорю! Если бы я не обнаружил решение в источнике C около 15 минут, прежде чем вы разместили его, я уверен, что это все равно привело бы меня к этому. Ура! – voxobscuro