• 查看服务器的系统信息
$ lsb_release -a
LSB Version:	:base-4.0-amd64:base-4.0-noarch:core-4.0-amd64:core-4.0-noarch:graphics-4.0-amd64:graphics-4.0-noarch:printing-4.0-amd64:printing-4.0-noarch
Distributor ID:	CentOS
Description:	CentOS release 6.4 (Final)
Release:	6.4
Codename:	Final
  • Google search “CentOS install nginx”

搜到一篇文章: https://www.digitalocean.com/community/tutorials/how-to-install-nginx-on-centos-6-with-yum 姑且按照此文章介绍的步骤操作下去,

$ sudo yum install epel-release
$ sudo yum install nginx
  • 启动 Nginx
$ sudo /etc/init.d/nginx start

可以通过 ps 命令查看 nginx 是否正常启动,

$ ps aux | grep nginx
root     23497  0.0  0.0  96436  2020 ?        Ss   19:47   0:00 nginx: master process /usr/sbin/nginx -c /etc/nginx/nginx.conf
nginx    23498  0.0  0.0  96824  2668 ?        S    19:47   0:00 nginx: worker process                   

获取服务器 IP:

$ ifconfig eth0 | grep inet | awk '{ print $2 }'
  • 安装 RVM

用 google 搜索 “centos rvm”, 然后搜到一篇文章: https://www.digitalocean.com/community/tutorials/how-to-install-ruby-on-rails-on-centos-6-with-rvm 按照此文章介绍的步骤操作下去,

$ sudo yum update
$ sudo yum install curl
$ curl -L get.rvm.io | bash -s stable

安装的过程中遇到两个警告:

* WARNING: You have RUBYLIB set in your current environment.
    This may cause rubies to not work as you expect them to as it is not supported
    by all of them If errors show up, please try unsetting RUBYLIB first.


  * WARNING: You have '~/.profile' file, you might want to load it,
    to do that add the following line to '/home/itadmin/.bash_profile':

      source ~/.profile

在 ~/.bash_profile 里加入了 source ~/.profile, 对于第一个警告暂时不理会。

接着是 load RVM, 在这里我们不能照搬文章的步骤了:

# If you ran the installer as root, run:
source /usr/local/rvm/rvm.sh
# If you installed it through a user with access to sudo:
source ~/.rvm/rvm.sh

在安装的过程中有一段文字,

Installing RVM to /home/someuser/.rvm/
    Adding rvm PATH line to /home/itadmin/.profile /home/itadmin/.mkshrc /home/someuser/.bashrc /home/someuser/.zshrc.
    Adding rvm loading line to /home/someuser/.profile /home/someuser/.bash_profile /home/someuser/.zlogin.
Installation of RVM in /home/someuser/.rvm/ is almost complete:

  * To start using RVM you need to run `source /home/someuser/.rvm/scripts/rvm`
    in all your open shell windows, in rare cases you need to reopen all shell windows.

注意: 我用 someuser 替代了实际的用户名。

于是加载 RVM 的命令如下,

$ source /home/someuser/.rvm/scripts/rvm

查看 RVM 依赖:

rvm requirements

在我的服务器上显示:

Checking requirements for centos.
Installing requirements for centos.
Installing required packages: libyaml-devel, libffi-devel..itadmin password required for 'yum install -y libyaml-devel libffi-devel':

安装这些依赖(在实际的操作中,我没有使用 rvmsudo, 而是在上面文字的冒号后面直接输入密码就安装好了依赖)

$ rvmsudo yum install -y libyaml-devel libffi-devel
  • 安装 Ruby

我要安装的版本是: 1.9.3p448

$ rvm install 1.9.3-p448

最后我又安装了 1.9.3-p551

$ rvm install 1.9.3-p551

查看安装了哪些 ruby,

$ rvm list

输出,

rvm rubies

 * ruby-1.9.3-p448 [ x86_64 ]
=> ruby-1.9.3-p551 [ x86_64 ]

# => - current
# =* - current && default
#  * - default
  • 安装 RubyGems
$ rvm rubygems current
  • 安装 bundler
$ gem install bundler
  • 克隆项目代码并且安装 gems
$ cd ~
$ mkdir railsapp
$ cd railsapp
$ git clone app_name_git_url
$ cd app_name
$ bundle

bundle install 的过程中出现了错误:

Installing debugger-ruby_core_source 1.2.0
Gem::Ext::BuildError: ERROR: Failed to build gem native extension
An error occurred while installing debugger (1.5.0), and Bundler cannot continue.
Make sure that `gem install debugger -v '1.5.0'` succeeds before bundling.

