#!/usr/bin/env ruby
# Phusion Passenger - http://www.modrails.com/
# Copyright (C) 2008 Phusion
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; version 2 of the License.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
PASSENGER_ROOT = File.expand_path(File.dirname(__FILE__) << "/..")
$LOAD_PATH.unshift("#{PASSENGER_ROOT}/lib")
# The Apache executable may be located in an 'sbin' folder. We add
# the 'sbin' folders to $PATH just in case. On some systems
# 'sbin' isn't in $PATH unless the user is logged in as root from
# the start (i.e. not via 'su' or 'sudo').
ENV["PATH"] += ":/usr/sbin:/sbin:/usr/local/sbin"
require 'passenger/platform_info'
require 'passenger/dependencies'
require 'passenger/console_text_template'
include PlatformInfo
class Installer
include Passenger
PASSENGER_WEBSITE = "http://www.modrails.com/"
PHUSION_WEBSITE = "www.phusion.nl"
USERS_GUIDE = "#{PASSENGER_ROOT}/doc/Users guide.html"
File.read("#{PASSENGER_ROOT}/Rakefile") =~ /^PACKAGE_VERSION = "(.*)"$/
PASSENGER_VERSION = $1
REQUIRED_DEPENDENCIES = [
Dependencies::GCC,
Dependencies::Ruby_DevHeaders,
Dependencies::Ruby_OpenSSL,
Dependencies::RubyGems,
Dependencies::Rake,
Dependencies::Apache2,
Dependencies::Apache2_DevHeaders,
Dependencies::APR_DevHeaders,
Dependencies::FastThread
]
def start
Dir.chdir(PASSENGER_ROOT)
show_welcome_screen
check_dependencies || exit(1)
check_whether_apache_uses_prefork_mpm
check_write_permission_to_passenger_root || exit(1)
if install_apache2_module
show_apache2_config_snippets
show_deployment_example
else
show_possible_solutions_for_compilation_and_installation_problems
exit(1)
end
ensure
reset_terminal_colors
end
private
def init_terminal_colors
STDOUT.write("\e[0m\e[37m\e[40m")
STDOUT.flush
end
def reset_terminal_colors
STDOUT.write("\e[0m")
STDOUT.flush
end
def show_welcome_screen
render_template 'welcome', :version => PASSENGER_VERSION
wait
end
def check_dependencies
missing_dependencies = []
color_puts "<banner>Checking for required software...</banner>"
puts
REQUIRED_DEPENDENCIES.each do |dep|
color_print " * #{dep.name}... "
result = dep.check
if result.found?
if result.found_at
color_puts "<green>found at #{result.found_at}</green>"
else
color_puts "<green>found</green>"
end
else
color_puts "<red>not found</red>"
missing_dependencies << dep
end
end
if missing_dependencies.empty?
return true
else
puts
color_puts "<red>Some required software is not installed.</red>"
color_puts "But don't worry, this installer will tell you how to install them.\n"
color_puts "<b>Press Enter to continue, or Ctrl-C to abort.</b>"
wait
line
color_puts "<banner>Installation instructions for required software</banner>"
puts
missing_dependencies.each do |dep|
print_dependency_installation_instructions(dep)
puts
end
return false
end
end
def check_whether_apache_uses_prefork_mpm
line
# 'httpd -V' output is in the form of:
#
# Server MPM: Prefork # <--- this line is not always available!
# ...
# Server compiled with....
# -D APACHE_MPM_DIR="server/mpm/prefork"
output = `#{HTTPD} -V`
output =~ /^Server MPM: +(.*)$/
if $1
mpm = $1.downcase
else
output =~ /APACHE_MPM_DIR="server\/mpm\/(.*)"/
if $1
mpm = $1.downcase
else
mpm = nil
end
end
if mpm != "prefork"
render_template 'apache_must_be_compiled_with_prefork_mpm',
:current_mpm => mpm
wait
end
end
def check_write_permission_to_passenger_root
File.new("__test__.txt", "w").close
return true
rescue
puts
line
if Process.uid == 0
render_template 'no_write_permission_to_passenger_root'
else
render_template 'run_installer_as_root'
end
return false
ensure
File.unlink("__test__.txt") rescue nil
end
def install_apache2_module
puts
line
color_puts '<banner>Compiling and installing Apache 2 module...</banner>'
puts "cd #{PASSENGER_ROOT}"
puts "rake clean apache2"
return system("rake", "clean", "apache2")
end
def show_apache2_config_snippets
puts
line
render_template 'apache2_config_snippets',
:module_location => "#{PASSENGER_ROOT}/ext/apache2/mod_passenger.so",
:spawn_server_location => "#{PASSENGER_ROOT}/bin/passenger-spawn-server",
:ruby => RUBY
wait
end
def show_deployment_example
puts
line
render_template 'deployment_example',
:users_guide => USERS_GUIDE,
:phusion_website => PHUSION_WEBSITE,
:passenger_website => PASSENGER_WEBSITE
end
def show_possible_solutions_for_compilation_and_installation_problems
puts
line
render_template 'possible_solutions_for_compilation_and_installation_problems',
:users_guide => USERS_GUIDE,
:passenger_website => PASSENGER_WEBSITE
end
private
def color_print(text)
STDOUT.write(ConsoleTextTemplate.new(:text => text).result)
STDOUT.flush
end
def color_puts(text)
color_print("#{text}\n")
end
def render_template(name, options = {})
puts ConsoleTextTemplate.new({ :file => name }, options).result
end
def line
puts "--------------------------------------------"
end
def wait
begin
STDIN.readline
rescue Interrupt
exit 2
end
end
def print_dependency_installation_instructions(dep)
color_puts " * To install <yellow>#{dep.name}</yellow>:"
if !dep.install_command.nil?
color_puts " Please run <b>#{dep.install_command}</b> as root."
elsif !dep.install_instructions.nil?
color_puts " " << dep.install_instructions
elsif !dep.website.nil?
color_puts " Please download it from <b>#{dep.website}</b>"
if !dep.website_comments.nil?
color_puts " (#{dep.website_comments})"
end
else
color_puts " Search Google."
end
end
end
Installer.new.start