Init Script
From OpenSimulator
(Difference between revisions)
												
			| Line 1: | Line 1: | ||
| + | = Region Init Script =  | ||
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:  | 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)  | * Your opensim instance is in /opt/opensim/staging/bin (that's an easy change)  | ||
| Line 167: | Line 168: | ||
     elsif mode == "process"  |      elsif mode == "process"  | ||
         puts opensim_pid  |          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 <japh@us.ibm.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"  |      elsif mode == "restart"  | ||
         puts "called restart"  |          puts "called restart"  | ||
Revision as of 10:06, 25 January 2009
Region Init Script
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.
#!/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
Grid Init Script
WARNING this is untested, so it may blow up on you.
#!/usr/bin/ruby # Start or stop OpenSim # # Sean Dague <japh@us.ibm.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