rehctaw 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 +41 -0
  3. data/bin/rehctaw +103 -0
  4. metadata +48 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 52bdd0357b77fbd19825f9cbe698a35ba024ba87
4
+ data.tar.gz: 1f584f7e65da9fa005c19b4aa3ecf886439ce991
5
+ SHA512:
6
+ metadata.gz: 3d7a13db6f39cdb4bfe59f47b0191eb538c08165084645f3830ecd2d61b4b9ea672fa835256b673c75d14775f519c21ce444ddd567ea4c6affb4d46375085d7c
7
+ data.tar.gz: 266fed86851ed1a113c1c53333f60138df14a502b7fcc2bc94c005f42b271a166ab082dbcc35716524bdbf7f53f71b66323eb479364bfcac4c8d6fe76e9fccb5
data/README.md ADDED
@@ -0,0 +1,41 @@
1
+ ## Name
2
+
3
+ `rehctaw` - Execute system commands according to file contents.
4
+
5
+ ## Description
6
+
7
+ `rehctaw` watches contents of a file, and executes system commands
8
+ according to those contents. The commands, intervals, ... are provided
9
+ in a YAML configuration file which is also watched.
10
+
11
+ ## Example
12
+
13
+ The sample configuration file can be found under `./examples/` directory.
14
+ To use this example, type
15
+
16
+ $ cp ./examples/simple.yaml ./examples/mine.yaml
17
+ $ ./bin/rehctaw ./examples/mine.yaml
18
+ $ echo foobar > /tmp/watcher
19
+ $ echo reload > /tmp/watcher
20
+
21
+ You can update the file `./examples/mine.yaml`. The program will use
22
+ new settings in the next run.
23
+
24
+ ## License
25
+
26
+ MIT
27
+
28
+ ## Author
29
+
30
+ Anh K. Huynh
31
+
32
+ ## History
33
+
34
+ The idea comes from some `Rails` framework. When a `Rails` application
35
+ is running, you can quickly send a `reload` signal to it, by touching
36
+ a file. See [ChiliProject][] for an example.
37
+
38
+ I don't want to use `inotify`, because that works at file system level
39
+ and it may cause some issues when the file is renamed.
40
+
41
+ [ChiliProject]: https://www.chiliproject.org/projects/chiliproject/wiki/Restart_ChiliProject
data/bin/rehctaw ADDED
@@ -0,0 +1,103 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # Purpose: Execute something according to contents of a file
4
+ # Author : Anh K. Huynh
5
+ # License: MIT
6
+ # Date : 2015 Feb 25
7
+
8
+ begin
9
+ require 'yaml'
10
+ require 'timeout'
11
+ rescue => e
12
+ STDERR.puts ":: Error: #{e}"
13
+ exit 127
14
+ end
15
+
16
+ GLOBAL_WATCHER = {
17
+ "mtime" => 0
18
+ }
19
+
20
+ _default_watcher = {
21
+ "interval" => 5,
22
+ "stop" => "/bin/true",
23
+ "start" => "/bin/true",
24
+ "restart" => "/bin/true",
25
+ "reset" => "/bin/true",
26
+ "action" => "",
27
+ "file" => "/dev/null",
28
+ "mtime" => 0,
29
+ "timeout" => 10
30
+ }
31
+
32
+ def _say(something)
33
+ STDERR.puts ":: #{something}"
34
+ end
35
+
36
+ def _configuration_rescan(watcher, config_file)
37
+ return watcher unless File.file?(config_file) and File.readable?(config_file)
38
+
39
+ new_mtime = File.stat(config_file).mtime.to_i
40
+
41
+ if new_mtime != GLOBAL_WATCHER["mtime"]
42
+ GLOBAL_WATCHER["mtime"] = new_mtime
43
+ begin
44
+ new_watcher = YAML.load_file(config_file)
45
+ watcher.merge!(new_watcher["watcher"])
46
+ watcher["interval"] = [1, watcher["interval"].to_i.abs].max
47
+ watcher["timeout"] = [1, watcher["timeout"].to_i.abs].max
48
+
49
+ _say "Info: Config reload => #{new_watcher.inspect}"
50
+ rescue => e
51
+ _say "Error: #{e}"
52
+ return watcher
53
+ end
54
+ end
55
+
56
+ return watcher
57
+ end
58
+
59
+ if ARGV.size < 1
60
+ _say "Error: Missing configuration file"
61
+ exit 127
62
+ end
63
+
64
+ GLOBAL_WATCHER["file"] = ARGV.first
65
+ watcher = _configuration_rescan(_default_watcher, GLOBAL_WATCHER["file"])
66
+
67
+ while true
68
+ executable = false
69
+
70
+ if File.file?(watcher["file"]) and File.readable?(watcher["file"])
71
+ new_mtime = File.stat(watcher["file"]).mtime.to_i
72
+ if new_mtime != watcher["mtime"]
73
+ executable = true if watcher["mtime"] > 0
74
+ watcher["mtime"] = new_mtime
75
+ # FIXME: reading the whole file may not a good idea. It's slow
76
+ # FIXME: should find a way to read the first line of a file.
77
+ new_action = File.readlines(watcher["file"]).first.to_s.strip
78
+ watcher["action"] = new_action
79
+ end
80
+ else
81
+ _say "Error: Action file '#{watcher["file"]}' unreadable"
82
+ end
83
+
84
+ if executable
85
+ if watcher[watcher["action"]]
86
+ command = watcher[watcher["action"]]
87
+ _say "Info: Executing (#{watcher["action"]}) '#{command}'"
88
+ begin
89
+ Timeout::timeout(watcher["timeout"]) do
90
+ ret = system("#{command}")
91
+ end
92
+ _say "Info: Execution complete"
93
+ rescue Timeout::Error => e
94
+ _say "Error: Timeout reachable (#{watcher["timeout"]}s)"
95
+ end
96
+ else
97
+ _say "Error: Invalid action: #{watcher["action"]}"
98
+ end
99
+ end
100
+
101
+ sleep(watcher["interval"])
102
+ watcher = _configuration_rescan(watcher, GLOBAL_WATCHER["file"])
103
+ end
metadata ADDED
@@ -0,0 +1,48 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rehctaw
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.1.1
5
+ platform: ruby
6
+ authors:
7
+ - Anh K. Huynh
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-02-26 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: "`rehctaw` watches contents of a file, and executes system commands according
14
+ to those contents. The commands, intervals, ... are provided in a YAML configuration
15
+ file which is also watched."
16
+ email: kyanh@theslinux.org
17
+ executables:
18
+ - rehctaw
19
+ extensions: []
20
+ extra_rdoc_files: []
21
+ files:
22
+ - README.md
23
+ - bin/rehctaw
24
+ homepage: https://github.com/icy/rehctaw
25
+ licenses:
26
+ - MIT
27
+ metadata: {}
28
+ post_install_message:
29
+ rdoc_options: []
30
+ require_paths:
31
+ - lib
32
+ required_ruby_version: !ruby/object:Gem::Requirement
33
+ requirements:
34
+ - - ">="
35
+ - !ruby/object:Gem::Version
36
+ version: '0'
37
+ required_rubygems_version: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - ">="
40
+ - !ruby/object:Gem::Version
41
+ version: '0'
42
+ requirements: []
43
+ rubyforge_project:
44
+ rubygems_version: 2.4.5
45
+ signing_key:
46
+ specification_version: 4
47
+ summary: "`rehctaw` executes system commands according to file contents"
48
+ test_files: []