rolo 1.0.2 → 1.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (4) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +55 -44
  3. data/bin/rolo +90 -18
  4. metadata +12 -12
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 85800c263104b5c8d064668bc6794ad5f8473a76
4
+ data.tar.gz: 8b5519137d8d035ed43a288512be8117b631d2d4
5
+ SHA512:
6
+ metadata.gz: c6eef30e55754f6f12806fe1ae57bc348fcb93bdb0f6f43a8db4bef66feb9808d727d464406b0cf3f868f56a97e5b18e33d9e4d2789f63d0acbf512f178c90d2
7
+ data.tar.gz: bd64784e67ef5eb6501abc32316cad8eab5edadb1702ef2aa33eacaedf1ab1d852df2722bfc5cd338107cdf99d9c91a91258862bd29eacd27d080f9adcad0716
data/README.md CHANGED
@@ -4,39 +4,42 @@
4
4
 
5
5
  ## SYNOPSIS
6
6
 
7
- <pre>
8
- $0 [-v] [--test] [-a address] -p port command [arguments]
9
- </pre>
7
+ $0 [options] command [arguments]
10
8
 
11
9
  ## DESCRIPTION
12
10
 
11
+ Start an application and/or prevent it from running twice by simply
12
+ checking if there is a network socket that is open by the application
13
+ and/or by `rolo`.
14
+
13
15
  `rolo.rb` prevents a program from running more than one copy at a time;
14
- it is useful with cron to make sure that a job doesn't run before a
15
- previous one has finished. `robo.rb` is a ruby version of Timothy
16
- program `solo` with more options.
16
+ it is useful with cron to make sure that a job doesn't run before a
17
+ previous one has finished. `robo.rb` is a ruby version of Timothy
18
+ program <https://github.com/timkay/solo> with some more options.
17
19
 
18
20
  ## OPTIONS
19
21
 
20
- * `-v` (`--verbose`)
21
- Print verbose message
22
- * `-t` (`--test`)
23
- Test of program is running. Don't execute command.
24
- * `-a` (`--address`)
25
- Address to check / listen on. By default, this address is
26
- `127.x.y.1:<port>` where `x.y` is translated from process's user
27
- identity number and this allows two different users on the system
28
- can use the same port with `rolo.rb`
29
- * `-p` (`--port`)
30
- Port to check / on which rolo will listen
31
-
32
- In `<command>` and `<arguments>`, you can use `%address`, `%port` which
33
- are replaced by the socket address and port that the problem uses to
34
- check for status of your command. This is very useful if your command
35
- closes all file descriptors at the time it runs, but it has some ways
36
- to listen on `%address:%port`. See EXAMPLE for details.
22
+ Please run the command `rolo` without any arguments for more details.
23
+
24
+ ## INSTALLATION
25
+
26
+ This program can be installed by using RubyGems
27
+
28
+ gem install --remote rolo
29
+
30
+ You can build and install it locally
31
+
32
+ git clone git://github.com/icy/rolo.git
33
+ cd rolo
34
+ gem build rolo.gemspec
35
+ gem install --local rolo-VERSION.gem
37
36
 
38
37
  ## HOW IT WORKS
39
38
 
39
+ If the `--no-bind` option is used, the program will simply assume that
40
+ the port is open by another program and it will only check if that port
41
+ is open or not. Otherwise, see below.
42
+
40
43
  Before starting your `<command>` (using `exec`), `rolo.rb` will open a
41
44
  socket on a local address (or address specified by option `--address`.)
42
45
  This socket will be closed after your command exits, and as long as
@@ -52,11 +55,13 @@ to listen on `%address:%port`. See EXAMPLE for details.
52
55
 
53
56
  ## EXAMPLE
54
57
 
58
+ Here are some simple examples and applications. Feel free to contribute.
59
+
60
+ ### Create SSH tunnels
61
+
55
62
  To create tunnel to a remote server, you can use this ssh command
56
63
 
