Какую логику я могу использовать для возобновления прерванного сценария оболочки? - PullRequest
0 голосов
/ 15 февраля 2011

Я написал большой скрипт для запуска серии тестов. Каждый тест является отдельной функцией, и я вызываю эти функции последовательно, чтобы выполнить работу.

Теперь я хочу подготовить условия для возобновления работы скрипта с последней функции, в которой он был прерван (например, в случае зависания системы). Логика, которую я сейчас использую, заключается в том, чтобы записать состояние выполнения в файл, а затем проверить содержимое файла, чтобы определить, где запустить сценарий и продолжить его с этого места.

Однако я не могу продолжать использовать эту логику, потому что я хочу ввести в скрипт меню, из которого я хочу иметь возможность выбирать:

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 ]

2 голосов
/ 15 февраля 2011

Как насчет этого?Удалите логику в 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"

РЕДАКТИРОВАТЬ: в этой версии вы можете просто заменить fn1fn2 и т. д. с именами тестов, так что вы по-прежнему получаете интерфейс N для тестирования, который вы можете использовать, чтобы связать все вместе.

1 голос
/ 06 августа 2015

Bash поддерживает "case cascade", иначе проваливается. Следовательно, вы можете записывать / читать прогресс в / из файла и действовать соответственно через каскад. Например

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
0 голосов
/ 15 февраля 2011

Если я вас правильно понял, вы можете использовать что-то вроде eval fn$(cat status).В конце каждой функции вы вызываете runnext, которая получает номер текущей функции, добавляет 1 и вызывает полученную функцию через eval.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...