[BACK]Return to mtctl_default.sh CVS log [TXT][DIR] Up to [local] / mtctl

Annotation of mtctl/mtctl_default.sh, Revision 1.7

1.1       bountyht    1: #---------------------------------------------------------------------
                      2: # Filename: mtctl
1.7     ! minionto    3: # Purpose: Minetest Server Control
        !             4: # License: Copyright (C) 2021-2022 by Miniontoby <miniontoby@ircnow.org>
1.1       bountyht    5: #---------------------------------------------------------------------
1.7     ! minionto    6: VERSION="1.5"
1.2       bountyht    7: config=[]
                      8: config[0]="no"; config[1]="/usr/local/share/minetest/"
1.1       bountyht    9:
                     10: #---------------------------------------------------------------------
                     11: # Alias
                     12:
                     13: mtinfo() {
                     14:        MSG="$1"
                     15:        echo -e "mtctl: $MSG" | sed -e 's/\\n/\\nmtctl: /'
                     16: }
                     17: mthelp() {
1.5       minionto   18:        echo -e "usage:  mtctl start|stop|restart|status|create|backup worldname\n        mtctl list|help|version|check_updates"
1.1       bountyht   19: }
1.5       minionto   20: if [ "x$1" == "x" ]; then mthelp; exit 0; fi
1.1       bountyht   21:
                     22:
                     23: #---------------------------------------------------------------------
1.2       bountyht   24: # Setup
                     25:
                     26: if [[ "`id -u`" -eq 0 ]]; then CONFDIR=/etc/mtctl; else CONFDIR=$HOME/.mtctl; fi
                     27: if [ \! -d $CONFDIR ]; then mkdir -p $CONFDIR || exit 1; fi
                     28: if [ \! -f $CONFDIR/config ]; then
                     29:        mtinfo "\nNo configfile found!\nCreating it now!\n\n"
                     30:        echo -n 'Use custom build minetest folder (yes/no): '; read MTBUILD
1.7     ! minionto   31:        case $MTBUILD in
1.2       bountyht   32:                YES|yes) MTBUILD='yes'
                     33:                        EXAMPLEDIR="$HOME/minetest"
                     34:                        ;;
                     35:                NO|no) MTBUILD='no'
                     36:                        EXAMPLEDIR="$HOME/.minetest"
                     37:                        ;;
                     38:                *) mtinfo "Error, not a valid option!"
                     39:                        exit 1
                     40:                        ;;
                     41:        esac
                     42:        echo -n "Insert the path to the minetest folder(eg. $EXAMPLEDIR): "; read MTLOCATION
                     43:
                     44:        echo -e "builded=$MTBUILD\nlocation=$MTLOCATION" > $CONFDIR/config
                     45:        unset MTBUILD MTLOCATION EXAMPLEDIR
                     46:        mtinfo "Configfile created!!\n\n"
                     47: fi
                     48:
                     49: while read line; do
                     50:        linea="`echo $line | grep -F = 2> /dev/null`"
                     51:        if [ "x$linea" \!= "x" ]; then
                     52:                varname=$(echo "$line" | cut -d '=' -f 1)
                     53:                case $varname in
                     54:                        builded) indexnumber=0
                     55:                                ;;
                     56:                        location) indexnumber=1
                     57:                                ;;
                     58:                esac
                     59:                config[$indexnumber]=$(echo "$line" | cut -d '=' -f 2-)
                     60:        fi
                     61: done < $CONFDIR/config
1.1       bountyht   62:
1.2       bountyht   63: mtsetup() {
                     64:        EXITDIR=${config[1]}/tmp
                     65:        if [ "${config[0]}" == "yes" ]; then SERVEREXE="${config[1]}/bin/minetestserver"; else SERVEREXE="`which minetestserver`"; fi
                     66:        WORLDBASE=${config[1]}/worlds
                     67:        LOGDIR=${config[1]}/log
                     68:        OK=0; cd ${config[1]} || exit 1
                     69:        touch temp.test && OK=1; if [ "@$OK" == "@0" ]; then mtinfo "Error: Directory tree should be owned by the MT user:\n${config[1]}"; exit 1; fi
                     70:        rm temp.test || exit 1
                     71:        if [ \! -f $SERVEREXE ]; then mtinfo "Error: Couldn't determine SERVEREXE setting\n$SERVEREXE"; exit 1; fi
                     72:
                     73:        mkdir -p $EXITDIR || exit 1
                     74:        mkdir -p $WORLDBASE || exit 1
                     75:        mkdir -p $LOGDIR || exit 1
                     76: }