57
- <pre>
58
- ssh -fN remote -L localhost:1234:localhost:10000
59
- </pre>
64
+ ssh -fN remote -L localhost:1234:localhost:10000
60
65
 
61
66
  This allows you to connect to the local port 1234 on your mahince
62
67
  as same as conneting to address `localhost:10000` on remote server.
@@ -65,15 +70,15 @@ ssh -fN remote -L localhost:1234:localhost:10000
65
70
 
66
71
  To keep this tunnel persistent, you can add this to your crontab
67
72
 
68
- <pre>
69
- rolo.rb -p 4567 \
70
- ssh remote -fNL localhost:1234:localhost:10000
71
- </pre>
73
+ rolo.rb -p 4567 \
74
+ ssh remote -fNL localhost:1234:localhost:10000
72
75
 
73
76
  and allows this line to be executed once every 5 minutes. `rolo.rb`
74
77
  will check if your ssh command is still running. If 'yes', it will
75
78
  simply exit; if 'no', `rolo.rb` will start the ssh command.
76
79
 
80
+ ### With OpenSSH 5.6p1 or later
81
+
77
82
  However, if you use *OpenSSH 5.6p1* (or later), `ssh` will close all file
78
83
  descriptors from the parent (except for `STDIN`, `STDOUT` and `STDERR`).
79
84
  As the socket opened by `rolo.rb` is closed, `rolo.rb` will always
@@ -83,12 +88,11 @@ rolo.rb -p 4567 \
83
88
 
84
89
  Fortunately, `ssh` has option to bind on the local address.
85
90
  Using this option we can trick `rolo.rb` as below
86
- <pre>
87
- rolo.rb -p 4567 \
88
- ssh remote -fN \
89
- -L localhost:1234:localhost:10000 \
90
- -L %address:%port:localhost:12345
91
- </pre>
91
+
92
+ rolo.rb -p 4567 \
93
+ ssh remote -fN \
94
+ -L localhost:1234:localhost:10000 \
95
+ -L %address:%port:localhost:12345
92
96
 
93
97
  The last use of option `-L` will ask `ssh` to open a socket on
94
98
  `%address:%port` (the real values will be provided by `rolo.rb`),
@@ -98,14 +102,21 @@ rolo.rb -p 4567 \
98
102
 
99
103
  Another way is to use option `--address`
100
104
 
101
- <pre>
102
- rolo.rb -p 1234 -a 127.0.0.1 \
103
- ssh remote -fNL localhost:1234:localhost:10000
104
- </pre>
105
+ rolo.rb -p 1234 -a 127.0.0.1 \
106
+ ssh remote -fNL localhost:1234:localhost:10000
105
107
 
106
108
  And this is another way
107
109
 
108
- <pre>
109
- rolo.rb -p 1234 -a 127.0.0.1 \
110
- ssh remote -fNL %address:%port:localhost:10000
111
- </pre>
110
+ rolo.rb -p 1234 -a 127.0.0.1 \
111
+ ssh remote -fNL %address:%port:localhost:10000
112
+
113
+ ### Start VirtualBox guests
114
+
115
+ To make sure that your VirtualBox Windows guest is always running,
116
+ you can use:
117
+
118
+ rolo -a 1.2.3.4 -p 3389 --no-bind \
119
+ VBoxManage startvm foobar --type headless
120
+
121
+ Here `1.2.3.4` is the guest's address, and `3389` is the port
122
+ that is used by `rdesktop` service on the guest.
data/bin/rolo CHANGED
@@ -53,6 +53,7 @@
53
53
  #
54
54
 
55
55
  require 'socket'
56
+ require 'timeout'
56
57
 
57
58
  class String
58
59
  def die(ret = 1, dev = STDERR, prefix = ":: ")
@@ -79,9 +80,60 @@ def close_on_exec(att = true)
79
80
  end
80
81
  end
81
82
 
