amqpcat-hw 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +3 -0
- data/Gemfile.lock +15 -0
- data/README.md +106 -0
- data/amqpcat.gemspec +32 -0
- data/bin/amqpcat +118 -0
- data/examples/test_direct.sh +20 -0
- data/examples/test_fanout.sh +21 -0
- data/examples/test_ssl.sh +24 -0
- data/lib/amqpcat.rb +86 -0
- data/lib/amqpcat/version.rb +3 -0
- metadata +75 -0
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
data/README.md
ADDED
@@ -0,0 +1,106 @@
|
|
1
|
+
amqpcat - Netcat-like tool for AMQP queues
|
2
|
+
==========================================
|
3
|
+
|
4
|
+
This was originally written as a "toy" to learn and experiment with
|
5
|
+
rabbitmq. It allows you to easily read/write from AMQP queues/exchanges
|
6
|
+
from the command line or from shell scripts. It is implemented with the
|
7
|
+
`bunny` Ruby gem.
|
8
|
+
|
9
|
+
Install
|
10
|
+
-------
|
11
|
+
Install from gem:
|
12
|
+
|
13
|
+
sudo gem install amqpcat
|
14
|
+
|
15
|
+
Install from github:
|
16
|
+
|
17
|
+
git clone https://github.com/joemiller/amqpcat
|
18
|
+
gem build amqpcat.gemspec
|
19
|
+
gem install amqpcat-0.0.1.gem
|
20
|
+
|
21
|
+
Example Usage
|
22
|
+
-------------
|
23
|
+
|
24
|
+
### 1:1 Messaging
|
25
|
+
|
26
|
+
Start a consumer. This will block until a message is received.
|
27
|
+
|
28
|
+
amqpcat --consumer amqp://guest:guest@rabbitmq.server/
|
29
|
+
|
30
|
+
Publish a message:
|
31
|
+
|
32
|
+
echo "hello rabbit" | amqpcat --publisher amqp://guest:guest@rabbitmq.server/
|
33
|
+
|
34
|
+
The consumer should output the message and exit.
|
35
|
+
|
36
|
+
### 1:N (fanout / pubsub)
|
37
|
+
|
38
|
+
See the `examples/test_fanout.sh` script for another example of fanout
|
39
|
+
messaging.
|
40
|
+
|
41
|
+
Start 2 consumers, using `-s` to prefix the output of each with an
|
42
|
+
identifying string:
|
43
|
+
|
44
|
+
amqpcat --consumer -n fanout.test -t fanout -s "Consumer 1: " amqp://guest:guest@rabbitmq.server/
|
45
|
+
amqpcat --consumer -n fanout.test -t fanout -s "Consumer 2: " amqp://guest:guest@rabbitmq.server/
|
46
|
+
|
47
|
+
Note: In fanout mode, consumers will create their own server-named queues and bind to an exchange
|
48
|
+
defined by the `-n` parameter.
|
49
|
+
|
50
|
+
Published a message to the exchange:
|
51
|
+
|
52
|
+
echo "hello rabbits" | amqpcat --publisher -n fanout.test -t fanout amqp://guest:guest@rabbitmq.server/
|
53
|
+
|
54
|
+
Both of the consumers should print out the message we published.
|
55
|
+
|
56
|
+
Options
|
57
|
+
-------
|
58
|
+
Run `amqpcat -h` to get detailed help output.
|
59
|
+
|
60
|
+
### One-message -vs- Continuous message mode
|
61
|
+
|
62
|
+
By default, when publishing, `amqpcat` will use the newline character to
|
63
|
+
distinguish between messages to publish. However, you can send a single
|
64
|
+
message by using the `--once` option. This can be useful if you need
|
65
|
+
to send a single message that contains new lines.
|
66
|
+
|
67
|
+
SSL Support
|
68
|
+
-----------
|
69
|
+
SSL support has been written but is not tested nor is it fully working
|
70
|
+
at this time (v0.0.1).
|
71
|
+
|
72
|
+
Additionally, the --ssl-key and --ssl-cert options are only supported
|
73
|
+
under newer versions of the Bunny gem (0.8+) or if bunny is installed
|
74
|
+
from the master branch on github.
|
75
|
+
|
76
|
+
Contributing
|
77
|
+
------------
|
78
|
+
1. Fork it.
|
79
|
+
2. Create a branch (`git checkout -b my_feature`)
|
80
|
+
3. Commit your changes (`git commit -am "did some stuff"`)
|
81
|
+
4. Push to the branch (`git push origin my_feature`)
|
82
|
+
5. Create an with a link to your branch
|
83
|
+
|
84
|
+
Author
|
85
|
+
------
|
86
|
+
|
87
|
+
Joe Miller - http://twitter.com/miller_joe || https://github.com/joemiller
|
88
|
+
|
89
|
+
License
|
90
|
+
-------
|
91
|
+
|
92
|
+
Author:: Joe Miller (<joeym@joeym.net>)
|
93
|
+
Copyright:: Copyright (c) 2012 Joe Miller
|
94
|
+
License:: Apache License, Version 2.0
|
95
|
+
|
96
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
97
|
+
you may not use this file except in compliance with the License.
|
98
|
+
You may obtain a copy of the License at
|
99
|
+
|
100
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
101
|
+
|
102
|
+
Unless required by applicable law or agreed to in writing, software
|
103
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
104
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
105
|
+
See the License for the specific language governing permissions and
|
106
|
+
limitations under the License.
|
data/amqpcat.gemspec
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
|
2
|
+
# -*- encoding: utf-8 -*-
|
3
|
+
$:.push('lib')
|
4
|
+
require "amqpcat/version"
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = "amqpcat-hw"
|
8
|
+
s.version = Amqpcat::VERSION.dup
|
9
|
+
s.date = "2012-02-05"
|
10
|
+
s.summary = "Netcat-like tool for reading and writing messages to AMQP message brokers"
|
11
|
+
s.email = "joeym@joeym.net"
|
12
|
+
s.homepage = "https://github.com/joemiller/amqpcat"
|
13
|
+
s.authors = ['Joe Miller']
|
14
|
+
|
15
|
+
s.description = <<-EOF
|
16
|
+
A netcat inspired command line tool for reading and writing simple
|
17
|
+
messages to AMQP based message brokers such as RabbitMQ.
|
18
|
+
EOF
|
19
|
+
|
20
|
+
s.files = Dir['**/*']
|
21
|
+
s.test_files = Dir['test/**/*'] + Dir['spec/**/*']
|
22
|
+
s.executables = Dir['bin/*'].map { |f| File.basename(f) }
|
23
|
+
s.require_paths = ["lib"]
|
24
|
+
|
25
|
+
## Make sure you can build the gem on older versions of RubyGems too:
|
26
|
+
s.rubygems_version = "1.3.6"
|
27
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
28
|
+
s.specification_version = 3 if s.respond_to? :specification_version
|
29
|
+
|
30
|
+
s.add_dependency("bunny", "0.7.8")
|
31
|
+
|
32
|
+
end
|
data/bin/amqpcat
ADDED
@@ -0,0 +1,118 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
$:.unshift(File.dirname(__FILE__) + '/../lib')
|
4
|
+
|
5
|
+
require 'optparse'
|
6
|
+
require 'amqpcat'
|
7
|
+
|
8
|
+
options = {}
|
9
|
+
optparse = OptionParser.new do |opts|
|
10
|
+
opts.banner = <<-EOS
|
11
|
+
Usage: #{$0} [options] amqp-url
|
12
|
+
|
13
|
+
amqp-url format: 'amqp://user:pass@host:port/vhost'
|
14
|
+
|
15
|
+
'amqp' : required. Either amqp or amqps (SSL)
|
16
|
+
'user:pass' : optional. Default: guest:guest
|
17
|
+
'host' : required.
|
18
|
+
'port' : optional. Default: 5672 (amqp), 5671 (amqps)
|
19
|
+
'vhost' : optional. Default: /
|
20
|
+
|
21
|
+
Options:
|
22
|
+
EOS
|
23
|
+
|
24
|
+
opts.on('-h', '--help', 'Display usage') { puts opts; exit 0 }
|
25
|
+
|
26
|
+
options[:mode] = nil
|
27
|
+
opts.on('-c', '--consumer', 'Read data from the queue specified by -n and write to STDOUT') do
|
28
|
+
options[:mode] = :consumer
|
29
|
+
end
|
30
|
+
|
31
|
+
opts.on('-p', '--publisher', 'Read data from STDIN and publish to the exchange specified by -n') do
|
32
|
+
options[:mode] = :publisher
|
33
|
+
end
|
34
|
+
|
35
|
+
opts.on('-k', '--ssl-key FILE', 'Use SSL key in FILE.') do |f|
|
36
|
+
options[:ssl_key] = f
|
37
|
+
end
|
38
|
+
|
39
|
+
opts.on('-r', '--ssl-cert FILE', 'Use SSL cert in FILE.') do |f|
|
40
|
+
options[:ssl_cert] = f
|
41
|
+
end
|
42
|
+
|
43
|
+
options[:verify_ssl] = true
|
44
|
+
opts.on('y', '--[no-]verify-ssl', 'Verify server SSL certficiate. (Default: true)') do |y|
|
45
|
+
options[:verify_ssl] = y
|
46
|
+
end
|
47
|
+
|
48
|
+
options[:prefix] = ''
|
49
|
+
opts.on('-s', '--string STRING', "prefix output with STRING") do |s|
|
50
|
+
options[:prefix] = s
|
51
|
+
end
|
52
|
+
|
53
|
+
options[:once] = false
|
54
|
+
opts.on('-o', '--once', "Read/Write one message then exit. (Default: false)") do
|
55
|
+
options[:once] = true
|
56
|
+
end
|
57
|
+
|
58
|
+
options[:name] = 'amqpcat.default'
|
59
|
+
opts.on('-n', '--name NAME', "Queue and Exchange NAME to use. (Default: amqpcat.default)") do |name|
|
60
|
+
options[:name] = name
|
61
|
+
end
|
62
|
+
|
63
|
+
options[:type] = 'direct'
|
64
|
+
opts.on('-t', '--type TYPE', "Exchange type: direct, fanout. (Default: direct)") do |type|
|
65
|
+
options[:type] = type
|
66
|
+
end
|
67
|
+
|
68
|
+
options[:durable] = true
|
69
|
+
opts.on('--[no-]durable', "Enable/Disable durable messages. (Default: durable=true)") do |d|
|
70
|
+
options[:durable] = d
|
71
|
+
end
|
72
|
+
|
73
|
+
options[:auto_delete] = false
|
74
|
+
opts.on('--[no-]auto_delete', "Enable/Disable auto_delete. (Default: auto_delete=false)") do |d|
|
75
|
+
options[:auto_delete] = d
|
76
|
+
end
|
77
|
+
|
78
|
+
opts.on('--routing-key KEY', "Bind or publish to the exchange with a routing key.") do |k|
|
79
|
+
options[:routing_key] = k
|
80
|
+
end
|
81
|
+
|
82
|
+
end
|
83
|
+
optparse.parse!
|
84
|
+
|
85
|
+
if ARGV.size < 1
|
86
|
+
puts "Must specify amqp-url. --help for help"
|
87
|
+
exit 1
|
88
|
+
end
|
89
|
+
|
90
|
+
if options[:mode].nil?
|
91
|
+
puts "Must specify --consumer or --publisher. --help for help"
|
92
|
+
exit 1
|
93
|
+
end
|
94
|
+
|
95
|
+
amqp_url = ARGV[0]
|
96
|
+
amqpcat = Amqpcat.new(amqp_url, options)
|
97
|
+
|
98
|
+
trap 'SIGINT', proc { amqpcat.finish; exit 0 }
|
99
|
+
|
100
|
+
case options[:mode]
|
101
|
+
when :consumer
|
102
|
+
amqpcat.subscribe do |msg|
|
103
|
+
$stdout.write options[:prefix] + msg[:payload]
|
104
|
+
$stdout.flush
|
105
|
+
if options[:once]
|
106
|
+
amqpcat.finish
|
107
|
+
exit
|
108
|
+
end
|
109
|
+
end
|
110
|
+
when :publisher
|
111
|
+
if options[:once]
|
112
|
+
amqpcat.publish $stdin.read
|
113
|
+
else
|
114
|
+
$stdin.each_line { |l| amqpcat.publish(l) }
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
amqpcat.finish
|
@@ -0,0 +1,20 @@
|
|
1
|
+
#!/bin/sh
|
2
|
+
|
3
|
+
amqpcat_bin="`dirname $0`/../bin/amqpcat"
|
4
|
+
|
5
|
+
url="amqp://guest:guest@rabbitmq/"
|
6
|
+
opts="--name=direct.test --type=direct"
|
7
|
+
|
8
|
+
## start 2 consumers ##
|
9
|
+
$amqpcat_bin -s "Consumer 1: " --consumer $url $opts &
|
10
|
+
$amqpcat_bin -s "Consumer 2: " --consumer $url $opts &
|
11
|
+
|
12
|
+
## send messages ##
|
13
|
+
echo "test direct queue: 1" | $amqpcat_bin --publisher $url $opts
|
14
|
+
echo "test direct queue: 2" | $amqpcat_bin --publisher $url $opts
|
15
|
+
echo "test direct queue: 3" | $amqpcat_bin --publisher $url $opts
|
16
|
+
echo "test direct queue: 4" | $amqpcat_bin --publisher $url $opts
|
17
|
+
|
18
|
+
## kill the consumers we forked ##
|
19
|
+
sleep 1
|
20
|
+
kill %1 %2
|
@@ -0,0 +1,21 @@
|
|
1
|
+
#!/bin/sh
|
2
|
+
|
3
|
+
amqpcat_bin="`dirname $0`/../bin/amqpcat"
|
4
|
+
|
5
|
+
amqp_url="amqp://guest:guest@rabbitmq/"
|
6
|
+
amqp_opts="--name=fanout.test --type=fanout"
|
7
|
+
|
8
|
+
## start 2 consumers ##
|
9
|
+
$amqpcat_bin -s "Consumer 1: " $amqp_url $amqp_opts &
|
10
|
+
$amqpcat_bin -s "Consumer 2: " $amqp_url $amqp_opts &
|
11
|
+
sleep 1
|
12
|
+
|
13
|
+
## send messages ##
|
14
|
+
echo "test fanout queue: 1" | $amqpcat_bin $amqp_url $amqp_opts
|
15
|
+
echo "test fanout queue: 2" | $amqpcat_bin $amqp_url $amqp_opts
|
16
|
+
echo "test fanout queue: 3" | $amqpcat_bin $amqp_url $amqp_opts
|
17
|
+
echo "test fanout queue: 4" | $amqpcat_bin $amqp_url $amqp_opts
|
18
|
+
|
19
|
+
## kill the consumers we forked ##
|
20
|
+
sleep 1
|
21
|
+
kill %1 %2
|
@@ -0,0 +1,24 @@
|
|
1
|
+
#!/bin/sh
|
2
|
+
|
3
|
+
whereami=$(dirname $0)
|
4
|
+
amqpcat_bin="$whereami/../bin/amqpcat"
|
5
|
+
|
6
|
+
url="amqps://guest:guest@rabbitmq/"
|
7
|
+
opts="--name=direct.test --type=direct \
|
8
|
+
--ssl-key=$whereami/client_key.pem \
|
9
|
+
--ssl-cert=$whereami/client_cert.pem\
|
10
|
+
--no-verify-ssl"
|
11
|
+
|
12
|
+
## start 2 consumers ##
|
13
|
+
$amqpcat_bin -s "Consumer 1: " --consumer $url $opts &
|
14
|
+
$amqpcat_bin -s "Consumer 2: " --consumer $url $opts &
|
15
|
+
|
16
|
+
## send messages ##
|
17
|
+
echo "test direct queue: 1" | $amqpcat_bin --publisher $url $opts
|
18
|
+
echo "test direct queue: 2" | $amqpcat_bin --publisher $url $opts
|
19
|
+
echo "test direct queue: 3" | $amqpcat_bin --publisher $url $opts
|
20
|
+
echo "test direct queue: 4" | $amqpcat_bin --publisher $url $opts
|
21
|
+
|
22
|
+
## kill the consumers we forked ##
|
23
|
+
sleep 1
|
24
|
+
kill %1 %2
|
data/lib/amqpcat.rb
ADDED
@@ -0,0 +1,86 @@
|
|
1
|
+
require 'uri'
|
2
|
+
require 'bunny'
|
3
|
+
|
4
|
+
class Amqpcat
|
5
|
+
DEFAULT_QUEUE = 'amqpcat.default'
|
6
|
+
|
7
|
+
def initialize(url, options={})
|
8
|
+
parse_amqp_url(url)
|
9
|
+
|
10
|
+
@opts = {
|
11
|
+
:type => 'direct',
|
12
|
+
:name => DEFAULT_QUEUE,
|
13
|
+
:durable => true,
|
14
|
+
:auto_delete => false,
|
15
|
+
:persistent => true,
|
16
|
+
:ssl_key => nil,
|
17
|
+
:ssl_cert => nil,
|
18
|
+
:verify_ssl => true,
|
19
|
+
}.merge(options)
|
20
|
+
|
21
|
+
@amqp_settings.merge!(@opts)
|
22
|
+
@amqp = Bunny.new(@amqp_settings)
|
23
|
+
@amqp.start
|
24
|
+
end
|
25
|
+
|
26
|
+
def publish(msg)
|
27
|
+
exchange.publish(msg, :persistent => @opts[:persistent], :key => @opts[:routing_key])
|
28
|
+
end
|
29
|
+
|
30
|
+
def message_count
|
31
|
+
queue.message_count
|
32
|
+
end
|
33
|
+
|
34
|
+
def fetch
|
35
|
+
queue.pop[:payload]
|
36
|
+
end
|
37
|
+
|
38
|
+
def subscribe(&block)
|
39
|
+
queue.subscribe(&block)
|
40
|
+
end
|
41
|
+
|
42
|
+
def finish
|
43
|
+
@amqp.stop
|
44
|
+
end
|
45
|
+
|
46
|
+
private
|
47
|
+
|
48
|
+
def parse_amqp_url(str)
|
49
|
+
url = URI.parse(str)
|
50
|
+
use_ssl = url.scheme.downcase == 'amqps'
|
51
|
+
@amqp_settings = {
|
52
|
+
:host => url.host,
|
53
|
+
:port => url.port || (use_ssl ? 5671 : 5672),
|
54
|
+
:user => url.user || 'guest',
|
55
|
+
:pass => url.password || 'guest',
|
56
|
+
:vhost => url.path == "" ? '/' : url.path,
|
57
|
+
:ssl => use_ssl,
|
58
|
+
}
|
59
|
+
end
|
60
|
+
|
61
|
+
def exchange
|
62
|
+
return @exchange if @exchange
|
63
|
+
options = {
|
64
|
+
:type => @opts[:type],
|
65
|
+
:durable => @opts[:durable],
|
66
|
+
:auto_delete => @opts[:auto_delete]
|
67
|
+
}
|
68
|
+
@exchange = @amqp.exchange(@opts[:name], options)
|
69
|
+
end
|
70
|
+
|
71
|
+
def queue
|
72
|
+
return @queue if @queue
|
73
|
+
options = {
|
74
|
+
:durable => @opts[:durable],
|
75
|
+
:auto_delete => @opts[:auto_delete]
|
76
|
+
}
|
77
|
+
@queue = case @opts[:type]
|
78
|
+
when 'fanout'
|
79
|
+
@amqp.queue(options)
|
80
|
+
else
|
81
|
+
@amqp.queue(@opts[:name], options)
|
82
|
+
end
|
83
|
+
@queue.bind(exchange, :routing_key => @opts[:routing_key])
|
84
|
+
@queue
|
85
|
+
end
|
86
|
+
end
|
metadata
ADDED
@@ -0,0 +1,75 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: amqpcat-hw
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease:
|
5
|
+
version: 0.0.2
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Joe Miller
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-02-05 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
type: :runtime
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - '='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: 0.7.8
|
22
|
+
prerelease: false
|
23
|
+
version_requirements: !ruby/object:Gem::Requirement
|
24
|
+
none: false
|
25
|
+
requirements:
|
26
|
+
- - '='
|
27
|
+
- !ruby/object:Gem::Version
|
28
|
+
version: 0.7.8
|
29
|
+
name: bunny
|
30
|
+
description: ! 'A netcat inspired command line tool for reading and writing simple
|
31
|
+
|
32
|
+
messages to AMQP based message brokers such as RabbitMQ.
|
33
|
+
|
34
|
+
'
|
35
|
+
email: joeym@joeym.net
|
36
|
+
executables:
|
37
|
+
- amqpcat
|
38
|
+
extensions: []
|
39
|
+
extra_rdoc_files: []
|
40
|
+
files:
|
41
|
+
- Gemfile
|
42
|
+
- Gemfile.lock
|
43
|
+
- bin/amqpcat
|
44
|
+
- lib/amqpcat/version.rb
|
45
|
+
- lib/amqpcat.rb
|
46
|
+
- examples/test_ssl.sh
|
47
|
+
- examples/test_direct.sh
|
48
|
+
- examples/test_fanout.sh
|
49
|
+
- amqpcat.gemspec
|
50
|
+
- README.md
|
51
|
+
homepage: https://github.com/joemiller/amqpcat
|
52
|
+
licenses: []
|
53
|
+
post_install_message:
|
54
|
+
rdoc_options: []
|
55
|
+
require_paths:
|
56
|
+
- lib
|
57
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
58
|
+
none: false
|
59
|
+
requirements:
|
60
|
+
- - ! '>='
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
version: '0'
|
63
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
64
|
+
none: false
|
65
|
+
requirements:
|
66
|
+
- - ! '>='
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
requirements: []
|
70
|
+
rubyforge_project:
|
71
|
+
rubygems_version: 1.8.24
|
72
|
+
signing_key:
|
73
|
+
specification_version: 3
|
74
|
+
summary: Netcat-like tool for reading and writing messages to AMQP message brokers
|
75
|
+
test_files: []
|