0

这是我编写的一个 bash 脚本,它以 crontab 中指定的时间间隔自动修剪我的世界服务器的所有世界。它将在每个世界上一一执行“/wb $WORLD trim”命令和“/wb trim confirm”命令,其中$WORLD 是它当前正在处理的世界。通过将文件列表中的每个世界加载到 for 循环中,它将按顺序修剪每个世界。现在,由于世界修剪可能需要不同的时间,我不确定如何告诉它在尚未完成的情况下不要停止,因为每个世界只分配了 30 秒。我认为读取日志文件以获取命令的状态可能会起作用,但我不确定如何去做。我认为像“grep”和“awk”这样的东西可能会完成这项工作,但我不确定这是否会奏效,因为这似乎是一个相当复杂的障碍。有任何想法吗?我有一个日志文件的一部分,它在修剪发布的世界时打印这里是pastebin。另外,除了我可以做些什么来改进这个脚本之外,还有什么可以做的吗?我只写了几个月的代码,而且不是那么频繁,所以我通常是编程/脚本的新手。

#!/bin/bash
# Title: World Border Trim Automator
# Author: Jonathan Bondhus

######### CONFIG STARTS HERE #########

# Location of the init script
INIT_SCRIPT="/etc/init.d/minecraft"

# Name to use for the screen instance
SCREEN="minecraft"

# User that should run the server
USERNAME="minecraft"

# Path to minecraft server directory 
MCPATH="/home/${USERNAME}/minecraft"

# Where the worlds are located on the disk
WORLDSTORAGE="${MCPATH}/worlds"

######### CONFIG ENDS HERE #########

## Start of script, don't edit anything below this line unless you know what you are doing

as_user() {
    if [ $ME == $USERNAME ] ; then
        bash -c "$1"
    else
        su $USERNAME -s /bin/bash -c "$1"
    fi
}

my_trim() {
    a=1
    for NAME in $(ls $WORLDSTORAGE)
    do
        if [ -d $WORLDSTORAGE/$NAME ]
        then
            WORLDNAME[$a]=$NAME
            a=$a+1
            # Run the /wb trim command
            echo "Running /wb $NAME trim..."
            as_user "screen -p 0 -S $SCREEN -X eval 'stuff \"wb $NAME trim\"\015'"
            sleep 2     # Wait 2 seconds
            clear
            echo "Running /wb trim confirm..."
            as_user "screen -p 0 -S $SCREEN -X eval 'stuff \"wb trim confirm\"\015'"
            sleep 1
            clear
            echo "Waiting 30 seconds for trim to complete..."
            sleep 30    # Wait 30 seconds
        fi
    done
}

my_is_running(){
    # Checks for the minecraft servers screen session
    # returns true if it exists.
    if ps ax | grep -v grep | grep "$SCREEN $INVOCATION" > /dev/null
    then
        return 0
    fi
    return 1
}

my_main(){
    ME=`whoami`     # Sets $ME to equal the current user's username
    my_is_running
    if my_is_running
        then
            my_trim
        else
            echo "Server is not running... Starting..."
            my_as_user "$INIT_SCRIPT start"
            wait 100
    fi
}

my_as_user() {
    if [ $me == $username ] ; then
        bash -c "$1"
    else
        su $USERNAME -s /bin/bash -c "$1"
    fi
}

my_main
exit 0
4

2 回答 2

0

下面假设变量MCLOGFILE设置为日志文件名。

my_trim() {
    cd $WORLDSTORAGE
    for NAME in *
    do
        if [ -d $NAME ]
        then
            # Run the /wb trim command
            echo "Running /wb $NAME trim..."
            as_user "screen -p 0 -S $SCREEN -X eval 'stuff \"wb $NAME trim\"\015'"
            sleep 2     # Wait 2 seconds
            clear
            echo "Running /wb trim confirm..."
    kill `((tail -f $MCLOGFILE -n0& echo $! >&3
            as_user "screen -p 0 -S $SCREEN -X eval 'stuff \"wb trim confirm\"\015'"
            sleep 1
            clear >&2
            echo "Waiting for trim to complete..." >&2
           )|grep -q 'task successfully completed!'
          ) 3>&1|head -1
         `
        fi
    done
}

这些kill东西在那里,因为否则将继续在后台运行,直到将其写入日志文件tail之后的一行。task successfully completed!

于 2014-03-31T13:25:38.253 回答
0

你有什么理由在“屏幕”内运行“东西”?

如果你删除它,'stuff' 将同步执行,并在命令完成后返回。

my_trim() {
    a=1
    for NAME in $(ls $WORLDSTORAGE)
    do
        if [ -d $WORLDSTORAGE/$NAME ]
        then
            WORLDNAME[$a]=$NAME
            a=$a+1
            # Run the /wb trim command
            echo "Running /wb $NAME trim..."
            as_user "stuff \"wb $NAME trim\"\015" # will block here until stuff returns
            #sleep 2     # no reason this any more
            clear
            echo "Running /wb trim confirm..."
            as_user "stuff \"wb trim confirm\"\015"
            #sleep 1
            clear
            echo "Done"
            #sleep 30
        fi
    done
}
于 2012-06-17T14:44:42.387 回答