修复方法:

$ gem install debugger
$ bundle
  • 安装配置 Passenger

使用 google 搜索 “centos passenger”, 按照 https://www.digitalocean.com/community/tutorials/how-to-deploy-rails-apps-using-passenger-with-nginx-on-centos-6-5 写的步骤操作:

$ sudo yum groupinstall -y 'development tools'
$ sudo yum install -y nodejs
$ gem install passenger
$ rvmsudo passenger-install-nginx-module

Nginx 被重新安装到了 /opt/nginx

  • 创建 Nginx 管理脚本
$ nano /etc/rc.d/init.d/nginx
#!/bin/sh
. /etc/rc.d/init.d/functions
. /etc/sysconfig/network
[ "$NETWORKING" = "no" ] && exit 0

nginx="/opt/nginx/sbin/nginx"
prog=$(basename $nginx)

NGINX_CONF_FILE="/opt/nginx/conf/nginx.conf"

lockfile=/var/lock/subsys/nginx

start() {
    [ -x $nginx ] || exit 5
    [ -f $NGINX_CONF_FILE ] || exit 6
    echo -n $"Starting $prog: "
    daemon $nginx -c $NGINX_CONF_FILE
    retval=$?
    echo
    [ $retval -eq 0 ] && touch $lockfile
    return $retval
}

stop() {
    echo -n $"Stopping $prog: "
    killproc $prog -QUIT
    retval=$?
    echo
    [ $retval -eq 0 ] && rm -f $lockfile
    return $retval
}

restart() {
    configtest || return $?
    stop
    start
}

reload() {
    configtest || return $?
    echo -n $”Reloading $prog: ”
    killproc $nginx -HUP
    RETVAL=$?
    echo
}

force_reload() {
    restart
}

configtest() {
    $nginx -t -c $NGINX_CONF_FILE
}

rh_status() {
    status $prog
}

rh_status_q() {
    rh_status >/dev/null 2>&1
}

case "$1" in
start)
rh_status_q && exit 0
$1
;;
stop)
rh_status_q || exit 0
$1
;;
restart|configtest)
$1
;;
reload)
rh_status_q || exit 7
$1
;;
force-reload)
force_reload
;;
status)
rh_status
;;
condrestart|try-restart)
rh_status_q || exit 0
;;
*)
echo $"Usage: $0 {start|stop|status|restart|condrestart|try-restart|reload|force-reload|configtest}"
exit 2
esac

启动 Nginx

$ /etc/rc.d/init.d/nginx start
  • 配置 capfile
$ sudo chown myuser /var/www
$ mkdir -p /var/www/staging/shared
$ mkdir -p /var/www/staging/releases

capfile 内容如下:


default_run_options[:pty] = true  
set :application, "My Site"
set :repository,  "git@github.com:My/site"
require 'bundler/capistrano'
set :scm, :git
set :user, "myuser"
ssh_options[:forward_agent] = true
set :branch, "staging"
set :keep_releases, 10
set :use_sudo, false

set :deploy_to, "/var/www"
set :deploy_via, :remote_cache

server "localhost", :app, :web
set :shared, %w{
  config/database.yml
  log
  public/data
  public/assets
  public/files
  public/company_documents
}
after "deploy:setup", "deploy:steup_settings_local_yml"
before "deploy:update", "god:terminate_if_running"
after "deploy:update", "god:start"
after 'deploy:create_symlink', 'deploy:create_my_symlink'
after "deploy:restart", "deploy:cleanup"#, "deploy:copy_resque_assets"

# If you are using Passenger mod_rails uncomment this:
# if you're still using the script/reapear helper you will need
# these http://github.com/rails/irs_process_scripts

