Question

Je suis en train de se connecter, lire et écrire à partir d'une prise UNIX en Ruby. Il est une prise de courant utilisée par les statistiques haproxy.

Mon code est le suivant:

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

Il réussit la première fois, mais la deuxième tentative échoue. Je ne sais pas pourquoi.

# 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

Quel est le problème? Y at-il une bonne référence à l'utilisation des sockets UNIX et Ruby?

Était-ce utile?

La solution

Looks like the connection has been closed after the first request. I don't think you are doing anything wrong. The HAProxy stats socket is probably designed so that it responds to a single command and then closes the connection.

I think you need to reconnect for each request.

If you look at this blog post which is about using HAProxy stats socket with socat then this makes sense because you pipe the show stat command into socat and socat reads from the socket until it closes.

Autres conseils

Olly,

HAproxy closes connection after the first request unless you use the "prompt" command (see http://haproxy.1wt.eu/download/1.4/doc/configuration.txt section 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            

I also encountered the same problem when use socket.puts, you can use socket.write instead of socket.puts to fix it.

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

Look this gem for more information, source code is here.

You can use man socket. You can use the socket-class just like you would if it was a C-function.

I found man-pages to be very useful.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top