rolo 1.0.2 → 1.1.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/README.md +55 -44
- data/bin/rolo +90 -18
- 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
|
-
|
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
|
-
|
15
|
-
|
16
|
-
|
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
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
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
|
-
|
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
|
-
|
69
|
-
|
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
|
-
|
87
|
-
rolo.rb -p 4567 \
|
88
|
-
|
89
|
-
|
90
|
-
|
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
|
-
|
102
|
-
|
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
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
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
|
-
|
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
|
-
|
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
|
-
("
|
125
|
-
% [address, OPTIONS[:port], cmd]).verbose(OPTIONS[:verbose])
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
rescue
|
136
|
-
|
137
|
-
|
138
|
-
|
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.
|
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:
|
11
|
+
date: 2013-06-21 00:00:00.000000000 Z
|
13
12
|
dependencies: []
|
14
|
-
description:
|
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:
|
43
|
+
rubygems_version: 2.0.3
|
44
44
|
signing_key:
|
45
|
-
specification_version:
|
46
|
-
summary:
|
45
|
+
specification_version: 4
|
46
|
+
summary: '`rolo` prevents a program from running more than one copy at a time'
|
47
47
|
test_files: []
|