82
- OPTIONS = {:verbose => false, :port => 0}
83
+ # See also
84
+ # http://stackoverflow.com/questions/517219/ruby-see-if-a-port-is-open
85
+ def port_open?(ip, port, timeout = 1)
86
+ Timeout::timeout(timeout) do
87
+ begin
88
+ TCPSocket.new(ip, port).close
89
+ true
90
+ rescue Errno::ECONNREFUSED, Errno::EHOSTUNREACH => e
91
+ false
92
+ end
93
+ end
94
+ rescue Timeout::Error
95
+ false
96
+ end
97
+
98
+ OPTIONS = {:verbose => false,
99
+ :port => 0,
100
+ :timeout => 3,
101
+ :no_bind => false,
102
+ :address => "",
103
+ :message => ":: Address is in use. Is your application running?"}
104
+
105
+ "Start an application and/or prevent it from running twice by simply
106
+ checking if there is a network socket that is open by the application
107
+ and/or by `rolo`.
108
+
109
+ Syntax: rolo [options] <command> [<command arguments>]
110
+
111
+ Option may be
112
+
113
+ --verbose Show some verbose message (not very useful, though)
114
+ -t, --test Test if application is running or if there's any error
115
+ and return, without executing the command
116
+ -a, --address * Specify the address to listen on / to check
117
+ -p, --port * To port to bind on / to check
118
+ -m, --message * The error message to use when application is running
119
+ --timeout * Time to wait for check if port `address:port` is open
120
+ --no-bind Don't bind on any `address:port`, just use a simple
121
+ TCP connection to check if `address:port` is open.
122
+ This option should be used with `--address` option.
123
+ This option is useful if your application binds on
124
+ another interface (e.g, an remote command), and/or
125
+ the port is too low to bind on (e.g, 22, 80).
83
126
 
84
- "Syntax: rolo [--verbose] [--test] [--address <address>] --port <port_number> <command> [<arguments>]".die if ARGV.empty?
127
+ (Any star `*` indicates the option requires a valid value.)
128
+
129
+ In `<command>` and `<arguments>`, you can use `%address`, `%port` which
130
+ are replaced by the socket address and port that the problem uses to
131
+ check for status of your command. This is very useful if your command
132
+ closes all file descriptors at the time it runs, but it has some ways
133
+ to listen on `%address:%port`. See EXAMPLE for details.
134
+
135
+ To get support please use https://github.com/icy/rolo/issues.
136
+ ".die(1, STDERR, "") if ARGV.empty?
85
137
 
86
138
  while true
87
139
  f = ARGV.first
@@ -100,6 +152,12 @@ while true
100
152
  elsif %w{-m --message}.include?(f)
101
153
  ARGV.shift
102
154
  OPTIONS[:message] = ARGV.shift
155
+ elsif %w{--no-bind}.include?(f)
156
+ ARGV.shift
157
+ OPTIONS[:no_bind] = true
158
+ elsif %w{--timeout}.include?(f)
159
+ ARGV.shift
160
+ OPTIONS[:timeout] = ARGV.shift.to_i
103
161
  elsif %w{-t --test}.include?(f)
104
162
  OPTIONS[:test] = true
105
163
  ARGV.shift
@@ -121,24 +179,38 @@ address = OPTIONS[:address] || [127, Process.uid, 1].pack("CnC").unpack("C4").jo
121
179
 
122
180
  cmd = cmd.gsub("%port", OPTIONS[:port].to_s).gsub("%address", address)
123
181
 
