2

毎日午前 5 時にマインクラフト サーバーの世界をトリミングするスクリプトを作成しようとしています。これまでのところ、コマンド /wb $NAME trim ($NAME はワールドの名前) を実行してから、コマンド /wb trim confirm を実行して、トリミング プロセスを初期化しています。

#!/bin/bash
# /usr/local/bin/trim
# 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
            echo "Running /wb trim confirm..."
            as_user "screen -p 0 -S $SCREEN -X eval 'stuff \"wb trim confirm\"\015'"
            echo "Waiting 10 minutes for trim to complete"
            sleep 600   # Wait 10 minutes (600 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

1 つの問題があります。トリミング プロセスがまだ行われている間に再度実行を試みると、サーバーはその要求を無視し、スクリプトは何も問題がなかったかのように実行し続けます。私がやりたいことは、トリムが完了するまでログをチェックすることです。トリム全体のログ ファイルは次のようになります。

2012-08-12 03:58:08 [INFO] World trimming task is ready for world "world", trimming the map past 208 blocks beyond the border (default 208), and the task will try to process up to 5000 chunks per second (default 5000).
2012-08-12 03:58:08 [INFO] This process can take a while depending on the world's overall size. Also, depending on the chunk processing rate, players may experience lag for the duration.
2012-08-12 03:58:08 [INFO] You should now use wb trim confirm to start the process.
2012-08-12 03:58:08 [INFO] You can cancel at any time with wb trim cancel, or pause/unpause with wb trim pause.
2012-08-12 03:58:10 [INFO] WorldBorder map trimming task started.
2012-08-12 03:58:35 [INFO] [WorldBorder] [Trim] 0 entire region(s) and 216 individual chunk(s) trimmed so far (11.8% done)
2012-08-12 04:00:04 [INFO] [WorldBorder] [Trim] 0 entire region(s) and 1016 individual chunk(s) trimmed so far (25.5% done)
2012-08-12 04:01:55 [INFO] [WorldBorder] [Trim] 0 entire region(s) and 1975 individual chunk(s) trimmed so far (36.6% done)
2012-08-12 04:03:18 [INFO] [WorldBorder] [Trim] 0 entire region(s) and 2718 individual chunk(s) trimmed so far (45.2% done)
2012-08-12 04:03:58 [INFO] [WorldBorder] [Trim] 0 entire region(s) and 3084 individual chunk(s) trimmed so far (52.7% done)
2012-08-12 04:04:12 [INFO] [WorldBorder] [Trim] 0 entire region(s) and 3203 individual chunk(s) trimmed so far (61.1% done)
2012-08-12 04:05:07 [INFO] [WorldBorder] [Trim] 0 entire region(s) and 3690 individual chunk(s) trimmed so far (73.5% done)
2012-08-12 04:05:53 [INFO] [WorldBorder] [Trim] 0 entire region(s) and 4080 individual chunk(s) trimmed so far (100.0% done)
2012-08-12 04:05:53 [INFO] [WorldBorder] [Trim] task successfully completed!

もちろん、ログにはワールド境界情報だけでなく、人々のチャットも含まれ、発生したすべてのログが記録されます. したがって、ログの最後の 10 行を追跡して、10 行が経過したかどうかを確認することはできません (たとえば、最後の 10 行を確認する前にスクリプトが待機する間隔で 10 行を超えるエラーを出力するエラー)。 、終了したことを認識する原因となるものを見つけることは決してできないため、何かがおかしいことに気付くまで、貴重なリソースを使い果たし、世界がトリミングされるのを防ぎながら、永遠に待機します。自動化されてから数日、場合によっては数週間かかります。

完了時に停止する必要があるだけでなく、そのワールドについてのみ、ワールドのトリミングを開始した時間と分を記録し、その後のみチェックする必要があります。そうしないと、そのワールドのログに「タスクが正常に完了しました」が既に存在し、スクリプトがほぼ即座に停止するため、問題が発生します。誰もこれに対する解決策を見ていますか? 考えただけで頭が痛くなる… :P

4

1 に答える 1

1

スクリプト/関数の実行中に「.lock」ファイルを使用する利点を見つけ、あらゆる種類の完了 (エラーまたはその他) でそれを削除しますか?

ロック ファイルは、一意の名前を持つ 0 バイト (空) のファイルです (通常はファイル名と同じ名前で、最後に「.lock」が追加されます)。スクリプトを実行したら、そのファイルの存在を確認します。存在しない場合は、作成して (つまりtouch $MCPATH.lock)、trim コマンドを実行します。

そのロック ファイル存在する間は、単純wait()に数秒間 (または必要に応じてそれ以上)、再度ポーリングします。

トリム機能が完了したら (エラーで完了した場合でも)、その.lockファイルを削除します。次に、通常どおりにエラー (または成功) を処理します。

于 2012-08-28T20:32:42.117 に答える