app-deploy 0.6.0
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.
- data/CHANGES +7 -0
- data/README +85 -0
- data/Rakefile +34 -0
- data/TODO +10 -0
- data/app-deploy.gemspec +34 -0
- data/example/Rakefile +113 -0
- data/example/bin/install.sh +4 -0
- data/example/bin/remote_install.sh +9 -0
- data/example/bin/remote_update.sh +3 -0
- data/example/bin/start.sh +3 -0
- data/example/bin/update.sh +7 -0
- data/example/daemon_cluster.yaml +10 -0
- data/example/rack_cluster.yaml +13 -0
- data/lib/app-deploy/daemon.rake +33 -0
- data/lib/app-deploy/daemon.rb +64 -0
- data/lib/app-deploy/daemon_cluster.rb +62 -0
- data/lib/app-deploy/deploy.rake +18 -0
- data/lib/app-deploy/deprecated/merb.rake +20 -0
- data/lib/app-deploy/deprecated/mongrel.rake +13 -0
- data/lib/app-deploy/gem.rake +25 -0
- data/lib/app-deploy/git.rake +66 -0
- data/lib/app-deploy/install.rake +84 -0
- data/lib/app-deploy/nginx.rake +31 -0
- data/lib/app-deploy/rack.rake +34 -0
- data/lib/app-deploy/rack_cluster.rb +79 -0
- data/lib/app-deploy/server.rake +9 -0
- data/lib/app-deploy/signal.rake +30 -0
- data/lib/app-deploy/thin.rake +13 -0
- data/lib/app-deploy/utils.rb +189 -0
- data/lib/app-deploy/version.rb +4 -0
- data/lib/app-deploy.rb +6 -0
- metadata +119 -0
data/CHANGES
ADDED
data/README
ADDED
@@ -0,0 +1,85 @@
|
|
1
|
+
= app-deploy 0.6
|
2
|
+
by Lin Jen-Shin (aka godfat-真常[http://godfat.org])
|
3
|
+
godfat (XD) godfat.org
|
4
|
+
|
5
|
+
== LINKS:
|
6
|
+
|
7
|
+
* github-project[http://github.com/godfat/app-deploy]
|
8
|
+
|
9
|
+
== DESCRIPTION:
|
10
|
+
|
11
|
+
rake tasks for deployment
|
12
|
+
|
13
|
+
== FEATURES:
|
14
|
+
|
15
|
+
$ rake -T app
|
16
|
+
(in /home/photos)
|
17
|
+
rake app:daemon:restart[config] # restart the daemon cluster
|
18
|
+
rake app:daemon:start[config] # start the daemon cluster
|
19
|
+
rake app:daemon:stop[config] # stop the daemon cluster
|
20
|
+
rake app:deploy # deploy to master state
|
21
|
+
rake app:deploy:after # after deploy hook for you to override
|
22
|
+
rake app:deploy:before # before deploy hook for you to override
|
23
|
+
rake app:gem:install # install gems
|
24
|
+
rake app:gem:reinstall # reinstall gems
|
25
|
+
rake app:gem:uninstall # uninstall gems
|
26
|
+
rake app:git[cmd] # generic git cmd walk through all dependency
|
27
|
+
rake app:git:clone # clone repoitory from github
|
28
|
+
rake app:git:pull # pull anything from origin
|
29
|
+
rake app:git:stash # make anything reflect master state
|
30
|
+
rake app:git:submodule # init and update submodule
|
31
|
+
rake app:install # install this application
|
32
|
+
rake app:install:after # after install hook for you to override
|
33
|
+
rake app:install:before # before install hook for you to override
|
34
|
+
rake app:install:remote[hosts,git,cd,branch,script] # remote installation
|
35
|
+
rake app:install:remote:setup[user,file,hosts,script] # upload a tarball and untar to user home, then useradd
|
36
|
+
rake app:install:remote:sh[hosts,script] # invoke a shell script on remote machines
|
37
|
+
rake app:install:remote:upload[file,hosts,path] # upload a file to remote machines
|
38
|
+
rake app:install:remote:useradd[user,hosts,script] # create a user on remote machines
|
39
|
+
rake app:nginx:reload # reload config
|
40
|
+
rake app:nginx:restart # restart nginx
|
41
|
+
rake app:nginx:start[config,nginx] # start nginx, default config is config/nginx.conf, nginx is /usr/sbin/nginx
|
42
|
+
rake app:nginx:stop[timeout] # stop nginx
|
43
|
+
rake app:rack:restart[config] # restart the rack cluster
|
44
|
+
rake app:rack:start[config] # start the rack cluster
|
45
|
+
rake app:rack:stop[config] # stop the rack cluster
|
46
|
+
rake app:server:restart # please define your server:restart task
|
47
|
+
|
48
|
+
== SYNOPSIS:
|
49
|
+
|
50
|
+
see
|
51
|
+
- example/Rakefile
|
52
|
+
- example/rack_cluster.yaml
|
53
|
+
- example/daemon_cluster.yaml
|
54
|
+
|
55
|
+
== REQUIREMENTS:
|
56
|
+
|
57
|
+
* ruby 1.8.7+
|
58
|
+
* [required] rake
|
59
|
+
* [optional] rubygems for rubygems task
|
60
|
+
* [optional] git for git task
|
61
|
+
* [optional] nginx for nginx task
|
62
|
+
* [optional] rack and daemons for rack-cluster task
|
63
|
+
* [optional] thin for thin task
|
64
|
+
|
65
|
+
== INSTALL:
|
66
|
+
|
67
|
+
* gem install app-deploy
|
68
|
+
|
69
|
+
== LICENSE:
|
70
|
+
|
71
|
+
Apache License 2.0
|
72
|
+
|
73
|
+
Copyright (c) 2008-2009, Lin Jen-Shin (aka godfat 真常)
|
74
|
+
|
75
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
76
|
+
you may not use this file except in compliance with the License.
|
77
|
+
You may obtain a copy of the License at
|
78
|
+
|
79
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
80
|
+
|
81
|
+
Unless required by applicable law or agreed to in writing, software
|
82
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
83
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
84
|
+
See the License for the specific language governing permissions and
|
85
|
+
limitations under the License.
|
data/Rakefile
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
begin
|
4
|
+
require 'bones'
|
5
|
+
rescue LoadError
|
6
|
+
abort '### Please install the "bones" gem ###'
|
7
|
+
end
|
8
|
+
|
9
|
+
ensure_in_path 'lib'
|
10
|
+
proj = 'app-deploy'
|
11
|
+
require "#{proj}/version"
|
12
|
+
|
13
|
+
Bones{
|
14
|
+
version AppDeploy::VERSION
|
15
|
+
|
16
|
+
# ruby_opts [''] # silence warning, too many in addressable and/or dm-core
|
17
|
+
|
18
|
+
name proj
|
19
|
+
url "http://github.com/godfat/#{proj}"
|
20
|
+
authors 'Lin Jen-Shin (aka godfat 真常)'
|
21
|
+
email 'godfat (XD) godfat.org'
|
22
|
+
|
23
|
+
history_file 'CHANGES'
|
24
|
+
readme_file 'README'
|
25
|
+
ignore_file '.gitignore'
|
26
|
+
rdoc.include ['\w+']
|
27
|
+
}
|
28
|
+
|
29
|
+
CLEAN.include Dir['**/*.rbc']
|
30
|
+
|
31
|
+
task :default do
|
32
|
+
Rake.application.options.show_task_pattern = /./
|
33
|
+
Rake.application.display_tasks_and_comments
|
34
|
+
end
|
data/TODO
ADDED
data/app-deploy.gemspec
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
Gem::Specification.new do |s|
|
4
|
+
s.name = %q{app-deploy}
|
5
|
+
s.version = "0.5.0"
|
6
|
+
|
7
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
8
|
+
s.authors = ["Lin Jen-Shin (a.k.a. godfat \347\234\237\345\270\270)"]
|
9
|
+
s.date = %q{2009-02-09}
|
10
|
+
s.description = %q{rake tasks for deployment}
|
11
|
+
s.email = %q{godfat (XD) godfat.org}
|
12
|
+
s.extra_rdoc_files = ["CHANGES", "README", "TODO", "app-deploy.gemspec", "example/daemon_cluster.yaml", "example/rack_cluster.yaml", "lib/app-deploy/daemon.rake", "lib/app-deploy/deploy.rake", "lib/app-deploy/gem.rake", "lib/app-deploy/git.rake", "lib/app-deploy/install.rake", "lib/app-deploy/merb.rake", "lib/app-deploy/mongrel.rake", "lib/app-deploy/nginx.rake", "lib/app-deploy/rack.rake", "lib/app-deploy/server.rake", "lib/app-deploy/thin.rake"]
|
13
|
+
s.files = ["CHANGES", "README", "Rakefile", "TODO", "app-deploy.gemspec", "example/Rakefile", "example/daemon_cluster.yaml", "example/rack_cluster.yaml", "lib/app-deploy.rb", "lib/app-deploy/daemon.rake", "lib/app-deploy/daemon.rb", "lib/app-deploy/daemon_cluster.rb", "lib/app-deploy/deploy.rake", "lib/app-deploy/gem.rake", "lib/app-deploy/git.rake", "lib/app-deploy/install.rake", "lib/app-deploy/merb.rake", "lib/app-deploy/mongrel.rake", "lib/app-deploy/nginx.rake", "lib/app-deploy/rack.rake", "lib/app-deploy/rack_cluster.rb", "lib/app-deploy/server.rake", "lib/app-deploy/thin.rake", "lib/app-deploy/utils.rb", "lib/app-deploy/version.rb"]
|
14
|
+
s.has_rdoc = true
|
15
|
+
s.homepage = %q{http://github.com/godfat/app-deploy}
|
16
|
+
s.rdoc_options = ["--diagram", "--charset=utf-8", "--inline-source", "--line-numbers", "--promiscuous", "--main", "README"]
|
17
|
+
s.require_paths = ["lib"]
|
18
|
+
s.rubyforge_project = %q{ludy}
|
19
|
+
s.rubygems_version = %q{1.3.1}
|
20
|
+
s.summary = %q{rake tasks for deployment}
|
21
|
+
|
22
|
+
if s.respond_to? :specification_version then
|
23
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
24
|
+
s.specification_version = 2
|
25
|
+
|
26
|
+
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
27
|
+
s.add_development_dependency(%q<bones>, [">= 2.4.0"])
|
28
|
+
else
|
29
|
+
s.add_dependency(%q<bones>, [">= 2.4.0"])
|
30
|
+
end
|
31
|
+
else
|
32
|
+
s.add_dependency(%q<bones>, [">= 2.4.0"])
|
33
|
+
end
|
34
|
+
end
|
data/example/Rakefile
ADDED
@@ -0,0 +1,113 @@
|
|
1
|
+
|
2
|
+
begin
|
3
|
+
require 'app-deploy'
|
4
|
+
rescue LoadError
|
5
|
+
puts "app-deploy not found, automaticly downloading and installing..."
|
6
|
+
|
7
|
+
gem_cmd = "#{Gem.ruby} #{`which gem`.strip}"
|
8
|
+
gem_opt = '--user-install --no-ri --no-rdoc'
|
9
|
+
gem_int = "#{gem_cmd} install #{gem_opt}"
|
10
|
+
|
11
|
+
sh "#{gem_int} bones" # need bones to build app-deploy
|
12
|
+
|
13
|
+
sh 'git clone git://github.com/godfat/app-deploy.git app-deploy'
|
14
|
+
Dir.chdir 'app-deploy'
|
15
|
+
|
16
|
+
sh 'rake clobber'
|
17
|
+
sh 'rake gem:package'
|
18
|
+
sh "#{gem_int} --local pkg/app-deploy-*.gem"
|
19
|
+
|
20
|
+
Dir.chdir '..'
|
21
|
+
Gem.refresh
|
22
|
+
require 'app-deploy'
|
23
|
+
end
|
24
|
+
|
25
|
+
task :default do
|
26
|
+
Rake.application.options.show_task_pattern = /./
|
27
|
+
Rake.application.display_tasks_and_comments
|
28
|
+
end
|
29
|
+
|
30
|
+
# install gem from rubyforge
|
31
|
+
AppDeploy.dependency_gem :gem => 'bones'
|
32
|
+
|
33
|
+
# install gem from github
|
34
|
+
AppDeploy.dependency_gem :gem => 'pagfiy', :source => 'http://gems.github.com'
|
35
|
+
|
36
|
+
# clone and build and install gem from github with bones
|
37
|
+
AppDeploy.dependency_gem :github_user => 'godfat',
|
38
|
+
:github_project => 'friendly_format',
|
39
|
+
:task_gem => 'bones'
|
40
|
+
|
41
|
+
# same as above but with hoe, and select a git clone path.
|
42
|
+
AppDeploy.dependency_gem :github_user => 'godfat',
|
43
|
+
:github_project => 'mogilefs-client',
|
44
|
+
:task_gem => 'hoe',
|
45
|
+
:git_path => 'tmp/mogilefs-client'
|
46
|
+
|
47
|
+
# same as above but with custom install script
|
48
|
+
AppDeploy.dependency_gem :github_user => 'godfat',
|
49
|
+
:github_project => 'app-deploy',
|
50
|
+
:git_path => 'tmp/app-deploy' do
|
51
|
+
sh 'rake clobber'
|
52
|
+
sh 'rake gem:package'
|
53
|
+
sh 'gem install pkg/app-deploy-*.gem'
|
54
|
+
end
|
55
|
+
|
56
|
+
# no gem to install, just clone it
|
57
|
+
AppDeploy.dependency :github_user => 'godfat',
|
58
|
+
:github_project => 'in_place_editing',
|
59
|
+
:git_path => 'tmp/vendor/plugins/in_place_editing'
|
60
|
+
|
61
|
+
%w[ rack rails daemons rmagick passenger
|
62
|
+
dm-core dm-types dm-timestamps dm-aggregates
|
63
|
+
mogilefs-client memcache-client rubycas-client ].each{ |name|
|
64
|
+
AppDeploy.dependency_gem(:gem => name)
|
65
|
+
}
|
66
|
+
|
67
|
+
namespace :app do
|
68
|
+
namespace :install do
|
69
|
+
# before install hook
|
70
|
+
task :before do
|
71
|
+
# explicit install gem, ignore gem that was already installed
|
72
|
+
AppDeploy.install_gem(:gem => 'hoe')
|
73
|
+
end
|
74
|
+
|
75
|
+
# after install hook
|
76
|
+
task :after do
|
77
|
+
# explicit uninstall gem, ignore gem that was not installed
|
78
|
+
AppDeploy.uninstall_gem(:gem => 'zzz')
|
79
|
+
|
80
|
+
# install passenger nginx module
|
81
|
+
sh("#{Gem.user_dir}/bin/" +
|
82
|
+
Gem.default_exec_format % 'passenger-install-nginx-module' +
|
83
|
+
" --auto --auto-download --prefix=#{Dir.pwd}/nginx")
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
namespace :server do
|
88
|
+
# use thin as server
|
89
|
+
task :restart => 'thin:restart'
|
90
|
+
|
91
|
+
[:start, :stop, :restart, :reload].each{ |cmd|
|
92
|
+
desc "#{cmd} nginx(passenger)"
|
93
|
+
task cmd do
|
94
|
+
ENV['config'] = '/home/app/config/nginx.conf'
|
95
|
+
ENV['nginx'] = '/home/app/nginx/sbin/nginx'
|
96
|
+
Rake::Task["app:nginx:#{cmd}"].invoke
|
97
|
+
end
|
98
|
+
}
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
begin # prevent lacking rails to stop rake app:install to install rails
|
103
|
+
gem 'rails'
|
104
|
+
|
105
|
+
require(File.join(File.dirname(__FILE__), 'config', 'boot'))
|
106
|
+
|
107
|
+
require 'rake'
|
108
|
+
require 'rake/testtask'
|
109
|
+
require 'rake/rdoctask'
|
110
|
+
|
111
|
+
require 'tasks/rails'
|
112
|
+
rescue LoadError
|
113
|
+
end
|
@@ -0,0 +1,9 @@
|
|
1
|
+
#!/bin/sh
|
2
|
+
|
3
|
+
rake app:install:remote:setup user=cas file=ssh.tgz hosts=root@10.0.0.101,root@10.0.0.106,root@10.0.0.111,root@10.0.0.116,root@10.0.0.121
|
4
|
+
|
5
|
+
rake app:install:remote hosts=cas@10.0.0.101,cas@10.0.0.106,cas@10.0.0.111,cas@10.0.0.116,cas@10.0.0.121 \
|
6
|
+
git=git@github.com:godfat/cas.git \
|
7
|
+
cd=~ \
|
8
|
+
branch=origin/stable \
|
9
|
+
script=./bin/install.sh
|
@@ -0,0 +1,33 @@
|
|
1
|
+
|
2
|
+
require 'app-deploy/daemon_cluster'
|
3
|
+
|
4
|
+
namespace :app do
|
5
|
+
namespace :daemon do
|
6
|
+
|
7
|
+
desc 'start the daemon cluster'
|
8
|
+
task :start, [:config] do |t, args|
|
9
|
+
path = args[:config] || 'config/daemon_cluster.yaml'
|
10
|
+
AppDeploy::DaemonCluster.each(path){ |config, cmd|
|
11
|
+
AppDeploy::DaemonCluster.start(config, cmd)
|
12
|
+
}
|
13
|
+
end
|
14
|
+
|
15
|
+
desc 'stop the daemon cluster'
|
16
|
+
task :stop, [:config] do |t, args|
|
17
|
+
path = args[:config] || 'config/daemon_cluster.yaml'
|
18
|
+
AppDeploy::DaemonCluster.each(path){ |config, cmd|
|
19
|
+
AppDeploy.term(config[:pid], config[:server])
|
20
|
+
}
|
21
|
+
end
|
22
|
+
|
23
|
+
desc 'restart the daemon cluster'
|
24
|
+
task :restart, [:config] do |t, args|
|
25
|
+
path = args[:config] || 'config/daemon_cluster.yaml'
|
26
|
+
AppDeploy::DaemonCluster.each(path){ |config, cmd|
|
27
|
+
AppDeploy.term(config[:pid], config[:server])
|
28
|
+
AppDeploy::DaemonCluster.start(config, cmd)
|
29
|
+
}
|
30
|
+
end
|
31
|
+
|
32
|
+
end # of rack
|
33
|
+
end # of app
|
@@ -0,0 +1,64 @@
|
|
1
|
+
|
2
|
+
require 'daemons'
|
3
|
+
|
4
|
+
require 'etc'
|
5
|
+
require 'fileutils'
|
6
|
+
|
7
|
+
module AppDeploy
|
8
|
+
|
9
|
+
module Daemon
|
10
|
+
module_function
|
11
|
+
def daemonize pid_path, log_path, user, group, chdir
|
12
|
+
Dir.chdir(chdir) if chdir
|
13
|
+
|
14
|
+
user ||= Etc.getpwuid(Process.uid).name
|
15
|
+
group ||= Etc.getpwuid(Process.gid).name
|
16
|
+
|
17
|
+
Daemon.change_privilege(user, group)
|
18
|
+
|
19
|
+
cwd = Dir.pwd
|
20
|
+
::Daemonize.daemonize(log_path)
|
21
|
+
Dir.chdir(cwd)
|
22
|
+
|
23
|
+
Daemon.write_pid(pid_path)
|
24
|
+
|
25
|
+
at_exit{
|
26
|
+
puts "Stopping #{pid_path}..."
|
27
|
+
Daemon.remove_pid(pid_path)
|
28
|
+
}
|
29
|
+
end
|
30
|
+
|
31
|
+
# extracted from thin
|
32
|
+
# Change privileges of the process
|
33
|
+
# to the specified user and group.
|
34
|
+
def change_privilege user, group
|
35
|
+
|
36
|
+
uid, gid = Process.euid, Process.egid
|
37
|
+
target_uid = Etc.getpwnam(user).uid
|
38
|
+
target_gid = Etc.getgrnam(group).gid
|
39
|
+
|
40
|
+
if uid != target_uid || gid != target_gid
|
41
|
+
puts "Changing process privilege to #{user}:#{group}"
|
42
|
+
|
43
|
+
# Change process ownership
|
44
|
+
Process.initgroups(user, target_gid)
|
45
|
+
Process::GID.change_privilege(target_gid)
|
46
|
+
Process::UID.change_privilege(target_uid)
|
47
|
+
end
|
48
|
+
|
49
|
+
rescue Errno::EPERM => e
|
50
|
+
puts "Couldn't change user and group to #{user}:#{group}: #{e}"
|
51
|
+
end
|
52
|
+
|
53
|
+
def write_pid path
|
54
|
+
FileUtils.mkdir_p(File.dirname(path))
|
55
|
+
File.open(path, 'w'){ |f| f.write(Process.pid) }
|
56
|
+
File.chmod(0644, path)
|
57
|
+
end
|
58
|
+
|
59
|
+
def remove_pid path
|
60
|
+
File.delete(path) if File.exist?(path)
|
61
|
+
end
|
62
|
+
|
63
|
+
end # of Daemon
|
64
|
+
end # of AppDeploy
|
@@ -0,0 +1,62 @@
|
|
1
|
+
|
2
|
+
module AppDeploy
|
3
|
+
|
4
|
+
module DaemonCluster
|
5
|
+
module_function
|
6
|
+
def each path
|
7
|
+
config_orig = YAML.load(File.read(path)).inject({}){ |h, kv|
|
8
|
+
k, v = kv
|
9
|
+
h[k.to_sym] = v
|
10
|
+
h
|
11
|
+
}
|
12
|
+
|
13
|
+
config_orig = { :servers => 1,
|
14
|
+
:log => 'log/daemon_cluster.log',
|
15
|
+
:pid => 'tmp/pids/daemon_cluster.pid'
|
16
|
+
}.merge(config_orig)
|
17
|
+
|
18
|
+
config_orig[:servers].times{ |n|
|
19
|
+
config = config_orig.dup
|
20
|
+
|
21
|
+
config[:num] = n
|
22
|
+
config[:pid] = DaemonCluster.pid_path(config, n)
|
23
|
+
config[:log] = DaemonCluster.log_path(config, n)
|
24
|
+
|
25
|
+
args = [:pid, :log, :user, :group, :chdir].map{ |kind|
|
26
|
+
value = config.send(:[], kind)
|
27
|
+
value ? "'#{value}'" : 'nil'
|
28
|
+
}.join(', ')
|
29
|
+
|
30
|
+
init_script = "require 'app-deploy/daemon'; AppDeploy::Daemon.daemonize(#{args});"
|
31
|
+
ruby_opts = "-r rubygems -e \"#{init_script} load('#{config[:script]}')\""
|
32
|
+
|
33
|
+
yield( config, "#{config[:ruby]} #{ruby_opts} #{config[:args]}" )
|
34
|
+
}
|
35
|
+
end
|
36
|
+
|
37
|
+
def start config, cmd
|
38
|
+
puts "Starting ##{config[:num]} #{config[:ruby]} #{config[:script]} #{config[:args]}..."
|
39
|
+
sh cmd
|
40
|
+
puts
|
41
|
+
end
|
42
|
+
|
43
|
+
def pid_path config, number
|
44
|
+
path, script, args = config[:pid], config[:script], config[:args]
|
45
|
+
DaemonCluster.path_with_number(path, script, args, number)
|
46
|
+
end
|
47
|
+
|
48
|
+
def log_path config, number
|
49
|
+
# log should expand path since daemons' working dir is different
|
50
|
+
path, script, args = config[:log], config[:script], config[:args]
|
51
|
+
File.expand_path(DaemonCluster.path_with_number(path, script, args, number))
|
52
|
+
end
|
53
|
+
|
54
|
+
def path_with_number path, script, args, number
|
55
|
+
name = (args ? File.basename("#{script} #{args}") :
|
56
|
+
File.basename(script) ).gsub(/\s+/, '_')
|
57
|
+
|
58
|
+
ext = File.extname(path)
|
59
|
+
path.gsub(/#{ext}$/, ".#{name}.#{number}#{ext}")
|
60
|
+
end
|
61
|
+
end # of DaemonCluster
|
62
|
+
end # of AppDeploy
|
@@ -0,0 +1,18 @@
|
|
1
|
+
|
2
|
+
namespace :app do
|
3
|
+
|
4
|
+
desc 'deploy to master state'
|
5
|
+
task :deploy => 'deploy:default'
|
6
|
+
|
7
|
+
namespace :deploy do
|
8
|
+
desc 'before deploy hook for you to override'
|
9
|
+
task :before
|
10
|
+
|
11
|
+
desc 'after deploy hook for you to override'
|
12
|
+
task :after
|
13
|
+
|
14
|
+
task :default => [:before, 'git:stash',
|
15
|
+
'server:restart', :after]
|
16
|
+
|
17
|
+
end # of deploy
|
18
|
+
end # of app
|
@@ -0,0 +1,20 @@
|
|
1
|
+
|
2
|
+
namespace :app do
|
3
|
+
namespace :merb do
|
4
|
+
|
5
|
+
desc 'start the merb server, default config: config/merb.yml'
|
6
|
+
task :start, [:config] do |t, args|
|
7
|
+
sh "merb #{AppDeploy.extract_config(args[:config] || 'config/merb.yml')}"
|
8
|
+
end
|
9
|
+
|
10
|
+
desc 'stop the merb server'
|
11
|
+
task :stop do
|
12
|
+
sh 'merb -K all'
|
13
|
+
sleep(0.5)
|
14
|
+
end
|
15
|
+
|
16
|
+
desc 'restart the merb server'
|
17
|
+
task :restart => [:stop, :start]
|
18
|
+
|
19
|
+
end # of merb
|
20
|
+
end # of app
|
@@ -0,0 +1,25 @@
|
|
1
|
+
|
2
|
+
namespace :app do
|
3
|
+
namespace :gem do
|
4
|
+
|
5
|
+
desc 'install gems'
|
6
|
+
task :install do
|
7
|
+
AppDeploy.each(:gem){ |dep|
|
8
|
+
puts "Installing #{dep[:gem] || dep[:github_project]}..."
|
9
|
+
AppDeploy.install_gem(dep)
|
10
|
+
}
|
11
|
+
end
|
12
|
+
|
13
|
+
desc 'uninstall gems'
|
14
|
+
task :uninstall do
|
15
|
+
AppDeploy.each(:gem){ |dep|
|
16
|
+
puts "Uninstalling #{dep[:gem] || dep[:github_project]}..."
|
17
|
+
AppDeploy.uninstall_gem(dep)
|
18
|
+
}
|
19
|
+
end
|
20
|
+
|
21
|
+
desc 'reinstall gems'
|
22
|
+
task :reinstall => [:uninstall, :install]
|
23
|
+
|
24
|
+
end # of gem
|
25
|
+
end # of app
|
@@ -0,0 +1,66 @@
|
|
1
|
+
|
2
|
+
namespace :app do
|
3
|
+
|
4
|
+
desc 'generic git cmd walk through all dependency'
|
5
|
+
task :git, [:cmd] do |t, args|
|
6
|
+
cmd = args[:cmd] || 'status'
|
7
|
+
|
8
|
+
puts "Invoking git #{cmd}..."
|
9
|
+
begin
|
10
|
+
sh "git #{cmd}"
|
11
|
+
rescue RuntimeError => e
|
12
|
+
puts e
|
13
|
+
end
|
14
|
+
|
15
|
+
AppDeploy.each(:github){ |opts|
|
16
|
+
puts "Invoking git #{cmd} on #{opts[:github_project]}..."
|
17
|
+
begin
|
18
|
+
sh "git #{cmd}"
|
19
|
+
rescue RuntimeError => e
|
20
|
+
puts e
|
21
|
+
end
|
22
|
+
}
|
23
|
+
|
24
|
+
end
|
25
|
+
|
26
|
+
namespace :git do
|
27
|
+
|
28
|
+
task :reset => :stash
|
29
|
+
|
30
|
+
desc 'make anything reflect master state'
|
31
|
+
task :stash do
|
32
|
+
puts 'Stashing...'
|
33
|
+
sh 'git stash'
|
34
|
+
end
|
35
|
+
|
36
|
+
desc 'init and update submodule'
|
37
|
+
task :submodule do
|
38
|
+
sh 'git submodule init'
|
39
|
+
sh 'git submodule update'
|
40
|
+
end
|
41
|
+
|
42
|
+
desc 'clone repoitory from github'
|
43
|
+
task :clone do
|
44
|
+
AppDeploy.github.each{ |dep|
|
45
|
+
puts "Cloning #{dep[:github_project]}..."
|
46
|
+
AppDeploy.clone(dep)
|
47
|
+
}
|
48
|
+
end
|
49
|
+
|
50
|
+
desc 'pull anything from origin'
|
51
|
+
task :pull do
|
52
|
+
puts 'Pulling...'
|
53
|
+
begin
|
54
|
+
sh 'git pull' if `git remote` =~ /^origin$/
|
55
|
+
rescue RuntimeError => e
|
56
|
+
puts e
|
57
|
+
end
|
58
|
+
|
59
|
+
AppDeploy.each(:github){ |opts|
|
60
|
+
puts "Pulling #{opts[:github_project]}..."
|
61
|
+
sh 'git pull'
|
62
|
+
}
|
63
|
+
end
|
64
|
+
|
65
|
+
end # of git
|
66
|
+
end # of app
|
@@ -0,0 +1,84 @@
|
|
1
|
+
|
2
|
+
namespace :app do
|
3
|
+
|
4
|
+
desc 'install this application'
|
5
|
+
task :install => 'install:default'
|
6
|
+
|
7
|
+
namespace :install do
|
8
|
+
desc 'before install hook for you to override'
|
9
|
+
task :before
|
10
|
+
|
11
|
+
desc 'after install hook for you to override'
|
12
|
+
task :after
|
13
|
+
|
14
|
+
task :default => [:before,
|
15
|
+
'git:submodule',
|
16
|
+
'git:clone',
|
17
|
+
'gem:install',
|
18
|
+
:after]
|
19
|
+
|
20
|
+
desc 'remote installation'
|
21
|
+
task :remote, [:hosts, :git, :cd, :branch, :script] => 'remote:default'
|
22
|
+
|
23
|
+
namespace :remote do
|
24
|
+
task :default, [:hosts, :git, :cd, :branch, :script] do |t, args|
|
25
|
+
unless [args[:hosts], args[:git]].all?
|
26
|
+
puts 'please fill your arguments like:'
|
27
|
+
puts " > rake app:install:remote[#{args.names.join(',').upcase}]"
|
28
|
+
exit(1)
|
29
|
+
end
|
30
|
+
|
31
|
+
cd = args[:cd] || '~'
|
32
|
+
branch = args[:branch] || 'master'
|
33
|
+
tmp = "app-deploy-#{Time.now.to_i}"
|
34
|
+
|
35
|
+
chdir = "cd #{cd}"
|
36
|
+
clone = "git clone #{args[:git]} /tmp/#{tmp}"
|
37
|
+
setup = "find /tmp/#{tmp} -maxdepth 1 '!' -name #{tmp} -exec mv -f '{}' #{cd} ';'"
|
38
|
+
rmdir = "rmdir /tmp/#{tmp}"
|
39
|
+
check = "git checkout #{branch}"
|
40
|
+
|
41
|
+
ENV['script'] =
|
42
|
+
"#{chdir}; #{clone}; #{setup}; #{rmdir}; #{check}; #{args[:script]}"
|
43
|
+
|
44
|
+
Rake::Task['app:install:remote:sh'].invoke
|
45
|
+
end
|
46
|
+
|
47
|
+
desc 'invoke a shell script on remote machines'
|
48
|
+
task :sh, [:hosts, :script] do |t, args|
|
49
|
+
args[:hosts].split(',').map{ |host|
|
50
|
+
script = args[:script].gsub('"', '\\"')
|
51
|
+
Thread.new{ sh "ssh #{host} \"#{script}\"" }
|
52
|
+
}.each(&:join)
|
53
|
+
end
|
54
|
+
|
55
|
+
desc 'upload a file to remote machines'
|
56
|
+
task :upload, [:file, :hosts, :path] do |t, args|
|
57
|
+
args[:hosts].split(',').each{ |host|
|
58
|
+
sh "scp #{args[:file]} #{host}:#{args[:path]}"
|
59
|
+
}
|
60
|
+
end
|
61
|
+
|
62
|
+
desc 'create a user on remote machines'
|
63
|
+
task :useradd, [:user, :hosts, :script] do |t, args|
|
64
|
+
useradd = "sudo useradd -m #{args[:user]}"
|
65
|
+
args[:hosts].split(',').each{ |host|
|
66
|
+
script = "#{useradd}; #{args[:script]}".gsub('"', '\\"')
|
67
|
+
sh "ssh #{host} \"#{script}\""
|
68
|
+
}
|
69
|
+
end
|
70
|
+
|
71
|
+
desc 'upload a tarball and untar to user home, then useradd'
|
72
|
+
task :setup, [:user, :file, :hosts, :script] do |t, args|
|
73
|
+
ENV['path'] = "/tmp/app-deploy-#{Time.now.to_i}"
|
74
|
+
Rake::Task['app:install:remote:upload'].invoke
|
75
|
+
|
76
|
+
ENV['script'] = "sudo -u #{args[:user]} tar -zxf #{ENV['path']}" +
|
77
|
+
" -C /home/#{args[:user]};" +
|
78
|
+
" rm #{ENV['path']}; #{args[:script]}"
|
79
|
+
Rake::Task['app:install:remote:useradd'].invoke
|
80
|
+
end
|
81
|
+
|
82
|
+
end # of remote
|
83
|
+
end # of install
|
84
|
+
end # of app
|
@@ -0,0 +1,31 @@
|
|
1
|
+
|
2
|
+
namespace :app do
|
3
|
+
namespace :nginx do
|
4
|
+
|
5
|
+
desc 'start nginx, default config is config/nginx.conf, nginx is /usr/sbin/nginx'
|
6
|
+
task :start, [:config, :nginx] do |t, args|
|
7
|
+
# TODO: extract pid file path
|
8
|
+
if File.exist?('tmp/pids/nginx.pid')
|
9
|
+
puts "WARN: pid file #{'tmp/pids/nginx.pid'} already exists, ignoring."
|
10
|
+
else
|
11
|
+
sh "#{args[:nginx] || '/usr/sbin/nginx'} -c #{args[:config] || 'config/nginx.conf'}"
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
desc 'reload config'
|
16
|
+
task :reload do
|
17
|
+
# sh 'kill -HUP `cat tmp/pids/nginx.pid`'
|
18
|
+
AppDeploy.hup('tmp/pids/nginx.pid', 'nginx')
|
19
|
+
end
|
20
|
+
|
21
|
+
desc 'stop nginx'
|
22
|
+
task :stop, [:timeout] do |t, args|
|
23
|
+
# sh "kill -TERM `cat tmp/pids/nginx.pid`"
|
24
|
+
AppDeploy.term('tmp/pids/nginx.pid', 'nginx', args[:timeout] || 5)
|
25
|
+
end
|
26
|
+
|
27
|
+
desc 'restart nginx'
|
28
|
+
task :restart => [:stop, :start]
|
29
|
+
|
30
|
+
end # of nginx
|
31
|
+
end # of app
|
@@ -0,0 +1,34 @@
|
|
1
|
+
|
2
|
+
require 'app-deploy/rack_cluster'
|
3
|
+
|
4
|
+
namespace :app do
|
5
|
+
namespace :rack do
|
6
|
+
|
7
|
+
desc 'start the rack cluster'
|
8
|
+
task :start, [:config] do |t, args|
|
9
|
+
path = args[:config] || 'config/rack_cluster.yaml'
|
10
|
+
AppDeploy::RackCluster.each(path){ |config, ruby_opts, rack_opts|
|
11
|
+
AppDeploy::RackCluster.start(config, ruby_opts, rack_opts)
|
12
|
+
}
|
13
|
+
end
|
14
|
+
|
15
|
+
desc 'stop the rack cluster'
|
16
|
+
task :stop, [:config] do |t, args|
|
17
|
+
path = args[:config] || 'config/rack_cluster.yaml'
|
18
|
+
AppDeploy::RackCluster.each(path){ |config, ruby_opts, rack_opts|
|
19
|
+
AppDeploy.term(config[:pid], config[:server])
|
20
|
+
}
|
21
|
+
end
|
22
|
+
|
23
|
+
desc 'restart the rack cluster'
|
24
|
+
task :restart, :config do |t, args|
|
25
|
+
path = args[:config] || 'config/rack_cluster.yaml'
|
26
|
+
AppDeploy::RackCluster.each(path){ |config, ruby_opts, rack_opts|
|
27
|
+
AppDeploy.term(config[:pid], config[:server])
|
28
|
+
AppDeploy::RackCluster.start(config, ruby_opts, rack_opts)
|
29
|
+
sleep(config[:delay]) if config[:delay]
|
30
|
+
}
|
31
|
+
end
|
32
|
+
|
33
|
+
end # of rack
|
34
|
+
end # of app
|
@@ -0,0 +1,79 @@
|
|
1
|
+
|
2
|
+
module AppDeploy
|
3
|
+
|
4
|
+
module RackCluster
|
5
|
+
module_function
|
6
|
+
def each path
|
7
|
+
config_orig = {}
|
8
|
+
rack_opts = AppDeploy.extract_config(path){ |opt, value|
|
9
|
+
case opt
|
10
|
+
when 'environment'
|
11
|
+
"--env #{value}"
|
12
|
+
|
13
|
+
when *%w[server host]
|
14
|
+
config_orig[opt.to_sym] = value
|
15
|
+
"--#{opt} #{value}"
|
16
|
+
|
17
|
+
when *%w[user group chdir servers require rackup daemonize port pid log delay]
|
18
|
+
config_orig[opt.to_sym] = value
|
19
|
+
nil # rack doesn't have this option
|
20
|
+
|
21
|
+
else
|
22
|
+
"--#{opt} #{value}"
|
23
|
+
|
24
|
+
end
|
25
|
+
}
|
26
|
+
|
27
|
+
config_orig = { :servers => 1,
|
28
|
+
:port => 9292,
|
29
|
+
:host => '0.0.0.0',
|
30
|
+
:log => 'log/rack_cluster.log',
|
31
|
+
:pid => 'tmp/pids/rack_cluster.pid',
|
32
|
+
:server => 'mongrel',
|
33
|
+
:rackup => 'config.ru' }.merge(config_orig)
|
34
|
+
|
35
|
+
config_orig[:servers].times{ |n|
|
36
|
+
config = config_orig.dup
|
37
|
+
|
38
|
+
config[:port] += n
|
39
|
+
config[:pid] = RackCluster.pid_path(config[:pid], config[:port])
|
40
|
+
config[:log] = RackCluster.log_path(config[:log], config[:port])
|
41
|
+
|
42
|
+
args = [:pid, :log, :user, :group, :chdir].map{ |kind|
|
43
|
+
value = config.send(:[], kind)
|
44
|
+
value ? "'#{value}'" : 'nil'
|
45
|
+
}.join(', ')
|
46
|
+
|
47
|
+
init_script = "AppDeploy::Daemon.daemonize(#{args})"
|
48
|
+
ruby_opts = "-r rubygems -r app-deploy/daemon -e \"#{init_script}\""
|
49
|
+
|
50
|
+
yield( config, ruby_opts, rack_opts + " --port #{config[:port]}" )
|
51
|
+
}
|
52
|
+
|
53
|
+
end
|
54
|
+
|
55
|
+
def start config, ruby_opts, rack_opts
|
56
|
+
puts "Starting #{config[:server]} on #{config[:host]}:#{config[:port]}..."
|
57
|
+
sh "rackup #{ruby_opts} #{rack_opts} #{config[:rackup]}"
|
58
|
+
puts
|
59
|
+
end
|
60
|
+
|
61
|
+
def pid_path path, port
|
62
|
+
RackCluster.path_with_number(path, port)
|
63
|
+
end
|
64
|
+
|
65
|
+
def log_path path, port
|
66
|
+
# log should expand path since daemons' working dir is different
|
67
|
+
File.expand_path(RackCluster.path_with_number(path, port))
|
68
|
+
end
|
69
|
+
|
70
|
+
# extracted from thin
|
71
|
+
# Add the server port or number in the filename
|
72
|
+
# so each instance get its own file
|
73
|
+
def path_with_number path, number
|
74
|
+
ext = File.extname(path)
|
75
|
+
path.gsub(/#{ext}$/, ".#{number}#{ext}")
|
76
|
+
end
|
77
|
+
|
78
|
+
end # of RackCluster
|
79
|
+
end # of AppDeploy
|
@@ -0,0 +1,30 @@
|
|
1
|
+
|
2
|
+
namespace :app do
|
3
|
+
namespace :signal do
|
4
|
+
|
5
|
+
desc 'invoke command if not running already.'
|
6
|
+
task :start, [:script, :pid] do |t, args|
|
7
|
+
if File.exist?(args[:pid])
|
8
|
+
puts "WARN: pid file #{args[:pid]} already exists, ignoring."
|
9
|
+
else
|
10
|
+
sh args[:script]
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
desc 'send a signal to a process with a pid file'
|
15
|
+
task :kill, [:signal] do |t, args|
|
16
|
+
# sh 'kill -HUP `cat tmp/pids/nginx.pid`'
|
17
|
+
AppDeploy.kill(args[:signal], 'tmp/pids/nginx.pid', 'nginx')
|
18
|
+
end
|
19
|
+
|
20
|
+
desc 'stop nginx'
|
21
|
+
task :stop, [:timeout] do |t, args|
|
22
|
+
# sh "kill -TERM `cat tmp/pids/nginx.pid`"
|
23
|
+
AppDeploy.term('tmp/pids/nginx.pid', 'nginx', args[:timeout] || 5)
|
24
|
+
end
|
25
|
+
|
26
|
+
desc 'restart nginx'
|
27
|
+
task :restart => [:stop, :start]
|
28
|
+
|
29
|
+
end # of nginx
|
30
|
+
end # of app
|
@@ -0,0 +1,13 @@
|
|
1
|
+
|
2
|
+
namespace :app do
|
3
|
+
namespace :thin do
|
4
|
+
|
5
|
+
[:start, :stop, :restart].each{ |name|
|
6
|
+
desc "#{name} the thin cluster"
|
7
|
+
task name, [:config] do |t, args|
|
8
|
+
sh "thin -C #{args[:config] || 'config/thin.yml'} #{name}"
|
9
|
+
end
|
10
|
+
}
|
11
|
+
|
12
|
+
end # of thin
|
13
|
+
end # of app
|
@@ -0,0 +1,189 @@
|
|
1
|
+
|
2
|
+
module AppDeploy
|
3
|
+
module_function
|
4
|
+
def github; @github ||= []; end
|
5
|
+
def dependency opts = {}
|
6
|
+
opts = opts.dup
|
7
|
+
opts[:git_path] ||= opts[:github_project]
|
8
|
+
github << opts.freeze
|
9
|
+
end
|
10
|
+
|
11
|
+
def gem; @gem ||= []; end
|
12
|
+
def dependency_gem opts = {}, &block
|
13
|
+
opts = opts.dup
|
14
|
+
|
15
|
+
if opts[:github_project]
|
16
|
+
opts[:git_path] ||= opts[:github_project]
|
17
|
+
opts[:task_gem] = block if block_given?
|
18
|
+
github << opts.freeze
|
19
|
+
end
|
20
|
+
|
21
|
+
gem << opts.freeze
|
22
|
+
end
|
23
|
+
|
24
|
+
def each *with
|
25
|
+
# yield common gem first, github gem last
|
26
|
+
with = [:gem, :github] if with.empty?
|
27
|
+
cwd = Dir.pwd
|
28
|
+
|
29
|
+
# github's gem would be in @github and @gem,
|
30
|
+
# so call uniq to ensure it wouldn't get called twice.
|
31
|
+
with.map{ |kind| AppDeploy.send(kind) }.flatten.uniq.each{ |opts|
|
32
|
+
puts
|
33
|
+
|
34
|
+
if opts[:github_project]
|
35
|
+
if File.directory?(opts[:git_path])
|
36
|
+
begin
|
37
|
+
Dir.chdir(opts[:git_path])
|
38
|
+
yield(opts)
|
39
|
+
rescue RuntimeError => e
|
40
|
+
puts e
|
41
|
+
ensure
|
42
|
+
Dir.chdir(cwd)
|
43
|
+
end
|
44
|
+
else
|
45
|
+
puts "Skip #{opts[:github_project]}, because it was not found"
|
46
|
+
end
|
47
|
+
else # it's a plain gem
|
48
|
+
yield(opts)
|
49
|
+
end
|
50
|
+
}
|
51
|
+
end
|
52
|
+
|
53
|
+
def extract_config config
|
54
|
+
require 'yaml'
|
55
|
+
YAML.load(File.read(config)).inject([]){ |result, opt_value|
|
56
|
+
opt, value = opt_value
|
57
|
+
if block_given?
|
58
|
+
result << yield(opt, value)
|
59
|
+
else
|
60
|
+
result << "--#{opt} #{value}"
|
61
|
+
end
|
62
|
+
result
|
63
|
+
}.compact.join(' ')
|
64
|
+
end
|
65
|
+
|
66
|
+
# about git
|
67
|
+
def clone opts
|
68
|
+
user, proj, path = opts[:github_user], opts[:github_project], opts[:git_path]
|
69
|
+
|
70
|
+
if File.exist?(path)
|
71
|
+
puts "Skip #{proj} because #{path} exists"
|
72
|
+
else
|
73
|
+
sh "git clone git://github.com/#{user}/#{proj}.git #{path}"
|
74
|
+
sh "git --git-dir #{path}/.git gc"
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
# about gem
|
79
|
+
def installed_gem? gem_name
|
80
|
+
# `#{gem_bin} list '^#{gem_name}$'` =~ /^#{gem_name}/
|
81
|
+
Gem.send(:gem, gem_name)
|
82
|
+
true
|
83
|
+
rescue LoadError
|
84
|
+
false
|
85
|
+
end
|
86
|
+
|
87
|
+
def install_gem opts
|
88
|
+
gem_name = opts[:gem] || opts[:github_project]
|
89
|
+
|
90
|
+
if AppDeploy.installed_gem?(gem_name)
|
91
|
+
puts "Skip #{gem_name} because it was installed. Uninstall first if you want to reinstall"
|
92
|
+
|
93
|
+
else
|
94
|
+
if opts[:gem]
|
95
|
+
AppDeploy.install_gem_remote(opts[:gem], opts[:source])
|
96
|
+
else
|
97
|
+
AppDeploy.install_gem_local(opts[:github_project], opts[:task_gem])
|
98
|
+
end
|
99
|
+
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
def uninstall_gem opts
|
104
|
+
gem_name = opts[:gem] || opts[:github_project]
|
105
|
+
if AppDeploy.installed_gem?(gem_name)
|
106
|
+
sh "#{gem_bin} uninstall #{gem_name}"
|
107
|
+
else
|
108
|
+
puts "Skip #{gem_name} because it was not installed"
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
def install_gem_remote gem_name, source = nil
|
113
|
+
sh "#{gem_bin} install #{gem_name}#{source ? ' --source ' + source : ''}"
|
114
|
+
end
|
115
|
+
|
116
|
+
def install_gem_local proj, task
|
117
|
+
case task
|
118
|
+
when 'bones'
|
119
|
+
sh 'rake clobber'
|
120
|
+
sh 'rake gem:package'
|
121
|
+
sh "#{gem_bin} install --local pkg/#{proj}-*.gem --no-ri --no-rdoc"
|
122
|
+
|
123
|
+
when 'hoe'
|
124
|
+
sh 'rake gem'
|
125
|
+
sh "#{gem_bin} install --local pkg/#{proj}-*.gem --no-ri --no-rdoc"
|
126
|
+
|
127
|
+
when Proc
|
128
|
+
task.call
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
def gem_bin
|
133
|
+
Gem.ruby + ' ' + `which gem`.strip
|
134
|
+
end
|
135
|
+
|
136
|
+
# about sending signal
|
137
|
+
def read_pid pid_path
|
138
|
+
if File.exist?(pid_path)
|
139
|
+
File.read(pid_path).strip.to_i
|
140
|
+
|
141
|
+
else
|
142
|
+
puts "WARN: No pid file found in #{pid_path}"
|
143
|
+
nil
|
144
|
+
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
def term pid_path, name = nil, limit = 5
|
149
|
+
if pid = AppDeploy.read_pid(pid_path)
|
150
|
+
puts "Sending TERM to #{name}(#{pid})..."
|
151
|
+
|
152
|
+
else
|
153
|
+
return
|
154
|
+
|
155
|
+
end
|
156
|
+
|
157
|
+
require 'timeout'
|
158
|
+
begin
|
159
|
+
timeout(limit){
|
160
|
+
while true
|
161
|
+
Process.kill('TERM', pid)
|
162
|
+
sleep(0.1)
|
163
|
+
end
|
164
|
+
}
|
165
|
+
rescue Errno::ESRCH
|
166
|
+
if File.exist?(pid_path)
|
167
|
+
puts "WARN: No such pid: #{pid}, removing #{pid_path}..."
|
168
|
+
File.delete(pid_path)
|
169
|
+
else
|
170
|
+
puts "Killed #{name}(#{pid})"
|
171
|
+
end
|
172
|
+
|
173
|
+
rescue Timeout::Error
|
174
|
+
puts "Timeout(#{limit}) killing #{name}(#{pid})"
|
175
|
+
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
179
|
+
def hup pid_path, name = nil
|
180
|
+
if pid = AppDeploy.read_pid(pid_path)
|
181
|
+
puts "Sending HUP to #{name}(#{pid})..."
|
182
|
+
Process.kill('HUP', pid)
|
183
|
+
end
|
184
|
+
rescue Errno::ESRCH
|
185
|
+
puts "WARN: No such pid: #{pid}, removing #{pid_path}..."
|
186
|
+
File.delete(pid_path)
|
187
|
+
end
|
188
|
+
|
189
|
+
end
|
data/lib/app-deploy.rb
ADDED
metadata
ADDED
@@ -0,0 +1,119 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: app-deploy
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.6.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- "Lin Jen-Shin (aka godfat \xE7\x9C\x9F\xE5\xB8\xB8)"
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2009-12-14 00:00:00 +08:00
|
13
|
+
default_executable:
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: bones
|
17
|
+
type: :development
|
18
|
+
version_requirement:
|
19
|
+
version_requirements: !ruby/object:Gem::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">="
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: 3.2.0
|
24
|
+
version:
|
25
|
+
description: " rake tasks for deployment"
|
26
|
+
email: godfat (XD) godfat.org
|
27
|
+
executables: []
|
28
|
+
|
29
|
+
extensions: []
|
30
|
+
|
31
|
+
extra_rdoc_files:
|
32
|
+
- CHANGES
|
33
|
+
- README
|
34
|
+
- Rakefile
|
35
|
+
- TODO
|
36
|
+
- app-deploy.gemspec
|
37
|
+
- example/Rakefile
|
38
|
+
- example/bin/install.sh
|
39
|
+
- example/bin/remote_install.sh
|
40
|
+
- example/bin/remote_update.sh
|
41
|
+
- example/bin/start.sh
|
42
|
+
- example/bin/update.sh
|
43
|
+
- example/daemon_cluster.yaml
|
44
|
+
- example/rack_cluster.yaml
|
45
|
+
- lib/app-deploy/daemon.rake
|
46
|
+
- lib/app-deploy/deploy.rake
|
47
|
+
- lib/app-deploy/deprecated/merb.rake
|
48
|
+
- lib/app-deploy/deprecated/mongrel.rake
|
49
|
+
- lib/app-deploy/gem.rake
|
50
|
+
- lib/app-deploy/git.rake
|
51
|
+
- lib/app-deploy/install.rake
|
52
|
+
- lib/app-deploy/nginx.rake
|
53
|
+
- lib/app-deploy/rack.rake
|
54
|
+
- lib/app-deploy/server.rake
|
55
|
+
- lib/app-deploy/signal.rake
|
56
|
+
- lib/app-deploy/thin.rake
|
57
|
+
files:
|
58
|
+
- CHANGES
|
59
|
+
- README
|
60
|
+
- Rakefile
|
61
|
+
- TODO
|
62
|
+
- app-deploy.gemspec
|
63
|
+
- example/Rakefile
|
64
|
+
- example/bin/install.sh
|
65
|
+
- example/bin/remote_install.sh
|
66
|
+
- example/bin/remote_update.sh
|
67
|
+
- example/bin/start.sh
|
68
|
+
- example/bin/update.sh
|
69
|
+
- example/daemon_cluster.yaml
|
70
|
+
- example/rack_cluster.yaml
|
71
|
+
- lib/app-deploy.rb
|
72
|
+
- lib/app-deploy/daemon.rake
|
73
|
+
- lib/app-deploy/daemon.rb
|
74
|
+
- lib/app-deploy/daemon_cluster.rb
|
75
|
+
- lib/app-deploy/deploy.rake
|
76
|
+
- lib/app-deploy/deprecated/merb.rake
|
77
|
+
- lib/app-deploy/deprecated/mongrel.rake
|
78
|
+
- lib/app-deploy/gem.rake
|
79
|
+
- lib/app-deploy/git.rake
|
80
|
+
- lib/app-deploy/install.rake
|
81
|
+
- lib/app-deploy/nginx.rake
|
82
|
+
- lib/app-deploy/rack.rake
|
83
|
+
- lib/app-deploy/rack_cluster.rb
|
84
|
+
- lib/app-deploy/server.rake
|
85
|
+
- lib/app-deploy/signal.rake
|
86
|
+
- lib/app-deploy/thin.rake
|
87
|
+
- lib/app-deploy/utils.rb
|
88
|
+
- lib/app-deploy/version.rb
|
89
|
+
has_rdoc: true
|
90
|
+
homepage: http://github.com/godfat/app-deploy
|
91
|
+
licenses: []
|
92
|
+
|
93
|
+
post_install_message:
|
94
|
+
rdoc_options:
|
95
|
+
- --main
|
96
|
+
- README
|
97
|
+
require_paths:
|
98
|
+
- lib
|
99
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: "0"
|
104
|
+
version:
|
105
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
106
|
+
requirements:
|
107
|
+
- - ">="
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: "0"
|
110
|
+
version:
|
111
|
+
requirements: []
|
112
|
+
|
113
|
+
rubyforge_project: app-deploy
|
114
|
+
rubygems_version: 1.3.5
|
115
|
+
signing_key:
|
116
|
+
specification_version: 3
|
117
|
+
summary: rake tasks for deployment
|
118
|
+
test_files: []
|
119
|
+
|