2012-04-19 21 views
12

Piszę kod, który pobiera plik, przekazuje ten plik do jednego z kilku plików binarnych do przetworzenia i monitoruje proces konwersji pod kątem błędów. Napisałem i przetestowałem następującą procedurę w systemie OSX, ale system Linux zawiedzie z powodów, o których nie wiem.Ruby na Linux PTY odchodzi bez EOF, podnosi 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 
} 

Komenda który biegnie waha się całkiem sporo, a kod przy znaku ## został uproszczony do lokalnego echa w próbie debugowania problemu. Polecenie zostanie wykonane, a skrypt wypisze oczekiwane wyniki w terminalu, a następnie zgłasza wyjątek.

Błąd produkuje na systemach Debian jest: Errno::EIO (Input/output error - /dev/pts/0):

Wszystkie ciągi poleceń mogę wymyślić produkować ten błąd, a kiedy uruchomić kod bez lokalnego bloku echa działa dobrze:

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

W obu przypadkach sama komenda działa poprawnie, ale wygląda na to, że debian linux nie wysyła euf do góry. Strony doc dla PTY i IO na ruby-doc nie wydają się tutaj udzielać żadnej pomocy.

Wszelkie sugestie? Dzięki.

-vox-

+0

To tylko przypuszczenie, ale czy linie są poprawnie wkompilowane w wersję rubinową Debiana? Jeśli to jest problem i używasz rvm, ich uwagi dotyczące problemu mogą być pomocne: [http://beginrescueend.com/packages/readline/] (http://beginrescueend.com/packages/readline/) – forforf

+0

Thats dobra myśl. Nie używam rvm na tych serwerach, ale skompilowałem ruby1.9.3 ze źródła (i na innym serwerze 1.9.2). Nie sądziłem, że zmiana biblioteki readline może go rozwiązać. Dzieki za sugestie. – voxobscuro

+0

libreadline dotyczy edycji wiersza poleceń, historii itp. (Np. Nie wpływa to na metodę readline IO #. Możesz skompilować Ruby bez obsługi libreadline, a IO będzie działać zgodnie z oczekiwaniami (ale irb będzie nieprzyjemny w użyciu). –

Odpowiedz

15

Musiałem więc posunąć się aż do czytania źródła C biblioteki PTY, aby być naprawdę zadowolonym z tego, co się tutaj dzieje.

Doktor PTY Ruby tak naprawdę nie mówi co mówią komentarze in the source code.

Moim rozwiązaniem było skompletowanie metody pakowania i wywołanie jej z mojego skryptu w razie potrzeby. Ja również zapakowane do metody oczekuje na proces, aby na pewno zjazdu i wchodzenia stanu wyjścia z $?:

# 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 

ten wykorzystywany jest w zasadzie taka sama jak 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 

Byłem trochę bardziej sfrustrowany, gdy dowiedziałem się, że jest to poprawna odpowiedź, ponieważ było to całkowicie nieudokumentowane na ruby-doc.

+0

Interesujące. Przeglądając src, natknąłem się na to w komentarzach dla pty_open: "Wynik operacji odczytu po zamknięciu pty slave zależy od platformy". To jest również w rdoc, ale tęskniłem za tym. –

+0

@RichDrummond Tak, to jest komentarz, o którym mówiłem. Też tęskniłem za tym w rdoc, ale to dlatego, że patrzyłem na notatki dla .spawn i naprawdę nic innego. : - / – voxobscuro

5

Wydaje się ważne dla ERRNO :: EIO być tutaj podniesiona (oznacza to po prostu proces potomny zakończył i zamknął strumień), więc należy się spodziewać, że i go złapać.

Na przykład, patrz wybraną odpowiedź w Continuously read from STDOUT of external process in Ruby i http://www.shanison.com/2010/09/11/ptychildexited-exception-and-ptys-exit-status/

BTW, zrobiłem kilka testów. W Ruby 1.8.7 na Ubuntu 10.04 nie dostaję błędu. Z Ruby 1.9.3, robię. Z JRuby 1.6.4 na Ubuntu w obu trybach 1.8 i 1.9, nie dostaję błędu. W systemie OS X z wersjami 1.8.7, 1.9.2 i 1.9.3 nie pojawia się błąd. Zachowanie jest oczywiście zależne od twojej wersji i platformy Ruby.

+0

Nagroda przyznawana za bycie jedyną osobą, która miała pojęcie o czym mówiłem! Gdybym nie odkrył rozwiązania w źródle C około 15 minut przed opublikowaniem tego, jestem prawie pewien, że i tak by mnie to doprowadziło. Twoje zdrowie! – voxobscuro

Powiązane problemy