rolo 1.0.2 → 1.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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: []