ScenarioI run OSgrid / OpenSimulator on a home hosted machine under user 'grid'. The main user account on that machine is 'media'. I wanted a way to connect to the machine via SSH mainly and start and stop the simulators that I have running, this is the result...
RequirementsDirectory StructureThis requires at least the current version of the software (0e2abde as of the 22nd July 2019) and a previous version. This is so that a new release can be tested easily, and if there is a problem, you can drop back to your last working version.
You also need a seperate directory where all your simulators sit, in my case I use a directory called
OVERRIDEosgrid which holds an override file, and a directory called
Regions where the region configuration is held.
{L_CODE}:
-> /home
-> 0e2abde
-> bin
-> 481d715
-> bin
-> OVERRIDEosgrid
-> in1
-> Regions
- region.ini
- override.ini
-> in2
-> Regions
- region.ini
- override.ini
-> in3
-> Regions
- region.ini
- override.ini
-> in4
-> Regions
- region.ini
- override.ini
-> in5
-> Regions
- region.ini
- override.ini
The minimum requirements for the
override.ini are
{L_CODE}:
[Startup]
;; These are from OpenSim.ini
PIDFile = "/home/grid/gridservers/osgrid-in1.pid"
regionload_regionsdir = "/home/grid/gridservers/OVERRIDEosgrid/in1/Regions/"
[Network]
http_listener_port = 9011
[DatabaseService]
;; These are from gridcommon.ini
StorageProvider = "OpenSim.Data.MySQL.dll"
ConnectionString = "Data Source=localhost;Database=YOUR_DATABASE_NAME;User ID=YOUR_DATABASE_USER;Password=YOUR_DATABASE_PASSWORD;"
.
You will need to alter
PIDFile,
regionload_regionsdir and
http_listener_port for each of your instances.
The program{L_CODE}:
#!/bin/bash
hostmachine=192.168.0.50
BaseDir="/home/grid/gridservers/OVERRIDEosgrid"
SimOwner="SimUserAccount"
OwnerPassword="SimOwnerPassword"
CURRENT_VERSION=0e2abde
PREVIOUS_VERSION=481d715
# NEW_VERSION=0e2abde
LoggedIn=`id -u -n`
declare -a filenamearray
declare -a overridenamearray
declare -a simname
declare -a simport
declare -a httpport
declare -a simstatus
if [ -z $DISPLAY ]
then
DIALOG=dialog
else
# DIALOG=dialog
DIALOG=gdialog
fi
tempfile=`tempfile 2>/dev/null` || tempfile=/tmp/test$$
trap "rm -f $tempfile" 0 1 2 5 15
tempfile2=`subtempfile 2>/dev/null` || tempfile=/tmp/subtest$$
trap "rm -f $tempfile2" 0 1 2 5 15
cd $BaseDir
subdir=(`ls`)
subdirlen=${#subdir[*]}
inc1=0
inc2=0
function set_version {
$DIALOG --colors --no-shadow --backtitle "Control Board" \
--title "Version" --clear \
--menu "Choose a version" 20 70 4 \
"Current" "${CURRENT_VERSION}" \
"Previous" "${PREVIOUS_VERSION}" \
"Exit" "Exit the program" 2> $tempfile
retval=$?
choice=`cat $tempfile`
case $retval in
0)
if [ "$choice" == "Current" ]
then
version=${CURRENT_VERSION}
start_menu
elif [ "$choice" == "Previous" ]
then
version=${PREVIOUS_VERSION}
start_menu
else
main_menu
fi
;;
1)
# Cancel chosen
main_menu
;;
255)
# ESC Chosen
main_menu
;;
esac
trap "rm -f $tempfile" 0 1 2 5 15
start_menu
}
function main_menu {
sim_status
$DIALOG --colors --no-shadow --backtitle "Control Board" \
--title "Main Menu" --clear \
--menu "Current Status \n${dialogstatus}\nPlease choose an option:" 20 70 4 \
"Start" "Start an estate" \
"Stop" "Close down an estate" \
"Exit" "Exit the program" 2> $tempfile
retval=$?
choice=`cat $tempfile`
case $retval in
0)
if [ "$choice" == "Start" ]
then
set_version
elif [ "$choice" == "Stop" ]
then
stop_menu
else
clear
exit 1
fi
;;
1)
clear
exit 1
;;
255)
clear
exit 1
;;
esac
}
function start_menu {
sim_status
inc1=0
inc2=0
simlist=()
while [ $inc1 -lt $subdirlen ]; do
simlist[$inc2]="${inc1}"
let inc2++
simlist[$inc2]="${simname[$inc1]}"
let inc2++
let inc1++
done
$DIALOG --no-tags --colors --no-shadow --backtitle "Control Board" \
--title "Start Menu" --clear \
--menu "Current Status \n${dialogstatus}\n\n Please choose an estate to start:" 25 70 7 \
"${simlist[@]}" \
"Back" "Main Menu" 2> $tempfile
retval2=$?
choice2=`cat $tempfile`
case $retval2 in
0)
if [ "$choice2" == "Back" ]
then
main_menu
fi
screen_id="${subdir[$choice2]}"
estate_name="${simname[$choice2]}"
estate_port="${simport[$choice2]}"
http_port="${httpport[$choice2]}"
start_sim
;;
1)
# Cancel chosen.
main_menu
exit 1
;;
255)
# ESC chosen
main menu
;;
esac
main_menu
}
function stop_menu {
sim_status
inc1=0
inc2=0
simlist=()
while [ $inc1 -lt $subdirlen ]; do
simlist[$inc2]="${inc1}"
let inc2++
simlist[$inc2]="${simname[$inc1]}"
let inc2++
let inc1++
done
$DIALOG --no-tags --colors --no-shadow --backtitle "Control Board" \
--title "Stop Menu" --clear \
--menu "Current Status \n${dialogstatus}\n\n Please choose an estate to stop:" 25 70 7 \
"${simlist[@]}" \
"Back" "Main Menu" 2> $tempfile
retval2=$?
choice2=`cat $tempfile`
case $retval2 in
0)
if [ "$choice2" == "Back" ]
then
main_menu
fi
screen_id="${subdir[$choice2]}"
estate_name="${simname[$choice2]}"
estate_port="${simport[$choice2]}"
http_port="${httpport[$choice2]}"
stop_sim
;;
1)
# Cancel chosen.
main_menu
;;
255)
# ESC chosen
main_menu
;;
esac
main_menu
}
function start_sim {
if (: < /dev/tcp/$hostmachine/$http_port) 2>/dev/null
then
$DIALOG --title "${estate_name}" \
--msgbox "This region may already be running, please check and try again." 10 40
start_menu
else
$DIALOG --title "${estate_name}" \
--infobox "Starting ${estate_name} on screen ${screen_id}." 6 40
screen -dmS $screen_id
if [ "$LoggedIn" != "${SimOwner}" ]
then
screen -S $screen_id -X stuff 'su '$SimOwner'^M'`echo -ne '\015'`
sleep 5
screen -S $screen_id -X stuff $OwnerPassword'^M'`echo -ne '\015'`
fi
screen -S $screen_id -X stuff 'cd /home/grid/gridservers/'$version'/bin^M'`echo -ne '\015'`
screen -S $screen_id -p 0 -X stuff 'mono OpenSim.exe -inidirectory='${BaseDir}'/'${screen_id}'/^M'`echo -ne '\015'`
while ! nc -z ${hostmachine} ${http_port} </dev/null; do
sleep 5
done
$DIALOG --title "${estate_name}" \
--msgbox "${estate_name} has now started" 6 40
fi
start_menu
}
function stop_sim {
if (: < /dev/tcp/$hostmachine/$http_port) 2>/dev/null
then
$DIALOG --title "${estate_name}" \
--infobox "Shutdown of ${estate_name} in progress...\nPlease wait." 6 40
screen -S $screen_id -X stuff 'shutdown^M'`echo -ne '\015'`
until ! nc -z ${hostmachine} ${http_port} </dev/null; do
sleep 10
done
screen -S $screen_id -X stuff 'exit^M'`echo -ne '\015'`
sleep 10
screen -S $screen_id -X stuff 'exit^M'`echo -ne '\015'`
sleep 10
stop_menu
else
$DIALOG --title "${estate_name}" \
--msgbox "${estate_name} may not be running" 10 40
stop_menu
fi
}
function sim_status {
inc1=0
while [ $inc1 -lt $subdirlen ]; do
if (: < /dev/tcp/${hostmachine}/${httpport[$inc1]}) 2>/dev/null
then
simstatus[$inc1]="Connection to \Zu${simname[$inc1]}\ZU \Zb\Z2succeeded\Zn on port ${simport[$inc1]} / ${httpport[$inc1]}"
else
simstatus[$inc1]="Connection to \Zu${simname[$inc1]}\ZU \Zb\Z1failed\ZB\Zn on port ${simport[$inc1]} / ${httpport[$inc1]}"
fi
let inc1++
done
inc1=0
dialogstatus=${simstatus[$inc1]}
dialogstatus+="\n"
let inc1++
while [ $inc1 -lt $subdirlen ]; do
dialogstatus+=${simstatus[$inc1]}
dialogstatus+="\n"
let inc1++
done
}
function get_dir {
while [ $inc1 -lt $subdirlen ]; do
cd $BaseDir/${subdir[$inc1]}/Regions
files=(`ls *.ini`)
filelen=${#files[*]}
while [ $inc2 -lt $filelen ]; do
filenamearray+=(${files[inc2]})
let inc2++
done
inc2=0
let inc1++
done
inc1=0
while [ $inc1 -lt $subdirlen ]; do
cd $BaseDir/${subdir[$inc1]}
files=(`ls *.ini`)
filelen=${#files[*]}
while [ $inc2 -lt $filelen ]; do
overridenamearray+=(${files[inc2]})
let inc2++
done
inc2=0
let inc1++
done
get_file
}
function get_file {
while [ $inc2 -lt $subdirlen ]; do
filepath=(${BaseDir}/${subdir[$inc2]}/Regions/${filenamearray[$inc2]})
simport[$inc2]=$(awk '/InternalPort/ {print $3}' ${BaseDir}/${subdir[$inc2]}/Regions/${filenamearray[$inc2]})
simname[$inc2]=`(head -n 1 $filepath | tail -n 1)`
httpport[$inc2]=$(awk '/http_listener_port/ {print $3}' ${BaseDir}/${subdir[$inc2]}/${overridenamearray[$inc2]})
tempstr="${simname[$inc2]:1}"
simname[$inc2]=$tempstr
tempstr="${simname[$inc2]:0:-1}"
simname[$inc2]=$tempstr
let inc2++
done
}
get_dir
main_menu
cd ~
This may be overkill, but for me, it works. If you have a different way of doing this, or improvements to my code, please comment.
Regards
Baron Brown
(Edited 23 Jul 2019 to remove the requirement for the
InternalPort to be on the second line and the
http_listener_port to be
InternalPort + 10)