2012-08-12 124 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