2010-06-02 113 views
12

我試圖從Ruby中的UNIX套接字進行連接,讀取和寫入。它是haproxy使用的統計套接字。從Ruby中的Unix套接字讀取/寫入

我的代碼如下:

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 

它成功的第一次,但在第二次嘗試失敗。我不知道爲什麼。

# 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 

什麼問題?有沒有一個很好的參考使用UNIX套接字和Ruby?

回答

5

看起來像第一次請求後連接已關閉。我認爲你沒有做錯什麼。 HAProxy統計套接字可能被設計爲響應單個命令,然後關閉連接。

我認爲你需要重新連接每個請求。

如果你看一下this blog post這是關於使用HAProxy的統計插座與socat那麼這是有道理的,因爲你管的show stat命令到socat和socat從套接字中,直到它關閉。

+0

謝謝。看起來我需要了解UNIX套接字如何工作。我期待它像TCPSocket一樣工作,保持開放。 – Olly 2010-06-03 08:36:52

+0

我沒有得到的東西之一是當我使用socat,然後我總是得到從套接字返回的結果,但是當我通過上面的ruby代碼執行此操作時,每隔一段時間我都不會收到任何返回的數據從HAproxy ...所以我必須運行幾次...我猜,在Ruby的套接字實現中有一些狡猾的東西。 – gyre 2013-01-20 15:30:53

0

您可以使用man插座。您可以像使用C函數那樣使用套接字類。

我發現手冊頁非常有用。

13

奧利,

HAProxy的封閉第一請求後連接,除非您使用「提示」命令(見http://haproxy.1wt.eu/download/1.4/doc/configuration.txt 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

我也遇到了同樣的問題,當使用socket.puts,你可以使用socket.write而不是socket.puts來修復它。

#!/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"] 

看看這個gem瞭解更多信息,源代碼是here