namespace :deploy do
#   task :start {}
#   task :stop {}
#   task :restart, :roles => :app, :except => { :no_release => true } do
#     run "#{try_sudo} touch #{File.join(current_path,'tmp','restart.txt')}"
#   end
  desc 'restart passenger'
  task :restart do
    run "touch #{current_path}/tmp/restart.txt"
    run 'curl -k https://localhost/distributor_contact?login=master'
    run 'curl -k https://localhost/distributor_contact?login=master'
    run 'curl -k https://localhost/distributor_contact?login=master'
    run 'curl -k https://localhost/distributor_contact?login=master'
    run 'curl -k https://localhost/distributor_contact?login=master'
    run 'curl -k https://localhost/distributor_contact?login=master'
    run 'curl -k https://localhost/distributor_contact?login=master'
    run 'curl -k https://localhost/distributor_contact?login=master'
  end
  
  desc "Symlinks"
  task :create_my_symlink, :roles => :app do
    run "ln -nfs #{deploy_to}/shared/config/avalara.yml #{release_path}/config/avalara.yml"
    run "ln -nfs #{deploy_to}/shared/config/ipay88.yml #{release_path}/config/ipay88.yml"
    run "ln -nfs #{deploy_to}/shared/config/couch.yml #{release_path}/config/couch.yml"
    run "ln -nfs #{deploy_to}/shared/config/hyperwallet.yml #{release_path}/config/hyperwallet.yml"
    run "ln -nfs #{deploy_to}/shared/config/uniteller.yml #{release_path}/config/uniteller.yml"
    run "ln -nfs #{deploy_to}/shared/config/captcha.yml #{release_path}/config/captcha.yml"
    run "ln -nfs #{deploy_to}/shared/config/ipay88.yml #{release_path}/config/ipay88.yml"
    run "ln -nfs #{deploy_to}/shared/config/paynamics_wpf.yml #{release_path}/config/paynamics_wpf.yml"
    run "ln -nfs #{deploy_to}/shared/config/mongoid.yml #{release_path}/config/mongoid.yml"
    run "ln -nfs #{deploy_to}/shared/config/database.yml #{release_path}/config/database.yml"
    run "ln -nfs #{deploy_to}/shared/config/redis_store.yml #{release_path}/config/redis_store.yml"
    run "ln -nfs #{deploy_to}/shared/config/settings.local.yml #{release_path}/config/settings.local.yml"
    run "ln -nfs #{deploy_to}/shared/public/data #{release_path}/public/data"
    run "ln -nfs #{deploy_to}/shared/images/oglogo.png #{release_path}/public/images/oglogo.png"
    run "ln -nfs #{deploy_to}/shared/public/company_documents #{release_path}/public/company_documents"
    run "ln -nfs #{deploy_to}/shared/public/assets #{release_path}/public/assets"
    run "ln -nfs #{deploy_to}/shared/public/files #{release_path}/public/files"
    run "ln -nfs #{deploy_to}/shared/public/star_achiever #{release_path}/public/star_achiever"
    run "ln -nfs #{deploy_to}/shared/reports #{release_path}/reports"
  end

  desc 'setup settings.local.yml'
  task :steup_settings_local_yml, :roles => :app do
    put File.read("config/settings.local.yml"), "#{shared_path}/config/settings.local.yml"
  end

  desc "Copy resque-web assets into public folder"
  task :copy_resque_assets do
    target = File.join(release_path, 'public', 'resque')
    run "cp -r #{`cd #{release_path} && bundle show resque`.chomp}/lib/resque/server/public #{target}"
  end
end

namespace :god do

  def god_is_running
    !capture("#{god_command} status >/dev/null 2>/dev/null || echo 'not running'").start_with?('not running')
  end

  def god_command
    "cd #{current_path}; bundle exec god"
  end

  desc "Stop god"
  task :terminate_if_running do
    if god_is_running
      run "#{god_command} terminate"
    end
  end

  desc "Start god"
  task :start do
    config_file = "#{current_path}/csite/god/resque.god"
    environment = { :RAILS_ENV => rails_env, :RAILS_ROOT => current_path }
    run "#{god_command} -c #{config_file}", :env => environment
  end
end

  • 启动应用
$ cap deploy

这个笔记是流水帐的记法属于做到哪写到哪的风格,所以看起来有些凌乱,现在对其做一个梳理提炼。

首先声明一个约定,我使用 myuser 作为实际用户的别名, mysite 作为实际站点的别名。

1. 确认部署蓝图

  • 服务器: CentOS
  • web 服务器: Nginx
  • 应用服务器: Passenger
  • Ruby 版本管理器: RVM
  • 部署工具: Capistrano

2. 安装系统相关软件和库

$ sudo yum update
$ sudo yum install epel-release
$ sudo yum install curl
$ sudo yum groupinstall -y 'development tools'
$ sudo yum install -y nodejs

安装配置 RVM

$ curl -L get.rvm.io | bash -s stable

这里可能会出现警告,根据安装过程中输出的提示操作即可。

加载 RVM

$ source /home/myuser/.rvm/scripts/rvm

查看 RVM 依赖

$ rvm requirements

如果提示需要安装某些库,直接敲 Enter 键安装即可,

Checking requirements for centos.
Installing requirements for centos.
Installing required packages: libyaml-devel, libffi-devel..itadmin password required for 'yum install -y libyaml-devel libffi-devel':

