2012-06-17 79 views
0

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

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

请参阅[进程管理](http://mywiki.wooledge.org/ProcessManagement),并且不要在$(ls)中为var进行操作 - 您只需要一个glob。使用'((a ++))'增加变量。你这样做,'a'是一个不断增长的'1 + 1 + 1 + 1 ... + 1'串(它在数组的下标中得到数学计算)。 –

+0

你不需要'bash -c“$ 1”' - 你可以直接使用'$ 1'(单独一行)。 –

+0

Pastebin链接已损坏;示例日志可以在[我的世界服务器的边界修剪脚本]找到(http://stackoverflow.com/questions/11922982/world-border-trim-script-for-minecraft-server)。 – Armali

回答

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 
} 
+0

'stuff'是一个_screen_命令;因此,它不能在_screen_之外运行。 – Armali

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!的一个被写入日志文件之后。