2010-06-02 12 views
12

Tôi đang cố kết nối, đọc và ghi từ ổ cắm UNIX trong Ruby. Nó là một ổ cắm thống kê được sử dụng bởi haproxy.Đọc/Viết từ Ổ cắm Unix trong Ruby

Mã của tôi là như sau:

require 'socket' 
socket = UNIXSocket.new("/tmp/haproxy.stats.socket") 

# First attempt: works 

socket.puts("show stat") 

while(line = socket.gets) do 
    puts line 
end 

# Second attemp: fails 

socket.puts("show stat") 

while(line = socket.gets) do 
    puts line 
end 

Nó thành công lần đầu tiên, nhưng trên nỗ lực thứ hai thất bại. Tôi cung không chăc tại sao.

# pxname,svname,qcur,qmax,scur,smax,slim,stot,bin,bout,dreq,dresp,ereq,econ,eresp,wretr,wredis,status,weight,act,bck,chkfail,chkdown,lastchg,downtime,qlimit,pid,iid,sid,throttle,lbtot,tracked,type,rate,rate_lim,rate_max,check_status,check_code,check_duration,hrsp_1xx,hrsp_2xx,hrsp_3xx,hrsp_4xx,hrsp_5xx,hrsp_other,hanafail,req_rate,req_rate_max,req_tot,cli_abrt,srv_abrt, 
stats,FRONTEND,,,0,0,2000,0,0,0,0,0,0,,,,,OPEN,,,,,,,,,1,1,0,,,,0,0,0,0,,,,0,0,0,0,0,0,,0,0,0,,, 
stats,BACKEND,0,0,0,0,2000,0,0,0,0,0,,0,0,0,0,UP,0,0,0,,0,22,0,,1,1,0,,0,,1,0,,0,,,,0,0,0,0,0,0,,,,,0,0, 
legacy_socket,FRONTEND,,,0,0,1000,0,0,0,0,0,0,,,,,OPEN,,,,,,,,,1,2,0,,,,0,0,0,0,,,,0,0,0,0,0,0,,0,0,0,,, 
all,FRONTEND,,,0,0,10000,0,0,0,0,0,0,,,,,OPEN,,,,,,,,,1,3,0,,,,0,0,0,0,,,,0,0,0,0,0,0,,0,0,0,,, 
socket_backend,socket,0,0,0,0,200,0,0,0,,0,,0,0,0,0,DOWN,1,1,0,0,1,22,22,,1,4,1,,0,,2,0,,0,L4CON,,0,0,0,0,0,0,0,0,,,,0,0, 
socket_backend,socket,0,0,0,0,200,0,0,0,,0,,0,0,0,0,DOWN,1,1,0,0,1,22,22,,1,4,2,,0,,2,0,,0,L4CON,,0,0,0,0,0,0,0,0,,,,0,0, 
socket_backend,socket,0,0,0,0,200,0,0,0,,0,,0,0,0,0,DOWN,1,1,0,0,1,22,22,,1,4,3,,0,,2,0,,0,L4CON,,0,0,0,0,0,0,0,0,,,,0,0, 
socket_backend,socket,0,0,0,0,200,0,0,0,,0,,0,0,0,0,DOWN,1,1,0,0,1,22,22,,1,4,4,,0,,2,0,,0,L4CON,,0,0,0,0,0,0,0,0,,,,0,0, 
socket_backend,socket,0,0,0,0,200,0,0,0,,0,,0,0,0,0,DOWN,1,1,0,0,1,22,22,,1,4,5,,0,,2,0,,0,L4CON,,0,0,0,0,0,0,0,0,,,,0,0, 
socket_backend,socket,0,0,0,0,200,0,0,0,,0,,0,0,0,0,DOWN,1,1,0,0,1,22,22,,1,4,6,,0,,2,0,,0,L4CON,,0,0,0,0,0,0,0,0,,,,0,0, 
socket_backend,socket,0,0,0,0,200,0,0,0,,0,,0,0,0,0,DOWN,1,1,0,0,1,22,22,,1,4,7,,0,,2,0,,0,L4CON,,0,0,0,0,0,0,0,0,,,,0,0, 
socket_backend,socket,0,0,0,0,200,0,0,0,,0,,0,0,0,0,DOWN,1,1,0,0,1,21,21,,1,4,8,,0,,2,0,,0,L4CON,,0,0,0,0,0,0,0,0,,,,0,0, 
socket_backend,socket,0,0,0,0,200,0,0,0,,0,,0,0,0,0,DOWN,1,1,0,0,1,21,21,,1,4,9,,0,,2,0,,0,L4CON,,0,0,0,0,0,0,0,0,,,,0,0, 
socket_backend,socket,0,0,0,0,200,0,0,0,,0,,0,0,0,0,DOWN,1,1,0,0,1,21,21,,1,4,10,,0,,2,0,,0,L4CON,,0,0,0,0,0,0,0,0,,,,0,0, 
socket_backend,BACKEND,0,0,0,0,0,0,0,0,0,0,,0,0,0,0,DOWN,0,0,0,,1,21,21,,1,4,0,,0,,1,0,,0,,,,0,0,0,0,0,0,,,,,0,0, 
api_backend,api,0,0,0,0,200,0,0,0,,0,,0,0,0,0,UP,1,1,0,0,0,22,0,,1,5,1,,0,,2,0,,0,L4OK,,0,0,0,0,0,0,0,0,,,,0,0, 
api_backend,api,0,0,0,0,1,0,0,0,,0,,0,0,0,0,UP,1,1,0,0,0,22,0,,1,5,2,,0,,2,0,,0,L4OK,,0,0,0,0,0,0,0,0,,,,0,0, 
api_backend,api,0,0,0,0,1,0,0,0,,0,,0,0,0,0,DOWN,1,1,0,0,1,21,21,,1,5,3,,0,,2,0,,0,L4CON,,0,0,0,0,0,0,0,0,,,,0,0, 
api_backend,BACKEND,0,0,0,0,0,0,0,0,0,0,,0,0,0,0,UP,2,2,0,,0,22,0,,1,5,0,,0,,1,0,,0,,,,0,0,0,0,0,0,,,,,0,0, 
www_backend,ruby-www,0,0,0,0,10000,0,0,0,,0,,0,0,0,0,UP,1,1,0,0,0,22,0,,1,6,1,,0,,2,0,,0,L4OK,,0,0,0,0,0,0,0,0,,,,0,0, 
www_backend,BACKEND,0,0,0,0,0,0,0,0,0,0,,0,0,0,0,UP,1,1,0,,0,22,0,,1,6,0,,0,,1,0,,0,,,,0,0,0,0,0,0,,,,,0,0, 