1.1       bountyht   77:
                     78: #---------------------------------------------------------------------
                     79: # Normal Functions
                     80:
                     81: GetPIDS() {
                     82:        FOO=`ps ax | grep $SERVEREXE | grep " $1" | grep -e "--port" | sed -e "s/^ *//" -e "s/ .*//"`; BAR=`ps ax | grep "mtctl start *$2"\$ | grep -v grep | grep -v "^ *$$ " | sed -e "s/^ *//" -e "s/ .*//"`
                     83: }
                     84:
                     85: SetWorld() {
                     86:        NAME=$1; if [ "x$NAME" == "x" ]; then mthelp; exit 1; fi
                     87:        WORLDDIR=$WORLDBASE/$NAME; if [ \! -d $WORLDDIR ]; then mtstatus "Failed"; mtinfo "Error: World not found: $NAME"; exit 1; fi
                     88:        PORT=`grep '^port.*=' $WORLDDIR/world.conf | sed -e "s/^.*= *//" -e "s/ .*//"`; if [ "x$PORT" == "x" ]; then mtstatus "Failed"; mtinfo "Error: Port for $NAME not defined in cfg file"; exit 1; fi
1.7     ! minionto   89:        OWNER=`grep '^name.*=' $WORLDDIR/world.conf | sed -e "s/^.*= *//" -e "s/ .*//"`; if [ "x$OWNER" == "x" ]; then mtstatus "Failed"; mtinfo "Error: Owner for $NAME not defined in cfg file"; exit 1; fi
1.1       bountyht   90: }
                     91: mtstatus() {
                     92:        CHECK="$1"
                     93:        EXTRA=""
                     94:        if [ "$CHECK" == "Ok" ]; then
                     95:                GetPIDS "$WORLDDIR" "$NAME"
                     96:                if [ "x$FOO$BAR" \!= "x" ]; then
                     97:                        CHECK="Online"
                     98:                else
                     99:                        CHECK="Offline"
                    100:                fi
                    101:                EXTRA="\n"
1.7     ! minionto  102:        elif [ "$CHECK" == "Failed" ]; then EXTRA="\n";
        !           103:        elif [ "$CHECK" == "Backup failed" ]; then EXTRA="\n";
        !           104:        elif [ "$CHECK" == "Backup success" ]; then EXTRA="\n"; fi
1.1       bountyht  105:        echo -ne "\r$NAME($CHECK)$EXTRA"
                    106: }
                    107:
                    108: #---------------------------------------------------------------------
                    109: # Functions for executing the actions
                    110:
                    111: startMT() {
                    112:        SetWorld "$1"; mtstatus
                    113:        GetPIDS "$WORLDDIR" "$NAME"
                    114:        BAR=`echo $BAR | wc -l`
                    115:        if [ "x$FOO" \!= "x" ]; then
                    116:                mtstatus "Failed"
                    117:                mtinfo "Error: World seems already to be running\nIf it is not running, run $ mctl stop $NAME to be sure"
                    118:                exit 1
                    119:        fi
                    120:
1.5       minionto  121:        EXITFLAGWORLD=$EXITDIR/mtctlstop.$NAME
1.7     ! minionto  122:        MINETEST_SUBGAME_PATH=${config[1]}/games
1.1       bountyht  123:        # MAYBE Export if linux doesnt work
                    124:
                    125:        sleep 1; DIR=`pwd` || exit 1; cd $WORLDDIR || exit 1
                    126:        F1=env_meta.txt; F2=env_meta.old; if [ -s $F1 ]; then N=`grep EnvArgsEnd $F1 | wc -l` || exit 1; if [ "x$N" == "x0" ]; then rm -f $F1 || exit 1; fi; fi; if [ -s $F1 ]; then rm -f $F2; cp -p $F1 $F2 || exit 1; else if [ -s $F2 ]; then rm -f $F1; cp -p $F2 $F1 || exit 1; else rm -f $F1 || exit 1; fi; fi
                    127:        cd $DIR || exit 1
                    128:
                    129:        (
                    130:        while true; do
                    131:                $SERVEREXE --config $WORLDDIR/world.conf --port $PORT --logfile $LOGDIR/debug-$NAME.log --map-dir $WORLDDIR >> $LOGDIR/$NAME.log 2>&1
1.5       minionto  132:                if [ -f $EXITFLAGWORLD ]; then exit 0; fi; sleep 10
1.1       bountyht  133:        done
                    134:        ) > $LOGDIR/start-$NAME.txt &
                    135:        mtstatus "Ok"
                    136: }
                    137:
                    138: stopMT() {
                    139:        SetWorld "$1"; mtstatus
                    140:        GetPIDS "$WORLDDIR" "$NAME"
                    141:        if [ "x$FOO$BAR" == "x" ]; then mtstatus "Failed"; mtinfo "$NAME seems to be stopped already"; exit 0; fi
1.5       minionto  142:        touch $EXITDIR/mtctlstop.$NAME
                    143:
                    144:        if [ "x$FOO" \!= "x" ]; then
                    145:                kill -SIGINT $FOO
1.7     ! minionto  146:        elif [ "x$BAR" \!= "x" ]; then
        !           147:                kill -9 $BAR
1.5       minionto  148:        fi
1.1       bountyht  149:
                    150:        mtstatus "Waiting"
1.5       minionto  151:        sleep 5; GetPIDS "$WORLDDIR" "$NAME"
1.1       bountyht  152:
                    153:        if [ "x$FOO$BAR" == "x" ]; then
                    154:                mtstatus "Ok"
                    155:        else
                    156:                mtstatus "Waiting."
1.5       minionto  157:                sleep 5; GetPIDS "$WORLDDIR" "$NAME"
1.1       bountyht  158:                if [ "x$FOO$BAR" == "x" ]; then
                    159:                        mtstatus "Ok"
                    160:                else
                    161:                        mtstatus "Failed"; mtinfo "Error: Stop of $NAME failed\nTry once more, then consult a sysadmin"; exit 1
                    162:                fi
                    163:        fi
                    164: }
                    165:
                    166: restartMT() {
                    167:        SetWorld "$1"
                    168:        /usr/bin/mtctl stop "$1"|| exit 1
                    169:        /usr/bin/mtctl start "$1" || exit 1
                    170: }
                    171:
                    172: statusMT() {
1.7     ! minionto  173:        SetWorld "$1"
        !           174:        GetPIDS "$WORLDDIR" "$NAME"
        !           175:        if [ "x$FOO$BAR" \!= "x" ]; then
        !           176:                STATUS="Online"
        !           177:        else
        !           178:                STATUS="Offline"
        !           179:        fi
        !           180:        LASTLOG="`tail -n 5 $LOGDIR/$NAME.log 2> /dev/null`"
        !           181:        echo -e "mtctl.$1 - The Minetest Server Control\n   Active: $STATUS\n  Process: $FOO\n Main PID: $BAR\n\n$LASTLOG"
1.1       bountyht  182: }
                    183:
                    184: listMT() {
                    185:        for WORLDNAME in `ls $WORLDBASE 2> /dev/null | grep '^[a-zA-Z0-9]*$' | sort`; do
                    186:                SetWorld "$WORLDNAME"
1.7     ! minionto  187:                mtinfo "World: $WORLDNAME, Port: $PORT, Owner: $OWNER"
1.1       bountyht  188:        done
                    189: }
                    190:
                    191: createMT() {
                    192:        NAME=$1; if [ "x$NAME" == "x" ]; then mthelp; exit 1; fi
                    193:        if [ "x$NAME" == "x" ]; then echo -e "Failed\nError: Worlds need a name\n"; exit 1; else if [ -d $WORLDBASE/$NAME ]; then echo -e "Failed\nError: World already exist\n"; exit 1; else echo -e "Server name: Ok"; fi; fi
                    194:        echo -ne "\nServer Description: "; read SERVER_DESCRIPTION
                    195:        PortCheck () {
1.7     ! minionto  196:                CHECK='yes'; if [ -z "${PORT##*[!0-9]*}" ]; then CHECK='no'; ERROR="Ports are only numeric"; return; fi; for x in `ls $WORLDBASE | sort`; do export WCFILE=$WORLDBASE/$x/world.conf; if [ -f $WCFILE ]; then export PORTF=`grep '^port.*=' $WCFILE | sed -e "s/^.*= *//" -e "s/ .*//"`; if [ "x$PORTF" == "x$1" ]; then CHECK='no'; ERROR="Port already in use"; return; fi; fi; done
1.1       bountyht  197:        }
1.7     ! minionto  198:        while true; do
        !           199:                echo -ne "\nPort: "; read PORT; PortCheck $PORT; if [ "$CHECK" == "no" ]; then echo -e "Failed\nError: $ERROR"; exit 1; else echo -e "Ok"; break; fi;
        !           200:        done
1.1       bountyht  201:        echo -ne "\nMessage Of The Day [MOTD]: "; read MOTD; echo -ne "\nSeed: "; read SEED; echo -ne "\nCreative (true/false): "; read CREATIVE_MODE
                    202:        echo -ne "\nEnable Damage (true/false): "; read ENABLE_DAMAGE; echo -ne "\nEnable Player Versus Player [PVP] (true/false): "; read ENABLE_PVP
                    203:        echo -ne "\nUsername: "; read USERNAME
                    204:
                    205:        cd $WORLDBASE; mkdir $NAME; cd $NAME
1.3       minionto  206:        echo -e "server_name = $NAME\nserver_description = $SERVER_DESCRIPTION\nport = $PORT\nmotd = $MOTD\nfixed_map_seed = $SEED\ncreative_mode = $CREATIVE_MODE\nenable_damage = $ENABLE_DAMAGE\nenable_pvp = $ENABLE_PVP\nname = $USERNAME\nserver_announce = true\nserverlist_url = servers.minetest.net\nsqlite_synchronous = 0\nserver_unload_unused_data_timeout = 900\nserver_map_save_interval = 900.0" > world.conf
1.5       minionto  207:        echo -e "creative_mode = $CREATIVE_MODE\nenable_damage = $ENABLE_DAMAGE\nbackend = SQLite3\nplayer_backend = SQLite3\nmod_storage_backend = SQLite3\nauth_backend = SQLite3\ngameid = minetest\nworld_name = $NAME" > world.mt
1.1       bountyht  208:        echo -ne "\nWorld created!\nWant to start the world?(yes/no): "; read startit
                    209:        if [[ "$startit" == "yes" ]]; then /usr/bin/mtctl start $NAME; fi
                    210:        echo -e "\nSuccess: \033[1;32mDone \033[m\nFeel free to join your new server at port $PORT"
                    211: }
                    212:
