Ruby tips

  • 1.多线程消费队列

  • 2.popen执行命令获取标准输出的写法

  • 3.Ruby解析脚本Option参数

1.多线程消费队列

场景:队列长度不限定,线程个数有限,使用线程循环消费队列内的元素对象

require 'thread'

queue = Queue.new
threads = []

# add work to the queue
queue << work_unit

4.times do
  threads << Thread.new do
    # loop until there are no more things to do
    until queue.empty?
      # pop with the non-blocking flag set, this raises
      # an exception if the queue is empty, in which case
      # work_unit will be set to nil
      work_unit = queue.pop(true) rescue nil
      if work_unit
        # do work
      end
    end
    # when there is no more work, the thread will stop
  end
end

# wait until all threads have completed processing
threads.each { |t| t.join }

使用该程序编写的一个多线程并发请求网络数据的代码

#! /usr/bin/env ruby

require 'json'
require 'net/http'
require 'nokogiri'          # gem install nokogiri

def sendhttp(hash,port)
	if port == '80'
            http = Net::HTTP.new(hash['domain'],80)
            http.use_ssl = false  
	elsif port == '443'
            http = Net::HTTP.new(hash['domain'],443)
            http.use_ssl = true  
        end
	begin
		resp = http.get(hash['uri'],hash['headers'])
	rescue
		puts "error:#{$!} #{hash['domain']}"
		#puts "at:#{$@}"  
	end	
	return resp
end


def polling(hash)
	ret = sendhttp(hash,'80')
	if ret
		return ret
	else 
		ret = sendhttp(hash,'443')
	end
	unless ret
		return false
	end
end

def main()
	headers = {   ##定义http请求头信息  
	  'User-Agent' => 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.9; rv:18.0) Gecko/20100101 Firefox/18.0',
	  'Content-Type' => 'application/x-www-form-urlencoded',  
	  'Accept' => 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
	  'Accept-Language' => 'zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3',
	  'Accept-Encoding' => 'gzip, deflate',
	  'Connection' => 'keep-alive',
  }  

	  para    = Hash.new
 #	  para['domain']  = 'api.immomo.com'
	  para['headers'] = headers
	  para['uri']     = '/'

	queue = Queue.new
	File.open('/tmp/urllist','r').readlines.each{|each| queue << each.chomp}
	
	threads = []
	5.times{
		threads << Thread.new {
			until queue.empty?
				work_until = queue.pop(true) rescue nil

				if work_until
					para['domain'] = work_until
					respones = polling(para)
					if respones 
						puts "#{para['domain']},#{respones.code}"
					else
						puts "#{para['domain']},connect error"
					end
				end
			end
		}
	}
	threads.each{|t| t.join}		
#	output 	= polling(para)

	#if output
	 # p output.code
	#end 
end

main

2.popen执行命令获取标准输出的代码写法

#!/usr/bin/env ruby

process = IO.popen(["./the-program", "testing", "one", "Two", "three"])

while !process.eof?
  line = process.gets
  puts "GOT: #{line}"
end

3.Ruby解析脚本Option参数

require 'getoptlong'

options = GetoptLong.new(
  ['--xxx', GetoptLong::REQUIRED_ARGUMENT],
  ['--yyy', GetoptLong::OPTIONAL_ARGUMENT],
  ['--zzz', GetoptLong::NO_ARGUMENT]
)
options.each do |option, argument|
  p [option, argument]
end

Output:

$ ruby types.rb --xxx foo

["--xxx", "foo"]

Reference

——————————

http://stackoverflow.com/questions/6558828/thread-and-queue

http://stackoverflow.com/questions/7117088/ruby-io-popen-stdout-buffering

https://docs.ruby-lang.org/en/master/GetoptLong.html


Author | Mushen

THE QUIETER YOU BECOME, THE MORE YOU ARE ABLE TO HEAR. 安全运营搞了十多年,现在在阿里云做安全架构和SDL。