executer 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,8 @@
1
+ .DS_Store
2
+ *.gem
3
+ .bundle
4
+ config/executer.yml
5
+ Gemfile.lock
6
+ pkg
7
+ tmp
8
+ *.log
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source "http://rubygems.org"
2
+
3
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,18 @@
1
+ Copyright (c) 2010
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
4
+ this software and associated documentation files (the "Software"), to deal in
5
+ the Software without restriction, including without limitation the rights to
6
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
7
+ the Software, and to permit persons to whom the Software is furnished to do so,
8
+ subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in all
11
+ copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
15
+ FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
16
+ COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
17
+ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
18
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,44 @@
1
+ Executer
2
+ ===========
3
+
4
+ A daemon that executes commands given to it.
5
+
6
+ Requirements
7
+ ------------
8
+
9
+ * redis
10
+ * executer gem: gem install executer
11
+
12
+ Setup
13
+ ------------
14
+
15
+ You'll need to set up the executer.yml to point to the redis server executer will use. Example:
16
+
17
+ <pre>
18
+ $ cat config/executer.yml
19
+ redis: localhost:6379
20
+ </pre>
21
+
22
+ To start the daemon:
23
+
24
+ <pre>
25
+ executer config/executer.yml
26
+
27
+ Starting executer server (redis @ localhost:6379)...
28
+
29
+ </pre>
30
+
31
+ To use the client and push commands to the daemon:
32
+
33
+ <pre>
34
+ $ irb
35
+ > require 'executer'
36
+ > Executer::Client.new('localhost:6379').run :cmd => 'uname >> /tmp/uname.txt', :id => 1
37
+ </pre>
38
+
39
+ To verify that the command got executed:
40
+
41
+ <pre>
42
+ $ cat /tmp/uname.txt
43
+ Darwin
44
+ </pre>
@@ -0,0 +1,27 @@
1
+ require 'bundler/gem_tasks'
2
+
3
+ # DELETE AFTER USING
4
+ desc "Rename project"
5
+ task :rename do
6
+ name = ENV['NAME'] || File.basename(Dir.pwd)
7
+ camelize = lambda do |str|
8
+ str.to_s.gsub(/\/(.?)/) { "::#{$1.upcase}" }.gsub(/(?:^|_)(.)/) { $1.upcase }
9
+ end
10
+ dir = Dir['**/executer*']
11
+ begin
12
+ from = dir.pop
13
+ if from
14
+ to = from.split('/')
15
+ to[-1].gsub!('executer', name)
16
+ FileUtils.mv(from, to.join('/'))
17
+ end
18
+ end while dir.length > 0
19
+ Dir["**/*"].each do |path|
20
+ if File.file?(path)
21
+ `sed -i '' 's/executer/#{name}/g' #{path}`
22
+ `sed -i '' 's/Executer/#{camelize.call(name)}/g' #{path}`
23
+ no_space = File.read(path).gsub(/\s+\z/, '')
24
+ File.open(path, 'w') { |f| f.write(no_space) }
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require File.expand_path("../../lib/executer", __FILE__)
4
+
5
+ Executer.new(ARGV[0])
@@ -0,0 +1,2 @@
1
+ redis: localhost:6379
2
+ log: /var/log/executer.log
@@ -0,0 +1,26 @@
1
+ # -*- encoding: utf-8 -*-
2
+ root = File.expand_path('../', __FILE__)
3
+ lib = "#{root}/lib"
4
+
5
+ $:.unshift lib unless $:.include?(lib)
6
+
7
+ Gem::Specification.new do |s|
8
+ s.name = "executer"
9
+ s.version = '0.1.0'
10
+ s.platform = Gem::Platform::RUBY
11
+ s.authors = ["Tung Nguyen"]
12
+ s.email = ["tongueroo@gmail.com"]
13
+ s.homepage = "https://github.com/tongueroo/executer"
14
+ s.summary = %q{A daemon that executes commands given to it}
15
+ s.description = %q{}
16
+
17
+ s.executables = `cd #{root} && git ls-files bin/*`.split("\n").collect { |f| File.basename(f) }
18
+ s.files = `cd #{root} && git ls-files`.split("\n")
19
+ s.require_paths = %w(lib)
20
+ s.test_files = `cd #{root} && git ls-files -- {features,test,spec}/*`.split("\n")
21
+
22
+ s.add_development_dependency "rspec", "~> 1.0"
23
+
24
+ s.add_dependency "redis", "~> 2.2.2"
25
+ s.add_dependency "yajl-ruby", "~> 1.0.0"
26
+ end
@@ -0,0 +1,63 @@
1
+ require "timeout"
2
+ require "yaml"
3
+ require "logger"
4
+
5
+ gem "yajl-ruby", "~> 1.0.0"
6
+ require "yajl"
7
+
8
+ gem "redis", "~> 2.2.2"
9
+ require "redis"
10
+
11
+ $:.unshift File.dirname(__FILE__)
12
+
13
+ require 'executer/client'
14
+ require 'executer/logger'
15
+
16
+ class Executer
17
+
18
+ def initialize(yaml)
19
+ options = YAML.load(File.read(yaml))
20
+
21
+ @logger = Logger.new(options['log'] || '/var/log/executer.log')
22
+ log "Starting executer server (redis @ #{options['redis']})."
23
+ log "Logging to stdout and #{options['log']}..."
24
+
25
+ redis = Redis.connect(:url => "redis://#{options['redis']}")
26
+ retries = 0
27
+
28
+ begin
29
+ while true
30
+ if request = redis.lpop('executer:request')
31
+ Timeout.timeout(60*60) do
32
+ request = Yajl::Parser.parse(request)
33
+ log("Running #{request.inspect}")
34
+ system(request['cmd'])
35
+ redis.publish(
36
+ "executer:response:#{request['id']}",
37
+ "finished"
38
+ )
39
+ end
40
+ end
41
+
42
+ sleep(1.0 / 1000.0)
43
+ end
44
+ rescue Interrupt
45
+ shut_down
46
+ rescue Exception => e
47
+ log "Error: #{e.message}"
48
+ log "\t#{e.backtrace.join("\n\t")}"
49
+ retries += 1
50
+ shut_down if retries >= 10
51
+ retry
52
+ end
53
+ end
54
+
55
+ def log(message)
56
+ @logger.info("SERVER: #{message}")
57
+ end
58
+
59
+ def shut_down
60
+ log "Shutting down executer server..."
61
+ exit
62
+ end
63
+ end
@@ -0,0 +1,46 @@
1
+ class Executer
2
+ class Client
3
+
4
+ attr_reader :redis_1, :redis_2
5
+
6
+ def initialize(config)
7
+ if File.exist?(config)
8
+ options = YAML.load(File.read(config))
9
+ redis_url = options['redis']
10
+ @logger = Logger.new(options['log'] || '/var/log/executer.log')
11
+ else
12
+ redis_url = config
13
+ @logger = Logger.new('/var/log/executer.log')
14
+ end
15
+ @redis_1 = Redis.connect(:url => "redis://#{redis_url}")
16
+ @redis_2 = Redis.connect(:url => "redis://#{redis_url}")
17
+ end
18
+
19
+ def run(options)
20
+ id = options[:id]
21
+ options = Yajl::Encoder.encode(options)
22
+
23
+ Timeout.timeout(60*60) do
24
+ @redis_1.subscribe("executer:response:#{id}") do |on|
25
+ on.subscribe do |channel, subscriptions|
26
+ log("Queuing: #{options.inspect}")
27
+ @redis_2.rpush "executer:request", options
28
+ end
29
+
30
+ on.message do |channel, message|
31
+ log("Finished: #{message.inspect}")
32
+ if message == 'finished'
33
+ @redis_1.unsubscribe
34
+ end
35
+ end
36
+ end
37
+ end
38
+ true
39
+ end
40
+
41
+ def log(message)
42
+ @logger.info("CLIENT: #{message}")
43
+ end
44
+
45
+ end
46
+ end
@@ -0,0 +1,8 @@
1
+ class Executer
2
+ class Logger < Logger
3
+ def add(severity, message = nil, progname = nil, &block)
4
+ puts progname
5
+ super
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,4 @@
1
+ require 'spec_helper'
2
+
3
+ describe Executer do
4
+ end
@@ -0,0 +1,8 @@
1
+ require "pp"
2
+ require "bundler"
3
+
4
+ Bundler.require(:development)
5
+
6
+ $root = File.expand_path('../../', __FILE__)
7
+
8
+ require "#{$root}/lib/executer"
metadata ADDED
@@ -0,0 +1,96 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: executer
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Tung Nguyen
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2011-12-29 00:00:00.000000000 -08:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: rspec
17
+ requirement: &70226755250660 !ruby/object:Gem::Requirement
18
+ none: false
19
+ requirements:
20
+ - - ~>
21
+ - !ruby/object:Gem::Version
22
+ version: '1.0'
23
+ type: :development
24
+ prerelease: false
25
+ version_requirements: *70226755250660
26
+ - !ruby/object:Gem::Dependency
27
+ name: redis
28
+ requirement: &70226755250140 !ruby/object:Gem::Requirement
29
+ none: false
30
+ requirements:
31
+ - - ~>
32
+ - !ruby/object:Gem::Version
33
+ version: 2.2.2
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: *70226755250140
37
+ - !ruby/object:Gem::Dependency
38
+ name: yajl-ruby
39
+ requirement: &70226755249640 !ruby/object:Gem::Requirement
40
+ none: false
41
+ requirements:
42
+ - - ~>
43
+ - !ruby/object:Gem::Version
44
+ version: 1.0.0
45
+ type: :runtime
46
+ prerelease: false
47
+ version_requirements: *70226755249640
48
+ description: ''
49
+ email:
50
+ - tongueroo@gmail.com
51
+ executables:
52
+ - executer
53
+ extensions: []
54
+ extra_rdoc_files: []
55
+ files:
56
+ - .gitignore
57
+ - Gemfile
58
+ - LICENSE
59
+ - README.md
60
+ - Rakefile
61
+ - bin/executer
62
+ - config/executer.yml.example
63
+ - executer.gemspec
64
+ - lib/executer.rb
65
+ - lib/executer/client.rb
66
+ - lib/executer/logger.rb
67
+ - spec/executer_spec.rb
68
+ - spec/spec_helper.rb
69
+ has_rdoc: true
70
+ homepage: https://github.com/tongueroo/executer
71
+ licenses: []
72
+ post_install_message:
73
+ rdoc_options: []
74
+ require_paths:
75
+ - lib
76
+ required_ruby_version: !ruby/object:Gem::Requirement
77
+ none: false
78
+ requirements:
79
+ - - ! '>='
80
+ - !ruby/object:Gem::Version
81
+ version: '0'
82
+ required_rubygems_version: !ruby/object:Gem::Requirement
83
+ none: false
84
+ requirements:
85
+ - - ! '>='
86
+ - !ruby/object:Gem::Version
87
+ version: '0'
88
+ requirements: []
89
+ rubyforge_project:
90
+ rubygems_version: 1.6.2
91
+ signing_key:
92
+ specification_version: 3
93
+ summary: A daemon that executes commands given to it
94
+ test_files:
95
+ - spec/executer_spec.rb
96
+ - spec/spec_helper.rb