2009-11-27 40 views
32

tôi có lỗi Broken pipe (Errno::EPIPE) bật lên và tôi không hiểu nó là gì hoặc cách khắc phục. lỗi đầy đủ là:Ống bị hỏng (Errno :: EPIPE)

example.rb:19:in `write': Broken pipe (Errno::EPIPE) 
    from example.rb:19:in `print' 
    from example.rb:19 

dòng 19 của mã của tôi là:

vari.print("x=" + my_val + "&y=1&z=Add+Num\r\n") 

Trả lời

21

Nó có nghĩa rằng bất cứ kết nối in được xuất ra để không còn được kết nối. Có lẽ chương trình bắt đầu như đầu vào cho một số chương trình khác:

% ruby_program | another_program 

gì xảy ra là another_program đã thoát đôi khi trước khi print trong câu hỏi.

+0

thực sự, mã này là tất cả cho một yêu cầu http. điều đó có nghĩa là máy chủ không được kết nối vào thời điểm đó? điều này dường như xảy ra ngẫu nhiên. – sepiroth

+0

Tôi không biết nhiều về ruby, nhưng EPIPE có thể là một sự ngắt kết nối mạng. Trên Linux, tôi mong đợi lỗi sẽ là ENETRESET, ECONNABORTED, ECONNRESET, ENOTCONN hoặc ESHUTDOWN cho điều kiện đó. – wallyk

+1

@sepiroth: 'EPIPE' được _system_ xác định; đó là mã thoát được báo cáo bởi một cuộc gọi hệ thống đã kích hoạt tín hiệu 'SIGPIPE', thường chỉ ra rằng quá trình tại đầu _reading_ của _pipe_ đã thoát (trong khi đầu _writing_ vẫn cố ghi vào đường ống); ngoài ra, trong ngữ cảnh _network_, [this] (https://www.gnu.org/software/libc/manual/html_mono/libc.html#Operation-Error-Signals) tuyên bố: "Nguyên nhân khác của' SIGPIPE' là khi bạn cố gắng xuất ra một _socket_ không được kết nối. Xem [Gửi dữ liệu] (https://www.gnu.org/software/libc/manual/html_mono/libc.html#Sending-Data) ". – mklement0

12

@wallyk là đúng về vấn đề này. Một giải pháp là để nắm bắt những tín hiệu với Signal.trap:

Signal.trap("PIPE", "EXIT") 
9

Mặc dù bẫy tín hiệu làm việc, như tokland nói, chúng được định nghĩa ứng dụng rộng rãi và có thể gây ra một số vấn đề nghi ngờ nếu bạn muốn xử lý một đường ống bị hỏng trong một số cách khác ở một nơi khác trong ứng dụng của bạn.

Tôi khuyên bạn chỉ nên sử dụng giải cứu tiêu chuẩn vì lỗi vẫn còn thừa kế từ StandardError. Thông tin thêm về module này lỗi: http://ruby-doc.org/core-2.0.0/Errno.html

Ví dụ:

begin 
    vari.print("x=" + my_val + "&y=1&z=Add+Num\r\n") 
rescue Errno::EPIPE 
    puts "Connection broke!" 
end 

Edit: Điều quan trọng cần lưu ý (như @ mklement0 làm trong các ý kiến) rằng nếu bạn ban đầu được đường ống đầu ra của bạn sử dụng puts một cái gì đó mong đợi đầu ra trên STDOUT, cuối cùng đặt trong mã trên sẽ nâng cao khác Errno :: EPIPE ngoại lệ. Nó có lẽ là thực hành tốt hơn để sử dụng STDERR.puts anyway.

begin 
    vari.print("x=" + my_val + "&y=1&z=Add+Num\r\n") 
rescue Errno::EPIPE 
    STDERR.puts "Connection broke!" 
end 
+0

+1 lời khuyên hợp lý – tokland

+1

Nghe có vẻ hợp lý, nhưng trong thực tế (Ruby 2.0.0) tôi đã không thể bắt lỗi này; thử 'ruby -e' bắt đầu; đặt (1..10000) .map {| n | "dòng # {n}"}; cứu Errno :: EPIPE; đặt "Không thể làm: # {$ !. message}"; kết thúc '| đầu' - nó vẫn bị vỡ; Ngay cả cố gắng giải cứu 'Ngoại lệ 'cũng không hiệu quả. Có cái gì tôi đang mất tích? – mklement0

+2

@ mklement0 Bạn đang thực sự giải cứu ngoại lệ, nhưng ngoại lệ được nâng lên một lần nữa trong câu lệnh giải cứu của bạn bởi vì bạn đang cố gắng viết chuỗi ngoại lệ tùy chỉnh của bạn tới STDOUT mà vẫn đang được dẫn tới đầu (và đường dẫn đầu đã bị hỏng) . Nếu bạn chạy 'ruby -e' này bắt đầu; đặt (1..10000) .map {| n | "dòng # {n}"}; cứu Errno :: EPIPE; STDERR.puts "Không thể thực hiện: # {$ !. message}"; kết thúc '| head' bạn sẽ thấy rằng nó thực sự giải cứu Errno gốc :: EPIPE ngoại lệ. –

6

Sau đây chủ yếu áp dụng cho các kịch bản của Ruby được thiết kế để hoạt động như CLIs; CLI thường chỉ cần chấm dứt lặng lẽ với mã thoát cụ thể khi nhận được SIGPIPE; đối với các tập lệnh yêu cầu xử lý từng trường hợp SIGPIPE, hãy xem xét donovan.lampa's helpful answer.

Để bổ sung wallyk's helpful answertokland's helpful answer:

Nếu bạn muốn kịch bản của bạn triển lãm của hệ thống mặc định hành vi, như nhất tiện ích Unix (ví dụ, cat) làm, sử dụng

Signal.trap("SIGPIPE", "SYSTEM_DEFAULT") 

ở đầu tập lệnh của bạn.

Bây giờ, khi kịch bản của bạn nhận được tín hiệu SIGPIPE (trên các hệ thống Unix-like), hành vi mặc định của hệ thống sẽ:

  • lặng lẽ chấm dứt kịch bản của bạn
  • báo cáo exit code 141 (mà được tính là 128 (cho biết chấm dứt bằng tín hiệu) + 13 (SIGPIPE 's số))

Ngược lại, Signal.trap("PIPE", "EXIT") sẽ báo cáo mã thoát 0.

Lưu ý rằng trong một vỏ bối cảnh mã lối ra thường là không rõ ràng trong một lệnh như ruby examble.rb | head, bởi vì vỏ (theo mặc định) chỉ báo cáo mã thoát các cuối cùng lệnh của.

Trong bash, bạn có thể kiểm tra ${PIPESTATUS[@]} để xem mã thoát của tất cả các lệnh trong đường dẫn.

Các vấn đề liên quan