124
- ("Will bind on %s:%d, command = '%s'" \
125
- % [address, OPTIONS[:port], cmd]).verbose(OPTIONS[:verbose])
126
-
127
- # Taken from example in the source code documetation
128
- # Link: http://ruby-doc.org/stdlib-1.8.7/
129
- # libdoc/socket/rdoc/Socket.html#method-i-bind
130
- begin
131
- include Socket::Constants
132
- socket = Socket.new(AF_INET, SOCK_STREAM, 0)
133
- socket.bind(Socket.pack_sockaddr_in(OPTIONS[:port], address))
134
- socket.close if OPTIONS[:address]
135
- rescue Errno::EADDRINUSE
136
- (OPTIONS[:message] || ":: Address is in use. Is your application running?").die(0, STDOUT, "")
137
- rescue => e
138
- e.to_s.die(1)
182
+ ("Would bind on %s:%d, command = '%s'" \
183
+ % [address, OPTIONS[:port], cmd]).verbose(OPTIONS[:verbose]) \
184
+ unless OPTIONS[:no_bind]
185
+
186
+ if OPTIONS[:no_bind]
187
+ "The '--no-bind' option must be used with '--address' option".die \
188
+ if OPTIONS[:address].empty?
189
+
190
+ begin
191
+ OPTIONS[:message].die(0, STDOUT, "") \
192
+ if port_open?(OPTIONS[:address], OPTIONS[:port], OPTIONS[:timeout])
193
+ rescue => e
194
+ e.to_s.die(1)
195
+ end
196
+ else
197
+ # Taken from example in the source code documetation
198
+ # Link: http://ruby-doc.org/stdlib-1.8.7/
199
+ # libdoc/socket/rdoc/Socket.html#method-i-bind
200
+ begin
201
+ include Socket::Constants
202
+ socket = Socket.new(AF_INET, SOCK_STREAM, 0)
203
+ socket.bind(Socket.pack_sockaddr_in(OPTIONS[:port], address))
204
+ # Bind on the address if specified
205
+ socket.close unless OPTIONS[:address].empty?
206
+ rescue Errno::EADDRINUSE
207
+ OPTIONS[:message].die(0, STDOUT, "") unless OPTIONS[:message].empty?
208
+ rescue => e
209
+ e.to_s.die(1)
210
+ end
139
211
  end
140
212
 
141
213
  unless OPTIONS[:test]
142
- close_on_exec(false)
214
+ close_on_exec(false) unless OPTIONS[:no_bind]
143
215
  exec cmd
144
216
  end
metadata CHANGED
@@ -1,17 +1,17 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rolo
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.2
5
- prerelease:
4
+ version: 1.1.1
6
5
  platform: ruby
7
6
  authors:
8
7
  - Anh K. Huynh
9
8
  autorequire:
10
9
  bindir: bin
11
10
  cert_chain: []
12
- date: 2012-07-20 00:00:00.000000000 Z
11
+ date: 2013-06-21 00:00:00.000000000 Z
13
12
  dependencies: []
14
- description: Prevents a program from running more than one copy at a time
13
+ description: Start an application and/or prevent it from running twice by simply checking
14
+ if there is a network socket that is open by the application and/or by `rolo`
15
15
  email: kyanh@viettug.org
16
16
  executables:
17
17
  - rolo
@@ -21,27 +21,27 @@ files:
21
21
  - README.md
22
22
  - bin/rolo
23
23
  homepage: https://github.com/icy/rolo
24
- licenses: []
24
+ licenses:
25
+ - GPL v2
26
+ metadata: {}
25
27
  post_install_message:
26
28
  rdoc_options: []
27
29
  require_paths:
28
30
  - lib
29
31
  required_ruby_version: !ruby/object:Gem::Requirement
30
- none: false
31
32
  requirements:
32
- - - ! '>='
33
+ - - '>='
33
34
  - !ruby/object:Gem::Version
34
35
  version: '0'
35
36
  required_rubygems_version: !ruby/object:Gem::Requirement
36
- none: false
37
37
  requirements:
38
- - - ! '>='
38
+ - - '>='
39
39
  - !ruby/object:Gem::Version
40
40
  version: '0'
41
41
  requirements: []
42
42
  rubyforge_project:
43
- rubygems_version: 1.8.16
43
+ rubygems_version: 2.0.3
44
44
  signing_key:
45
- specification_version: 3
46
- summary: ! '`rolo` prevents a program from running more than one copy at a time'
45
+ specification_version: 4
46
+ summary: '`rolo` prevents a program from running more than one copy at a time'
47
47
  test_files: []