1.3       minionto  213: backupMT() {
                    214:        SetWorld "$1"
                    215:        # Backup script from mtlbak by Minix
                    216:        # Copyright (C) 2021 Minix from FreedomTest (freedomtest@protonmail.com)
                    217:
                    218:        BACKUP_DIR="$CONFDIR/backups/$NAME"
                    219:        LOG_FILE="$LOGDIR/backup_$NAME.log"
                    220:        mkdir -p $BACKUP_DIR
                    221:        echo -ne "" >> $LOG_FILE
                    222:
                    223:        if [ -f /tmp/$(basename $WORLDDIR)_local_backup_in_progress ]; then
                    224:                echo "\nBackup for $(basename $WORLDDIR) on $(date) aborted because another backup is already in progress, this may be caused by a backup that is taking longer than expected" >> $LOG_FILE
                    225:                mtinfo "Backup for $(basename $WORLDDIR) on $(date) aborted because another backup is already in progress, this may be caused by a backup that is taking longer than expected"
                    226:                exit 1
                    227:        fi
                    228:
                    229:        touch /tmp/$(basename $WORLDDIR)_local_backup_in_progress
                    230:        rm $BACKUP_DIR/map.sqlite.tmp* 2> /dev/null #Cleaning in case of crashed attempts
                    231:
                    232:        echo -e "\n$(date) backup started" >> $LOG_FILE
                    233:        mtstatus "Backup started"
                    234:
                    235:        try=0
                    236:        while [ $try -lt 5 ]; do
                    237:                echo "Starting backup attempt #$(expr $try + 1) on $(date)" >> $LOG_FILE
                    238:                sqlite3 $WORLDDIR/map.sqlite ".backup $BACKUP_DIR/map.sqlite.tmp" 2> /dev/null
                    239:                if [ $? -eq 0 ]; then
                    240:                        mv $BACKUP_DIR/{map.sqlite.tmp,map.sqlite}
                    241:                        #Backup auth.sqlite and players.sqlite files properly
                    242:                        until sqlite3 $WORLDDIR/auth.sqlite ".backup $BACKUP_DIR/auth.sqlite" 2> /dev/null; do
                    243:                                continue
                    244:                        done
                    245:                        until sqlite3 $WORLDDIR/players.sqlite ".backup $BACKUP_DIR/players.sqlite" 2> /dev/null; do
                    246:                                continue
                    247:                        done
1.7     ! minionto  248:                        rsync -ptrW --delete --exclude "*.sqlite" $WORLDDIR/ $BACKUP_DIR/
1.3       minionto  249:                        echo "Backup finished succesfully on $(date)" >> $LOG_FILE
                    250:                        mtstatus "Backup success"
                    251:                        rm /tmp/$(basename $WORLDDIR)_local_backup_in_progress 2> /dev/null
                    252:                        exit 0
                    253:                else
                    254:                        rm $BACKUP_DIR/map.sqlite.tmp 2> /dev/null
                    255:                        try=$(expr $try + 1)
                    256:                        if [ $try -eq 5 ]; then
                    257:                                echo "Backup failed 5 times, aborting on $(date)" >> $LOG_FILE
                    258:                                mtstatus "Backup failed"
                    259:                                rm /tmp/$(basename $WORLDDIR)_local_backup_in_progress 2> /dev/null
                    260:                                exit 1
                    261:                        else
                    262:                                echo "map.sqlite backup attempt #$try failed, retrying in 60 seconds" >> $LOG_FILE
                    263:                                sleep 60
                    264:                        fi
                    265:                fi
                    266:        done
                    267: }
                    268:
                    269:
