Shell / Bash — позиционный параметр для столкновения скрипта и функции

#bash #amazon-web-services #shell #command-line-interface

Вопрос:

Мой сценарий должен принимать один параметр dms . После получения он создает несколько переменных, которые используются в качестве аргумента для retry_cli . Проблема, с которой я сталкиваюсь, связана с использованием позиционных параметров. Как обойти механизм создания скриптом переменных и использовать их в качестве параметров для запуска каждой функции?

В настоящее время кажется, что функция использует позиционные параметры, вводимые при запуске скрипта, а не те, которые созданы внутри него. В документации указано, что два $1 позиционных аргумента (для скрипта и функции) не должны быть проблемой.

 dms_name=$1
aws_region="us-east-1"
dms_arn=`aws dms describe-replication-tasks --filter Name=replication-task-id,Values="$dms_name" --query=ReplicationTasks[0].ReplicationTaskArn --output text --region "$aws_region"`

ri_arn=`aws dms describe-replication-tasks --filter Name=replication-task-id,Values=$dms_name --query=ReplicationTasks[0].ReplicationInstanceArn --region "$aws_region"`
target_arn=`aws dms describe-replication-tasks --filter Name=replication-task-id,Values=$dms_name --query=ReplicationTasks[0].TargetEndpointArn --region "$aws_region"`

ri_status=`aws dms describe-connections --filter Name=replication-instance-arn,Values=$ri_arn --query=Connections[0].Status --region "$aws_region"`
target_status=`aws dms describe-connections --filter Name=endpoint-arn,Values=$target_arn --query=Connections[0].Status --region "$aws_region"`

retry_cli () {
        local max_retry=100
        local counter=0
        local sleep_seconds=15 
        local aws_region="us-east-1"  
        until [[ $1 =~ "success" ]]
        do 
            status=`aws dms describe-connections --filter Name=$2,Values="$3" --query=Connections[0].Status --region "$aws_region"`
            [[ counter -eq $max_retry ]] amp;amp; echo "connection status of $3 failed!" amp;amp; exit 1
            ((counter  ))
            sleep $sleep_seconds
        done
        echo "connection for $3 OK!"
}

retry_cli "$ri_status" replication-instance-arn "$ri_arn"
retry_cli "$target_status" endpoint-arn "$target_arn"

echo startting dms
aws dms start-replication-task --replication-task-arn "$dms_arn" --start-replication-task-type resume-processing --region "$aws_region"
echo done
 

Ожидаемое поведение:

  1. скрипт запущен: sh script.sh dms_name
  2. заполняется каждая dms_ переменная
  3. retry_cli вызывается с 3 аргументами. Если $*_status это не похоже success на строку, то функция должна получить последнюю status с aws cli помощью command и повторять ее до тех пор, пока она не вернется success
  4. переход ко второму вызову функции

Ответ №1:

Я предполагаю, что цикл функции until выполняет повторный запуск команды до тех пор, пока не получит сообщение о состоянии, включающее строку success .

Для первого прохода until цикл проверяет первый входной параметр функции ( $1 ) для строки success .

Последующие проходы через until цикл все еще проверяют первый входной параметр функции ( $1 ) для строки success .

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

 retry_cli () {
    ...
    local status="$1"                           # new line
    until [[ "${status}" =~ "success" ]]        # modified line
    do
        ....
    done
    ...
}
 

Если это не решает проблему, то OP может захотеть предоставить более подробную информацию о проблеме (например, цикл никогда не завершается, цикл никогда не вводится, ???).

Комментарии:

1. Будет ли эта модификация по-прежнему помнить о проверке status из вызова функции для последующей проверки (в случае ошибки) status из внутреннего вызова функции?

2. @marcin2x4 в предлагаемой модификации кода status определяется локально (для функции), поэтому каждый вызов функции будет начинаться с новой копии status ; если вам нужна какая-то форма status , которая должна быть «передана» вызывающему процессу, тогда я бы предложил обновить вопрос с учетом этого факта, а также с помощьюпример того, как вы используете указанные значения в родительском скрипте; в таком сценарии мы, вероятно, захотим рассмотреть переход status от локальной переменной к nameref … но на данный момент я не хочу переусердствовать с написанием этого, если это не решает проблему

3. @marcin2x4 Я думаю, что этот ответ по-прежнему делает то, что вы хотите; вы пробовали? если он не выполняет то, что вы хотите, пожалуйста, предоставьте некоторые подробности о том, что не так / неправильно

4. если ваша версия «работала», это потому, что статус включал строку еще success до того, как функция была вызвана; проверьте содержимое ваших $ri_status $target_status переменных и перед вызовом функции; текущая функция (как показано в вопросе) никак не получит строку с ошибкой, выполните проходпройдите цикл и посмотрите $1 изменения (изменится только status переменная, и она не проверяется в until условии); в качестве проверки текущего кода: unset ri_status; retry_cli "$ri_status" replication-instance-arn "$ri_arn"

5. Работает так, как я объяснил в сообщении. Большое спасибо @markp-fuso. Похоже, как вы объяснили. Когда status не success было, цикл был инициирован, но в нем не было повторно передано значение status . Иначе — когда он получил другой статус, он не был передан внутри цикла.