/Users/Olly/Desktop/haproxy_stats.rb:14:in `write': Broken pipe (Errno::EPIPE) 
    from /Users/Olly/Desktop/haproxy_stats.rb:14:in `puts' 
    from /Users/Olly/Desktop/haproxy_stats.rb:14 

Sự cố là gì? Có một tham chiếu tốt để sử dụng ổ cắm UNIX và Ruby?

Trả lời

5

Có vẻ như kết nối đã bị đóng sau yêu cầu đầu tiên. Tôi không nghĩ bạn đang làm gì sai. Ổ cắm thống kê HAProxy có thể được thiết kế sao cho nó đáp ứng với một lệnh duy nhất và sau đó đóng kết nối.

Tôi nghĩ bạn cần phải kết nối lại cho từng yêu cầu.

Nếu bạn nhìn vào this blog post là về việc sử dụng ổ cắm thống kê HAProxy với socat thì điều này có ý nghĩa bởi vì bạn viết lệnh show stat vào lần đọc socat và socat từ socket cho đến khi đóng.

+0

Cảm ơn. Có vẻ như tôi cần phải đọc về cách ổ cắm UNIX hoạt động. Tôi đã hy vọng nó hoạt động giống như một TCPSocket vẫn mở. – Olly

+0

Một trong những điều tôi không nhận được là khi tôi sử dụng socat, sau đó tôi luôn nhận được kết quả trả về từ socket, tuy nhiên khi tôi làm điều này thông qua mã ruby ​​ở trên, mỗi bây giờ và sau đó tôi không nhận được bất kỳ dữ liệu nào được trả về từ HAproxy ... vì vậy tôi phải chạy vài lần ... một số thứ tồi tệ trong việc thực hiện socket của Ruby, tôi đoán vậy. – gyre

0

Bạn có thể sử dụng ổ cắm người. Bạn có thể sử dụng socket-class giống như bạn nếu nó là một hàm C.

Tôi thấy trang-man rất hữu ích.

13

Olly,

HAproxy đóng kết nối sau khi yêu cầu đầu tiên, trừ khi bạn sử dụng "nhắc nhở" lệnh (xem http://haproxy.1wt.eu/download/1.4/doc/configuration.txt phần 9.2):

#!/usr/bin/env ruby                               

require 'socket'                                

socket = UNIXSocket.new("/tmp/haproxy.stats.socket")                        

# Goes interactive mode 
socket.puts("prompt")                              

# Ask statistics every second                                
while true                                 
    socket.puts("show stat")                             
    socket.each_char do |c| 
    # We had the prompt, break out                         
    break if c == '>'                              
    print c                                 
    end                                  

    sleep 1                                 
end    
2

Tôi cũng gặp phải những vấn đề tương tự khi sử dụng socket.puts, bạn có thể sử dụng socket.write thay vì socket.puts để khắc phục.

#!/usr/bin/evn ruby 
# -*- coding: UTF-8 -*- 

require 'rubygems' 
require 'uri' 
require 'socket' 
require 'yaml' 

SOCKET = URI.parse("/var/run/haproxy/haproxy.sock") 

def get_info 
    UNIXSocket.open(SOCKET.path) do |socket| 
    socket.write("show info;") 
    info = YAML::load socket 
    #info.each {|key, value| puts "#{key} ➤ #{value}"} 
    end 
end 

puts get_info["Uptime_sec"] 

Nhìn này gem để biết thêm thông tin, mã nguồn là here.