1.1       bountyht  270: #---------------------------------------------------------------------
                    271: # Handle the actions
1.2       bountyht  272: ACTION="$1"
1.1       bountyht  273:
                    274: case $ACTION in
                    275:        start)
1.2       bountyht  276:                mtsetup
1.1       bountyht  277:                startMT "$2"
                    278:                ;;
                    279:        stop)
1.2       bountyht  280:                mtsetup
1.1       bountyht  281:                stopMT "$2"
                    282:                ;;
                    283:        restart)
1.2       bountyht  284:                mtsetup
1.1       bountyht  285:                restartMT "$2"
                    286:                ;;
                    287:        status)
1.2       bountyht  288:                mtsetup
1.1       bountyht  289:                statusMT "$2"
                    290:                ;;
                    291:        list)
1.2       bountyht  292:                mtsetup
1.1       bountyht  293:                listMT
                    294:                ;;
                    295:        create)
1.2       bountyht  296:                mtsetup
1.1       bountyht  297:                createMT "$2"
1.7     ! minionto  298:                ;;
        !           299:        backup)
        !           300:                mtsetup
        !           301:                backupMT "$2"
1.1       bountyht  302:                ;;
                    303:        version)
                    304:                mtinfo "Version: $VERSION"
                    305:                ;;
                    306:        check_updates)
                    307:                NEWESTVERSION=$(curl https://cvsweb.planetofnix.com/cgi-bin/cvsweb/~checkout~/mtctl/version.txt?content-type=text/plain 2> /dev/null)
                    308:                if [ "$NEWESTVERSION" \!= "$VERSION" ]; then
                    309:                        mtinfo "Update avaible!\n\nInstalling update NOW!"
1.4       minionto  310:                        curl -sSL https://ircforever.org/mtctl.php | $SHELL
1.1       bountyht  311:                fi
1.2       bountyht  312:                ;;
1.1       bountyht  313:        help)
                    314:                mthelp
                    315:                ;;
                    316:        *)
                    317:                mthelp
                    318:                ;;
                    319: esac
                    320:
                    321:
                    322: #---------------------------------------------------------------------
                    323: # Final

CVSweb