Init Script

From OpenSimulator

(Difference between revisions)
Jump to: navigation, search
(Replacing page with '== OpenSim Init Scripts == There is now a forge project for [http://forge.opensimulator.org/gf/linuxservice|Linux Service Scripts for OpenSim] that contains init scripts for r...')
Line 1: Line 1:
== Region Init Script ==
+
== OpenSim Init Scripts ==
The following is an init script that I wrote for starting, stopping, and monitoring OpenSim on Linux systems.  It makes some assumptions, and is only going to work (unmoddified) if you stay with those assumptions:
+
* Your opensim instance is in /opt/opensim/staging/bin (that's an easy change)
+
* You are only running 1 OpenSim.exe process per machine (that's '''not''' easy to change)
+
* You are using mysql (that's easy to change)
+
* Production mono is in /usr/local/bin (that's easy to change)
+
While it may not be suitable for all environments, it has been very useful for the environments that I run.
+
  
<source lang="ruby">
+
There is now a forge project for [http://forge.opensimulator.org/gf/linuxservice|Linux Service Scripts for OpenSim] that contains init scripts for running OpenSim.
#!/usr/bin/ruby
+
 
+
# Start or stop OpenSim
+
#
+
# Sean Dague <sdague@gmail.com>
+
 
+
### BEGIN INIT INFO
+
# Provides:          opensim
+
# Required-Start:    $local_fs $remote_fs $syslog $named $network $time $mysql
+
# Required-Stop:    $local_fs $remote_fs $syslog $named $network
+
# Default-Start:    2 3 4 5
+
# Default-Stop:      0 1 6
+
# Short-Description: start and stop opensim
+
# Description:      opensim init script
+
### END INIT INFO
+
 
+
require "rexml/document"
+
require "open-uri"
+
include REXML
+
 
+
OpenSimPath = "/opt/opensim/staging/bin"
+
Dir.chdir(OpenSimPath)
+
 
+
@host = "localhost"
+
@port = 9000
+
@uuid = "0"
+
 
+
def parse_config
+
    # first we figure out the external hostname of a region on the box
+
    Dir.new("#{OpenSimPath}/Regions").find do |f|
+
        if f =~ /\.xml$/
+
            doc = Document.new(File.new("#{OpenSimPath}/Regions/#{f}"))
+
           
+
            if doc.root.elements['Config'].attributes['external_host_name']
+
                @host = doc.root.elements['Config'].attributes['external_host_name']
+
            else
+
                @host = doc.root.elements['Config'].elements['external_host_name'].text
+
            end
+
     
+
            if doc.root.elements['Config'].attributes['sim_UUID']
+
                @uuid = doc.root.elements['Config'].attributes['sim_UUID'].gsub(/-/,'')
+
            else
+
                @uuid = doc.root.elements['Config'].elements['sim_UUID'].text.gsub(/-/,'')
+
            end
+
           
+
            break
+
        end
+
    end
+
    # then we figure out the external port from opensim.ini
+
    open("#{OpenSimPath}/OpenSim.ini") do |f|
+
        f.each do |line|
+
            if line =~ /^\s*http_listener_port/
+
                (key, equal, port) = line.split
+
                if port
+
                    @port = port
+
                end
+
            end
+
        end
+
    end
+
end
+
 
+
def alive?
+
    begin
+
        open("http://#{@host}:#{@port}/index.php?method=regionImage#{@uuid}") do |f|
+
            resp = f.read
+
            return true
+
        end
+
    rescue => e
+
    end
+
    return false
+
end
+
 
+
def pidof(item)
+
    IO.popen("ps auxw | grep #{item} | grep -v grep") do |line|
+
        line.each do |l|
+
            return l.split[1].to_i
+
        end
+
    end
+
    return nil
+
end
+
 
+
def opensim_pid
+
    return pidof("OpenSim.exe")
+
end
+
 
+
def status
+
    if alive?
+
        puts "OK"
+
        exit 0
+
    else
+
        puts "FAILED"
+
        exit 1
+
    end
+
end
+
 
+
def start
+
    if alive?
+
        puts "OpenSim already running"
+
        exit 0
+
    end
+
    if opensim_pid != nil
+
        # opensim process is running, but not responding, we're hung
+
        stop
+
        # this really is needed otherwise you get a wedge
+
        system("/etc/init.d/mysql restart")
+
        sleep 10
+
        # purge the addin cache, this may have been the reason for the hang
+
        system("rm -rf addin-db-*")
+
    end
+
    system("screen -wipe")
+
    system("screen -d -S opensim -m /usr/local/bin/mono --debug OpenSim.exe")
+
   
+
    20.times do |t|
+
        if alive?
+
            return
+
        end
+
        sleep 5
+
    end
+
   
+
    puts "FAILED to start region"
+
    exit 1
+
end
+
 
+
def stop
+
    if opensim_pid == nil
+
        puts "OpenSim not running"
+
        exit 0
+
    end
+
    system("screen -wipe")
+
    system("screen -S opensim -X eval 'stuff \"shutdown\015\"'")
+
    puts "Shutting down... waiting 30 seconds"
+
    30.times do |i|
+
        if opensim_pid == nil
+
            return
+
        end
+
        $stderr.write "."
+
        sleep 1
+
    end
+
   
+
    pid = opensim_pid
+
    if pid
+
        puts "Process not responding, forcing shutdown"
+
        Process.kill(9, pid)
+
    end
+
   
+
end
+
 
+
def main
+
    parse_config
+
   
+
    mode = ARGV[0]
+
   
+
    if mode == "start"
+
        start
+
    elsif mode == "stop"
+
        stop
+
    elsif mode == "status"
+
        status
+
    elsif mode == "process"
+
        puts opensim_pid
+
    elsif mode == "restart"
+
        puts "called restart"
+
    else
+
        puts "unknown"
+
    end
+
end
+
 
+
main
+
</source>
+
 
+
== Grid Init Script ==
+
'''WARNING''' this is untested, so it may blow up on you.
+
<source lang="ruby">
+
#!/usr/bin/ruby
+
 
+
# Start or stop OpenSim
+
#
+
# Sean Dague <sdague@gmail.com>
+
 
+
### BEGIN INIT INFO
+
# Provides:          opensim-grid
+
# Required-Start:    $local_fs $remote_fs $syslog $named $network $time $mysql
+
# Required-Stop:    $local_fs $remote_fs $syslog $named $network
+
# Default-Start:    2 3 4 5
+
# Default-Stop:      0 1 6
+
# Short-Description: start and stop opensim-grid
+
# Description:      opensim-grid init script
+
### END INIT INFO
+
 
+
require "rexml/document"
+
require "open-uri"
+
include REXML
+
 
+
OpenSimPath = "/opt/opensim/staging/bin"
+
Dir.chdir(OpenSimPath)
+
 
+
@host = "localhost"
+
@gridport = nil
+
@userport = nil
+
@invport = nil
+
@assetport = nil
+
@messageport = nil
+
 
+
GridExe = "OpenSim.Grid.GridServer.exe"
+
UserExe = "OpenSim.Grid.UserServer.exe"
+
AssetExe = "OpenSim.Grid.AssetServer.exe"
+
InventoryExe = "OpenSim.Grid.InventoryServer.exe"
+
MessagingExe = "OpenSim.Grid.MessagingServer.exe"
+
 
+
def parse_config
+
    # Grid
+
    begin
+
        doc = Document.new(File.new("#{OpenSimPath}/GridServer_Config.xml"))
+
        @gridport = doc.root.elements['Config'].attributes['http_port']
+
    rescue => e
+
    end
+
 
+
    # User
+
    begin
+
        doc = Document.new(File.new("#{OpenSimPath}/UserServer_Config.xml"))
+
        @userport = doc.root.elements['Config'].attributes['http_port']
+
    rescue => e
+
    end
+
   
+
    # Inventory
+
    begin
+
        doc = Document.new(File.new("#{OpenSimPath}/InventoryServer_Config.xml"))
+
        @invport = doc.root.elements['Config'].attributes['http_port']
+
    rescue => e
+
    end
+
   
+
    # Asset
+
    begin
+
        doc = Document.new(File.new("#{OpenSimPath}/AssetServer_Config.xml"))
+
        @assetport = doc.root.elements['Config'].attributes['http_port']
+
    rescue => e
+
    end
+
   
+
    # Messaging
+
    begin
+
        doc = Document.new(File.new("#{OpenSimPath}/MessagingServer_Config.xml"))
+
        @messageport = doc.root.elements['Config'].attributes['http_port']
+
    rescue => e
+
    end
+
end
+
 
+
def grid_alive?
+
    if not @gridport
+
        return false
+
    end
+
    # we actually only care if we cause an exception, which means the grid server is bust
+
    begin
+
        xml = open("http://#{@host}:#{@gridport}/sims/fc036b80fed84b3096a50569b60da265").read
+
        return true
+
    rescue => e
+
        return false
+
    end
+
end
+
 
+
def user_alive?
+
    if not @userport
+
      return false
+
    end
+
    # we actually only care if we cause an exception, which means the grid server is bust
+
    begin
+
        xml = open("http://#{@host}:#{@userport}/get_grid_info").read
+
        return true
+
    rescue => e
+
        return false
+
    end
+
end
+
 
+
def asset_alive?
+
    if not @assetport
+
        return false
+
    end
+
    begin
+
        # fetch the moon
+
        xml = open("http://#{@host}:#{@assetport}/assets/ec4b9f0b-d008-45c6-96a4-01dd947ac621").read
+
        # we need to check that we got something, because everything returns success, even if it didn't work
+
        if xml.size > 0
+
            return true
+
        else
+
            return false
+
        end
+
    rescue => e
+
        return false
+
    end
+
end
+
 
+
def inv_alive?
+
    if not @userport
+
      return false
+
    end
+
    return true
+
    # THERE IS CURRENTLY NO EASY CALL FOR INV SERVER
+
    # we actually only care if we cause an exception, which means the grid server is bust
+
    begin
+
        xml = open("http://#{@host}:#{@port}/get_grid_info").read
+
        return true
+
    rescue => e
+
        return false
+
    end
+
end
+
 
+
def message_alive?
+
    if not @messageport
+
        return false
+
    end
+
    return true
+
end
+
 
+
 
+
def pidof(item)
+
    IO.popen("ps auxw | grep #{item} | grep -v grep") do |line|
+
        line.each do |l|
+
            return l.split[1].to_i
+
        end
+
    end
+
    return nil
+
end
+
 
+
def grid_pid
+
    return pidof(GridExe)
+
end
+
def user_pid
+
    return pidof(UserExe)
+
end
+
def asset_pid
+
    return pidof(AssetExe)
+
end
+
def inv_pid
+
    return pidof(InventoryExe)
+
end
+
def message_pid
+
    return pidof(MessagingExe)
+
end
+
 
+
def failme(msg="")
+
    puts "FAIL - #{msg}"
+
    exit 1
+
end
+
 
+
def status
+
    if @gridport and (not grid_alive?)
+
        failme("Grid server not responding")
+
    end
+
    if @userport and (not user_alive?)
+
        failme("User server not responding")
+
    end
+
    if @assetport and (not asset_alive?)
+
        failme("Asset server not responding")
+
    end
+
    if @invport and (not inv_alive?)
+
        failme("Inventory server not responding")
+
    end
+
    if @messageport and (not message_alive?)
+
        failme("Grid server not responding")
+
    end
+
    puts "OK"
+
    exit 0
+
end
+
 
+
def start_service(name, exe)
+
    if pidof(exe) != nil
+
        puts("#{exe} already running")
+
        return
+
    end
+
    system("screen -d -S #{name} -m /usr/local/bin/mono --debug #{exe}")
+
end
+
 
+
def start
+
    # Grid
+
    start_service("grid", GridExe)
+
    10.times do |d|
+
        if grid_alive?
+
            break
+
        end
+
        sleep 2
+
    end
+
    if not grid_alive?
+
        failme("Grid server did not start")
+
    end
+
 
+
    # User
+
    start_service("user", UserExe)
+
    10.times do |d|
+
        if user_alive?
+
            break
+
        end
+
        sleep 2
+
    end
+
    if not user_alive?
+
        failme("User server did not start")
+
    end
+
 
+
    # Asset
+
    start_service("asset", AssetExe)
+
    10.times do |d|
+
        if asset_alive?
+
            break
+
        end
+
        sleep 2
+
    end
+
    if not asset_alive?
+
        failme("Asset server did not start")
+
    end
+
 
+
    # Inventory
+
    start_service("inventory", InventoryExe)
+
    10.times do |d|
+
        if inv_alive?
+
            break
+
        end
+
        sleep 2
+
    end
+
    if not inv_alive?
+
        failme("Inventory server did not start")
+
    end
+
   
+
    # sleep an extra 2 because we didn't sleep at all here
+
    sleep 2
+
    # Messaging
+
    start_service("messaging", MessagingExe)
+
    10.times do |d|
+
        if message_alive?
+
            break
+
        end
+
        sleep 2
+
    end
+
    if not message_alive?
+
        failme("Messaging server did not start")
+
    end
+
end
+
 
+
def stop_service(name, exe)
+
    if pidof(exe) == nil
+
        puts "WARNING - #{exe} not running"
+
    end
+
    system("screen -S #{name} -X eval 'stuff \"shutdown\015\"'")
+
    puts "Shutting down... waiting 30 seconds"
+
    30.times do |i|
+
        if pidof(exe) == nil
+
            # just puts out a newline
+
            puts ""
+
            return
+
        end
+
        $stderr.write "."
+
        sleep 1
+
    end
+
   
+
    pid = pidof(exe)
+
    if pid
+
        puts "Process not responding, forcing shutdown"
+
        Process.kill(9, pid)
+
    end
+
end
+
 
+
def stop
+
    stop_service("messaging",MessagingExe)
+
    stop_service("inventory",InventoryExe)
+
    stop_service("asset",AssetExe)
+
    stop_service("user",UserExe)
+
    stop_service("grid",GridExe)
+
end
+
 
+
def process
+
    puts "Grid #{grid_pid}"
+
    puts "User #{user_pid}"
+
    puts "Asset #{asset_pid}"
+
    puts "Inventory #{inv_pid}"
+
    puts "Messaging #{message_pid}"
+
end
+
 
+
def main
+
    parse_config
+
   
+
    mode = ARGV[0]
+
   
+
    if mode == "start"
+
        start
+
    elsif mode == "stop"
+
        stop
+
    elsif mode == "status"
+
        status
+
    elsif mode == "process"
+
        process
+
    elsif mode == "restart"
+
        puts "called restart"
+
    else
+
        puts "unknown"
+
    end
+
end
+
 
+
main
+
</source>
+

Revision as of 09:58, 31 January 2009

OpenSim Init Scripts

There is now a forge project for Service Scripts for OpenSim that contains init scripts for running OpenSim.

Personal tools
General
About This Wiki