2012-08-12 45 views
2

我試圖創建一個腳本,每天凌晨5點修剪一個Minecraft服務器的世界。到目前爲止,它運行命令/ wb $ NAME trim,其中$ NAME是世界的名稱,然後運行命令/ wb trim confirm,以初始化修剪過程。Minecraft服務器的世界邊界修剪腳本

#!/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 

有一個問題。如果在修剪過程仍在進行時嘗試再次運行它,則服務器將忽略該請求,並且腳本將繼續運行,就像沒有任何錯誤發生一樣。我想要它做的是檢查日誌,直到它發現修剪完成。整個內飾的日誌文件將是這個樣子:

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

+1

Dang,當這個被遷移的時候,我在codereview上丟失了我的答案。無論如何,使用函數+1作爲條件。但是,您可以安全地將'is_running'的第一個實例放入'main.'中。此外,請嘗試使用它而不是is_running:'is_running(){screen -ls | grep「$ SCREEN」>/dev/null; }'。不需要'if/then'或'return 0 | 1'。只是grep。準備晚餐的時間。 – 2012-08-12 15:08:07

回答

1

當腳本/函數正在運行時,您是否發現使用'.lock'文件有任何優勢,並且在任何類型的完成時都會刪除它(錯誤或除此以外)?

鎖定文件是一個具有唯一名稱的0字節(空)文件(通常與文件名相同,末尾附有'.lock')。當你的腳本運行時,檢查該文件是否存在。如果它不存在,創建它(即touch $MCPATH.lock),然後運行您的修剪命令。

雖然鎖文件確實存在,但只需wait()幾秒(或更長,如您所願),然後再次輪詢。

一旦修剪功能完成(即使它完成並出現錯誤),刪除那個.lock文件。然後像通常那樣簡單地處理錯誤(或成功)。

+0

問題是,這是一個minecraft服務器,所以所有的插件都是在服務器進程下運行的jar文件。修剪功能不是普通的bash命令,它是在bukkit服務器控制檯上運行的命令。它沒有PID號碼,它只是執行命令,(例如,它只是在bukkit服務器中啓動一個子進程,我真的不能稱之爲子進程的原因,因爲它是一個java插件,它不會獨立於bukkit運行,因此沒有它自己的PID號碼。)對不起,如果這個解釋令人困惑,如果你需要更好的解釋,我相信我能想到一些東西。 – 2012-08-29 00:26:18

+0

這是如何防止您使用鎖定文件?你不需要一個PID。等待10分鐘完成修剪後,您可以刪除腳本中的鎖定文件;這確實會阻止從前一個開始的10分鐘內開始新的修整,但是在完成之前立即開始新的修整不會有多大意義,是嗎? – Armali 2013-09-19 08:12:42