我可以使用什么逻辑来恢复中断的shell脚本?

时间:2011-02-15 12:22:22

标签: bash function shell menu

我写了一个大脚本来运行一系列测试。每个测试都是一个独立的功能,我将这些功能串行调用以完成工作。

我现在想要从中断的最后一个函数中恢复脚本运行(例如,在系统挂起的情况下)。我现在使用的逻辑是将进度状态写入文件,然后检查文件内容以确定从何处启动脚本并从那里继续。

但是,我无法继续使用此逻辑,因为我想在脚本中引入一个菜单,我希望能够从中选择:

1)从头到尾运行所有测试
2)运行单独测试(带有单独测试选项的另一个菜单)
3)从上次中止恢复

我已经编写了菜单代码,但仍然没有弄清楚如何使用菜单系统中使用的case构造来适应我现有的逻辑。我对目前正在使用的最后一次中止逻辑的当前简历感到不满,这是:

fn1()
{
  #do a bunch of things
  echo 1 > progress.log
  fn2
}

fn2()
{
STATUS=`cat progress.log`
case "$STATUS" in 
1)
  #do a bunch of things
  echo 2 > progress.log
  fn3
;;
*)
 fn3
;;
esac
}

..
..
# and more functions in the same style as fn2
..

# main call

if [ -f progress.log ]
 fn2
else
 fn1
fi

任何更简洁的方法都可以恢复逻辑,同时将其与在需要时单独运行测试的能力相结合?感谢。

3 个答案:

答案 0 :(得分:2)

这样的事情怎么样?删除将它们链接在一起的fn1..N中的逻辑,但仍然在其中写入progress.log文件,然后执行以下操作:

runtest()
{
    # run test X where X is 1..N
    case "$1" in
    1) fn1 ;;
    2) fn2 ;;
    3) fn3 ;;
    *) echo "Invalid test number $1" ;;
    esac
}

runtests()
{
    START="$1"; shift
    [ -z "$START"] && START=1 # default to test 1
    for i in $(seq "$START" 50); do # replace 50 with max test number
        runtest $i
    done
}

# from your menu, run from start:
runtests 1
# from menu, run from progress
runtests $(< progress.log)
# from menu, run test TESTNUM
runtest $TESTNUM
# or by name (this is dangerous if you don't trust the user):
eval "$TESTNAME"

编辑:使用此版本,您可以使用测试名称替换fn1,fn2等,这样您仍然可以使用一个最常用的N接口来将它们组合在一起。

答案 1 :(得分:1)

Bash支持“案例级联”,也就是说。因此,您可以通过案例级联来写入/读取文件中的进度和相应的行为。例如

function write_progress
{
    local step_name=$1
    echo "$(date '+%F %H:%M:%S') $step_name" >> "$PROGRESS_FILE"

    if [ $? -ne 0 ]; then
        error_out "failed to update progress"
    fi
}


function read_proress
{
    local step_name
    step_name=$(tail -1 "$PROGRESS_FILE" | cut -d' ' -f 3)

    if [ $? -ne 0 ]; then
        error_out "failed to read progress"
    fi
}

case $(read_proress) in
    step1) 
        echo do_sth_for_step1
        ;&
    step2)
        echo step2_thing
        ;&
    step3)
        echo step3_thing
        ;;
esac

答案 2 :(得分:0)

如果我理解你的话,你可以使用像eval fn$(cat status)这样的东西。在每个函数的最后,您调用runnext来派生当前函数的编号,添加1并通过eval调用生成的函数。