$:.unshift File.expand_path(File.join(File.dirname(__FILE__),'..','unix-like')) require 'optparse' require 'rho_connect_install_constants' require 'fileutils' options = {} optparse = OptionParser.new do |opts| options[:dist] = nil opts.on( '-d', '--dist DISTRO', 'Specify DISTRO as the current distribution.' ) do |dist| options[:dist] = dist end #do options[:prefix] = '/opt/rhoconnect' opts.on( '-p', '--prefix RHODIR', 'Specify RHODIR as the prefix directory.' ) do |dir| options[:prefix] = dir end #do options[:redis] = true opts.on( '--no-redis', '', 'Skip installing the redis server.' ) do options[:redis] = false end #do options[:rubyVersion] = 'rubyee' opts.on( '-r', '--rubyVer VERSION', 'Specify VERSION as the verion of ruby that is installed.' ) do |rubyVer| options[:rubyVersion] = rubyVer end #do options[:web_server] = "nginx" opts.on('-w', '--web-server Server', ' Specify that you are using web server SERVER') do |server| options[:web_server] = server end #do opts.on('-l', '--Logfile file', ' Specify installtion log file') do |file| options[:log_file] = file end #do end #do optparse.parse! @prefix = options[:prefix] @dist = options[:dist] @redis = options[:redis] @ruby_version = options[:rubyVersion] @profile = (@dist == 'debian') ? '~/.profile' : '~/.bash_profile' @server = options[:web_server] @log_file = options[:log_file] @passenger_root = Constants::PASSENGER_ROOT def passenger_version (`#{@prefix}/bin/passenger --version`.match /\d+\.\d+\.\d+/)[0] end # create_redis_init # Creates the redis initialization file and places it into the correct directory def create_redis_init redis_init_script = <<'_REDIS_INIT_SCRIPT_' #!/usr/bin/env bash ### BEGIN INIT INFO # Provides: redis-server # Required-Start: $syslog # Required-Stop: $syslog # Should-Start: $local_fs # Should-Stop: $local_fs # Default-Start: 2 3 4 5 # Default-Stop: 0 1 6 # Short-Description: redis-server - Persistent key-value db # Description: redis-server - Persistent key-value db ### END INIT INFO # # Author: Wayne E. Seguin # License: The same licence as Redis, New BSD # http://www.opensource.org/licenses/bsd-license.php # # Source the system config file, if it exists. if [[ -s /etc/conf.d/redis ]] ; then source /etc/conf.d/redis fi # Default config variables that have not been set. port="${port:-6379}" prefix="${prefix:-/opt/rhoconnect}" redis="${prefix}/bin/redis-server" redis_cli="${prefix}/bin/redis-cli" pidfile="${pidfile:-/var/run/redis.pid}" config="${config:-/opt/rhoconnect/etc/redis.conf}" user="${user:-root}" #prefix="${prefix:-/usr/local}" #config="${config:-/usr/local/etc/redis.conf}" #pidfile="${pidfile:-/var/run/redis/redis.pid}" #config="${config:-/etc/redis/redis.conf}" #user="${user:-redis}" # If the redis-cli file is not found, terminate the script. test -x $redis_cli || exit 0 # # Set the running $pid value based on $pidfile. # if [[ -s "$pidfile" ]] ; then pid=$(cat $pidfile) else rm -f $pidfile fi # In case there was pidfile corruption... if [[ "Linux" = "$(uname)" ]] ; then # /proc does not exist on say, Darwin if [[ ! -z "${pid}" ]] && [[ ! -x "/proc/${pid}" ]] ;then pid="$(ps auxww | grep [r]edis | grep "$config" | grep -v 'grep' | awk '{print $2}')" elif [[ -z "${pid}" ]] ; then pid="$(ps auxww | grep [r]edis | grep "$config" | grep -v 'grep' | awk '{print $2}')" fi else if [[ -z "${pid}" ]] ; then pid="$(ps auxww | grep [r]edis | grep "$config" | grep -v 'grep' | awk '{print $2}')" fi fi # # Start redis using redis-server as user 'redis'. # redis_start() { if [[ -f $pidfile ]] ; then echo "$pidfile exists, redis-server is either already running or crashed." exit 1 elif [[ ! -z "$pid" ]] ; then echo -e "\nRedis is already running with configuration '$config'." echo "$pid" > $pidfile # Ensure pidfile exists with the pid. else echo "Starting Redis server..." su $user -c "$redis $config" exit 0 fi } # # Stop redis using redis-cli SHUTDOWN. # redis_stop() { echo -n "Stopping redis server on port ${port} ... " "$redis_cli" -p ${port} SHUTDOWN # Keep user informed while server shuts down. echo "Waiting for the redis server to shutdown " if [[ "Linux" = "$(uname)" ]] ; then if [[ "${pid}" = "" ]] ; then echo "redis server is not running." # Clear out the old pidfile if available rm -f $pidfile exit 1 fi while [[ -x /proc/${pid} ]] ; do echo -n '.' ; sleep 1 done else # Darwin, etc ... while [[ ! -z "$(ps auxww | grep [r]edis | grep "$config" | grep -v grep | awk '{print $2}')" ]] ; do echo -n '.' ; sleep 1 done fi # Clear out the old pidfile. rm -f $pidfile # Notify user of successful completion. echo -e "redis server stopped." exit 0 } redis_usage() { echo -e "Usage: $0 {start,stop,restart,status}" exit 1 } redis_status() { "$redis_cli" -p ${port} INFO > /dev/null 2>&1 info=$? if (( $info )) ; then echo "Redis server not running"; else echo "Redis server running"; fi exit $info } # # CLI logic. # case "$1" in start) redis_start ;; stop) redis_stop ;; restart) $0 stop $0 start ;; status) redis_status ;; *) redis_usage ;; esac _REDIS_INIT_SCRIPT_ redisInit="/etc/init.d/redis" File.open(redisInit, 'w') { |f| f << redis_init_script } # Make the init script executable `chmod +x #{redisInit}` # Set run levels if @dist == 'debian' `update-rc.d -f redis defaults` else `/sbin/chkconfig redis on` # `/sbin/chkconfig --list redis` end redis_init_script end #create_redis_init def create_redis_logrotate redis_logrotate_conf = <<'_REDIS_LOGRORATE_CONF_' /var/log/redis.log { rotate 3 missingok notifempty size 250k create 0644 root root compress } _REDIS_LOGRORATE_CONF_ File.open('/etc/logrotate.d/redis', 'w') { |f| f << redis_logrotate_conf } end # # Nginx stuff ... def create_nginx_init nginx_init_script = <<'_NGINX_INIT_SCRIPT_' #!/bin/sh # Author: Ryan Norbauer http://norbauerinc.com # Modified: Geoffrey Grosenbach http://topfunky.com # Modified: Clement NEDELCU # Modified: Alexander Babichev # Reproduced with express authorization from its contributors PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin DESC="nginx daemon" NAME=nginx DAEMON=/opt/nginx/sbin/$NAME SCRIPTNAME=/etc/init.d/$NAME # If the daemon file is not found, terminate the script. test -x $DAEMON || exit 0 d_start() { $DAEMON || echo -n " already running" } d_stop() { $DAEMON -s quit || echo -n " not running" } d_reload() { $DAEMON -s reload || echo -n " could not reload" } case "$1" in start) echo -n "Starting $DESC: $NAME" d_start echo "." ;; stop) echo -n "Stopping $DESC: $NAME" d_stop echo "." ;; reload) echo -n "Reloading $DESC configuration ... " d_reload echo "reloaded." ;; restart) echo -n "Restarting $DESC: $NAME" d_stop # Sleep for two seconds before starting again, this should give the # Nginx daemon some time to perform a graceful stop. sleep 2 d_start echo "." ;; *) echo "Usage: $SCRIPTNAME {start|stop|restart|reload}" >&2 exit 3 ;; esac exit 0 _NGINX_INIT_SCRIPT_ nginx_script = '/etc/init.d/nginx' File.open(nginx_script, 'w') { |f| f << nginx_init_script } # Make the init script executable `chmod +x #{nginx_script}` # Set run levels # if @dist == 'debian' # #`update-rc.d -f nginx defaults` # else # #`/sbin/chkconfig nginx on` # end end def create_nginx_logrotate nginx_logrorate_conf = <<'_NGINX_LOGRORATE_CONF_' /opt/nginx/logs/*log { missingok notifempty rotate 4 size 100k delaycompress sharedscripts postrotate test ! -f /opt/nginx/logs/nginx.pid || kill -USR1 `cat /opt/nginx/logs/nginx.pid` endscript } _NGINX_LOGRORATE_CONF_ File.open('/etc/logrotate.d/nginx', 'w') { |f| f << nginx_logrorate_conf } end def create_nginx_conf_files(app_name) nginx_server_conf = <<'_NGINX_CONF_' user nginx; worker_processes 4; error_log logs/error.log; pid logs/nginx.pid; events { worker_connections 1024; } http { include mime.types; default_type application/octet-stream; sendfile on; keepalive_timeout 65; #gzip on; include /opt/nginx/conf/conf.d/*.conf; } _NGINX_CONF_ # create 'nginx' user if it does not exist user_nginx = `cat /etc/passwd | cut -d: -f1 | grep nginx` if user_nginx.empty? puts "Creating 'nginx' user ..." if @dist == 'debian' `adduser --system --home /opt/nginx/html --no-create-home --disabled-login --disabled-password --group nginx` else `/usr/sbin/useradd -M -r -s /sbin/nologin -d /opt/nginx/html nginx` end end FileUtils.mv("/opt/nginx/conf/nginx.conf", "/opt/nginx/conf/nginx.conf.bak") unless File.exist? "/opt/nginx/conf/nginx.conf.bak" File.open('/opt/nginx/conf/nginx.conf', 'w' ) { |f| f << nginx_server_conf } Dir.mkdir "/opt/nginx/conf/conf.d" unless File.exist? "/opt/nginx/conf/conf.d" rho_vhost_conf = <<_VHOST_CONF_ upstream thin_cluster { server unix:/tmp/thin.sock; #server unix:/tmp/thin.0.sock; #server unix:/tmp/thin.1.sock; #server unix:/tmp/thin.2.sock; #server unix:/tmp/thin.3.sock; } server { listen 80; root /opt/nginx/html/#{app_name}/public; # <-- be sure to point to 'public' folder of your application! # access_log off; # <-- disable access logging # error_log /dev/null crit; # <-- disable error logging, but critical errors only location / { proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Host $http_host; proxy_redirect off; proxy_pass http://thin_cluster; } error_page 500 502 503 504 /50x.html; location = /50x.html { root html; } } _VHOST_CONF_ File.open('/opt/nginx/conf/conf.d/rhoconnect.conf', 'w' ) { |f| f << rho_vhost_conf } end # End of nginx stuff ... # generate_common_info # Generates the readme info that is common across all distributions def generate_common_info readme = <<_README_ Thank you for choosing Rhoconnect for your mobile app sync needs! To finish this setup, please complete the following... 1) Add necessary bins to the path(s) of the users who will be using this software. You may also wish to add these items to your #{@profile} to automatically add them upon login. export PATH=#{@prefix}/bin:$PATH If you had other versions of ruby installed previously to running this installation, you may instead wish to simply create an alias for the newly installed ruby: alias #{@ruby_version}=#{@prefix}/bin/ruby _README_ if @dist == "yum" rpm_lib = <<_RPM_LIB_ Add #{@prefix}/lib to your library path like so: export LD_LIBRARY_PATH=#{@prefix}/lib:$LD_LIBRARY_PATH Note: You may also want to add this line to #{@profile} _RPM_LIB_ # concatenate _RPM_LIB_ onto _README_ readme = readme + rpm_lib end #if readme_2 = <<_README2_ 2) Rhoconnect installer configured redis server with the following settings: A) redis.conf file is located in #{@prefix}/etc/ directory with properties: daemonize yes pidfile /var/run/redis.pid logfile /var/log/redis.log B) Redis logrotate settings for /var/log/redis.log files defined in '/etc/logrotate.d/redis': /var/log/redis.log { rotate 3 missingok notifempty size 250k create 0644 root root compress } C) Redis start-up script '/etc/init.d/redis'. You can start/stop redis server by running the following commands: /etc/init.d/redis {start|stop} 3) Setup rhoconnect application directory Put your application code in a directory called /var/www/rhoconnect (make sure this is the root of your application directory, i.e. /var/www/rhoconnect/config.ru should exist). _README2_ readme = readme + readme_2 readme end #generate_common_info def nginx_readme readme = <<_NGINX_README_ 4) Installer compiled Nginx web server (/opt/nginx) with the following configuration files: - Nginx start-up script (/etc/init.d/nginx) - Nginx logrotate settings (/etc/logrotate.d/nginx) - Nginx configuration file (/opt/nginx/conf/nginx.conf) - passenger configuration file and virtual host template for rhoconnect application (/opt/nginx/conf/conf.d/passenger.conf and /opt/nginx/conf/conf.d/rhoconnect.conf) To complete setup of web server A) Configure virtual host for rhoconnect application: Edit the file /opt/nginx/conf/conf.d/rhoconnect.conf so that it reflects your specifications. B) As root user start server to pick up the changes: /etc/init.d/nginx start _NGINX_README_ readme end def generate_rhoapp(rho_path) puts "Generating rhoconnect application: /opt/nginx/html/rhoapp ..." Dir.chdir "/opt/nginx/html" unless File.directory? "/opt/nginx/html/rhoapp" `#{rho_path}/bin/rhoconnect app rhoapp` Dir.chdir "rhoapp" log = `#{rho_path}/bin/bundle install --without=test development` raise "Generatiion of rhoconnect application failured:\n#{log}" if $? != 0 Dir.chdir "../" `chown -R nginx:nginx rhoapp/` end end def copy_benchapp(rho_path) puts "Copy bench rhoconnect application to /opt/nginx/html directory ..." Dir.chdir "#{rho_path}/installer" `tar xzf bench.tar.gz -C #{rho_path}` `rm -rf bench.tar.gz` `#{rho_path}/bin/gem install ffaker --no-ri --no-rdoc` `#{rho_path}/bin/gem install thor --no-ri --no-rdoc` Dir.chdir "#{rho_path}/bench" `cp -r benchapp /opt/nginx/html` Dir.chdir "/opt/nginx/html/benchapp" `rm -rf Gemfile.lock` `#{rho_path}/bin/bundle install --without=test development` Dir.chdir "../" `chown -R nginx:nginx benchapp/` end def config_and_install_thin_scripts(rho_path) puts "Configuring and installing thin scripts ..." `#{rho_path}/bin/thin install` # >> Installing thin service at /etc/rc.d/thin ... # mkdir -p /etc/rc.d # writing /etc/rc.d/thin # chmod +x /etc/rc.d/thin # mkdir -p /etc/thin # # To configure thin to start at system boot: # on RedHat like systems: # sudo /sbin/chkconfig --level 345 thin on # on Debian-like systems (Ubuntu): # sudo /usr/sbin/update-rc.d -f thin defaults # on Gentoo: # sudo rc-update add thin default # # Then put your config files in /etc/thin `#{rho_path}/bin/thin config -C /etc/thin/rhoapp.yml -c /opt/nginx/html/rhoapp/ --socket /tmp/thin.sock --log /opt/nginx/logs/thin.log --pid /var/run/thin.pid -e production` `ln -s /etc/rc.d/thin /etc/init.d/.` if File.directory?('/etc/rc.d') end def create_texts if @redis create_redis_init create_redis_logrotate end if @server == 'nginx' create_nginx_init create_nginx_logrotate @use_bench_app = File.exist? "#{@prefix}/installer/bench.tar.gz" if @use_bench_app create_nginx_conf_files "benchapp" copy_benchapp @prefix else create_nginx_conf_files "rhoapp" generate_rhoapp @prefix end config_and_install_thin_scripts(@prefix) distro_info = nginx_readme end common_info = generate_common_info readme = common_info + distro_info File.open("#{@prefix}/README", 'w') { |f| f << readme } afterwords = <<_IT_SHOULD_BE_DONE_ Thank you for choosing Rhomobile for your cross-platform app needs! To finish this setup, please complete the following... 1) Add necessary bins to the path(s) of the users who will be using this software. You may also wish to add these items to your #{@profile} to automatically add them upon login. export PATH=#{@prefix}/bin:$PATH _IT_SHOULD_BE_DONE_ about_app = if @use_bench_app server_todo_list = <<_NGINX_TO_DO_ 2) Rhoconnect 'benchapp' application is created in /opt/nginx/html directory. To run it A) As root user start redis and nginx servers: /etc/init.d/redis start /etc/init.d/nginx start B) To verify that application up and running open web console in your browser: http://localhost/console/ _NGINX_TO_DO_ else server_todo_list = <<_NGINX_TO_DO_ 2) Try rhoconnect 'rhoapp' application, created in /opt/nginx/html directory A) As root user start redis and nginx servers: /etc/init.d/redis start /etc/init.d/nginx start /etc/init.d/thin start B) Open RhoConnect application web console in your browser: http://localhost/console/ _NGINX_TO_DO_ end afterwords << about_app afterwords << "For more details see #{@prefix}/README file." puts afterwords File.open("#{@log_file}", 'a') { |f| f << afterwords } if @log_file end create_texts