Как получить код выхода порожденного процесса в оболочке оболочки script?

Я пытаюсь выполнить script, который выполняет EXPECT script и порожденный процесс, в котором есть код выхода. Но я не могу получить код выхода порожденного процесса на главный script. Я всегда получаю нулевой успех.

Ожидание script:

 [Linux Dev:anr ]$ cat testexit.sh
 #!/bin/bash
 export tmp_script_file="/home/anr/tmp_script_temp.sh"
 cp /home/anr/tmp_script $tmp_script_file
 chmod a+x $tmp_script_file
 cat $tmp_script_file
 expect << 'EOF'
 set timeout -1
 spawn  $env(tmp_script_file)
 expect {
 "INVALID "  { exit 4 }
 timeout     { exit 4 }
 }
 EOF
 echo "spawned process status" $?
 rm -f $tmp_script_file
 echo "done"

Порожденный script:

 [Linux Dev:anr ]$ cat tmp_script
 exit 3

Выполнение Expect script:

 [Linux Dev:anr ]$ ./testexit.sh
 exit 3
 spawn /home/anr/tmp_script_temp.sh
 spawned process status 0
 done

Проблема в том, что я не могу получить возвращаемый код возврата, чтобы ожидать script. Я хочу, чтобы код выхода 3 порожденного script на главный script и основной script должен был выйти с кодом выхода 3.

Пожалуйста, помогите мне получить порожденный код выхода на главный script.

Ответ 1

С помощью glenn я получил решение.. и мой последний script is::

Ожидайте script

 [Linux Dev:anr ]$ cat testexit.sh
 #!/bin/bash
 export tmp_script_file="/home/anr/tmp_script_temp.sh"
 cp /home/anr/tmp_script $tmp_script_file
 chmod a+x $tmp_script_file
 cat $tmp_script_file
 expect << 'EOF'
 set timeout -1
 spawn  $env(tmp_script_file)
 expect {
 "INVALID "  { exit 4 }
 timeout     { exit 4 }
 eof
 }

 foreach {pid spawnid os_error_flag value} [wait] break

 if {$os_error_flag == 0} {
     puts "exit status: $value"
     exit $value
 } else {
     puts "errno: $value"
     exit $value
 }
 EOF
 echo "spawned process status" $?
 rm -f $tmp_script_file
 echo "done"

Порожденный script:

 [Linux Dev:anr ]$ cat tmp_script
 exit 3

Выполнение Expect script:

 [Linux Dev:anr ]$ ./testexit.sh
 exit 3
 spawn /home/anr/tmp_script_temp.sh
 exit status: 3
 spawned process status 3
 done

Спасибо Гленн еще раз.

Ответ 2

Вы получаете статус выхода созданного процесса с помощью команды wait:

expect <<'END'
log_user 0
spawn sh -c {echo hello; exit 42}
expect eof
puts $expect_out(buffer)

lassign [wait] pid spawnid os_error_flag value

if {$os_error_flag == 0} {
    puts "exit status: $value"
} else {
    puts "errno: $value"
}
END
hello

exit status: 42

На странице ожидать man

wait [args]

задерживается до тех пор, пока не завершится процесс порождения (или текущий процесс, если ни один из них не указан).

     

wait обычно возвращает список из четырех целых чисел. Первое целое число - это pid процесса, который ожидался. Второе целое - это соответствующий идентификатор spawn. Третье целое число равно -1, если произошла ошибка операционной системы, или 0 в противном случае. Если третье целое число равно 0, четвертое целое число - это статус, возвращаемый порожденным процессом. Если третье целое число равно -1, четвертое целое число - это значение errno, установленное операционной системой. Также устанавливается глобальная переменная errorCode.


Изменить

expect {
"INVALID "  { exit 4 }
timeout     { exit 4 }
}

к

expect {
    "INVALID "  { exit 4 }
    timeout     { exit 4 }
    eof
}

Затем добавьте команды lassign и if.

Ответ 3

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

Пример:

function shell_function {
   # Get the command and password as arguments
   # Run command using expect
   # Return the exit code
}

shell_function <cmd> <password>
echo $?

Как и у всех остальных, расширение переменной внутри heredoc было проблемой, которая требовала экспорта значения в переменную окружения и использования env для получения переменной внутри heredoc. Поскольку пароль был одним из аргументов, я не хотел хранить его как часть переменной окружения. Таким образом, вместо включения открытия heredoc одинарными кавычками, переменные heredoc были экранированы. Это позволило прямое использование переданных аргументов.

Ниже приведен финальный сценарий:

#! /bin/bash
# This function runs a command like 'ssh' and provides the password
function run_with_password {
    cmd="$2"
    paswd="$1"
    expect << END
        set timeout 60
        spawn $cmd
        expect {
            "yes/no" { send "yes\r" }
            "*assword*" { send -- $paswd\r }
        }
        expect EOF
        catch wait result
        exit [lindex \$result 3]
END
}

my_password="AnswerIS42Really?"
cmd_to_run="ssh [email protected]"
cmd_to_run="$cmd_to_run ls .sawfish"
run_with_password $my_password "$cmd_to_run"
echo "Command run code: $?"

В приведенном выше коде экранированная ожидаемая переменная равна $result. После изменения переменной на \$result скрипт начал работать как charm.

Я искренне благодарю пользователей, которые предоставили ответы на следующие вопросы, которые послужили отправной точкой для достижения моего решения.

Дуглас Лидер: помогите с ожидаемым скриптом, запустите cat на удаленном компе и получите вывод его в переменную

Гленн Джекман: Как вернуть порожденный код завершения процесса в сценарии Expect?

Ответ 4

Обязательно избегайте ввода $в ожидании, чтобы он интерпретировался оболочкой.