在运行另一个命令之前,我如何阅读日志以检查命令是否已完成执行?

时间:2012-06-17 14:16:10

标签: bash

这是我写的一个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

2 个答案:

答案 0 :(得分: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
}

答案 1 :(得分: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!之后的一行写入日志文件。