安装 Ruby

安装你需要的 ruby 版本即可, 我使用的是 1.9.3-p551,

$ rvm install 1.9.3-p551

安装 RubyGems 和 Bundler

$ rvm rubygems current

$ gem install bundler

克隆项目并且安装 gems

$ cd ~

$ mkdir railsapp

$ cd railsapp

$ git clone app_name_git_url

$ cd app_name

$ bundle install

安装配置 Passenger

$ gem install passenger

$ rvmsudo passenger-install-nginx-module

Nginx 被安装到了 /opt/nginx 目录。

Nginx 的管理脚本在 /etc/rc.d/init.d/nginx

Nginx 的配置文件在 /opt/nginx/conf/nginx.conf

在这里我贴出 Nginx 的配置文件, 有两个, 第一个是 /opt/nginx/conf/nginx.conf,

worker_processes  4;

error_log  /opt/nginx/logs/error.log;

pid       /var/run/nginx.pid;

events {
    worker_connections  1024;
}

http {
    proxy_set_header   X-Forwarded-For  $proxy_add_x_forwarded_for;
    passenger_root /home/myuser/.rvm/gems/ruby-1.9.3-p551/gems/passenger-5.0.5;
    passenger_ruby /home/myuser/.rvm/gems/ruby-1.9.3-p551/wrappers/ruby;
    passenger_max_pool_size 30;
    passenger_pool_idle_time 90;
    passenger_max_requests 500;
    client_max_body_size 20M;
    include       /opt/nginx/conf/mime.types;
    default_type  application/octet-stream;

    access_log  /opt/nginx/logs/access.log;
    sendfile        on;

    keepalive_timeout  65;
    gzip  on;
    gzip_disable "MSIE [1-6]\.(?!.*SV1)";
    gzip_http_version 1.0;
    gzip_comp_level 2;
    gzip_proxied any;
    gzip_types text/plain text/css application/x-javascript text/xml application/xml application/xml+rss text/javascript;


    include /opt/nginx/conf/sites-enabled/localhost;

    ssl_ciphers RC4:HIGH:!aNULL:!MD5:!kEDH;
    ssl_protocols SSLv3 TLSv1 TLSv1.1 TLSv1.2;
    ssl_prefer_server_ciphers on;
}

    # 这些都是和 Passenger 相关的。
    passenger_root /home/myuser/.rvm/gems/ruby-1.9.3-p551/gems/passenger-5.0.5;
    passenger_ruby /home/myuser/.rvm/gems/ruby-1.9.3-p551/wrappers/ruby;
    passenger_max_pool_size 30;
    passenger_pool_idle_time 90;
    passenger_max_requests 500;

第二个文件是 /opt/nginx/conf/sites-enabled/localhost, 这个文件里包含实际站点的配置内容,

server {
  listen 443;
  server_name notforpublic.mysite.com www.mysite.com;
  proxy_set_header X-Forwarded-Proto https;

  ssl on;
  ssl_certificate /etc/ssl/certs/demo.mysite.com.crt; 
  ssl_certificate_key /etc/ssl/certs/demo.mysite.com.key.pem; 

  access_log   logs/organogold443.access.log;
  root   /var/www/current/public;

  location /distributor_contact {
     return 200 "{}";
     access_log off;
  }

  passenger_enabled on;

  rails_env production;
    passenger_max_preloader_idle_time 0;
  location ~ /\.ht {
          deny  all;
  }

}


server {
  listen 9449;
  server_name notforpublic.mysite.com
  proxy_set_header X-Forwarded-Proto https;

  ssl on;
  ssl_certificate /etc/ssl/certs/demo.mysite.com.crt; 
  ssl_certificate_key /etc/ssl/certs/demo.mysitecom.key.pem; 
  access_log   logs/organogold7443.access.log;
  root   /var/www/staging/current/public;

  passenger_enabled on;

  rails_env production;
  passenger_max_preloader_idle_time 0;

}

  # 这些都是和 Passenger 相关的。
  passenger_enabled on;
  rails_env production;

配置 Capfile

Capfile 是跟着项目走的, 其中的内容已经在流水帐里贴出了。

创建部署目录以及相关目录, 具体创建哪些目录需要看 config/deploy 文件里的配置

$ sudo mkdir /var/www

$ chown myuser /var/www

$ mkdir /var/www/staging

$ mkdir /var/www/staging/shared

$ cp -r /path/to/shared /var/www/staging/shared

$ mkdir /var/www/staging/releases

启动项目,

$ cd /home/myuser/railsapp/app_name
$ cap deploy