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.
- 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: []
|