web-dev-qa-db-ja.com

期待されるシェルスクリプトで生成されたプロセスの終了コードを取得する方法

EXPECTスクリプトを実行するスクリプトと、その中に終了コードがある生成されたプロセスを実行しようとしています。しかし、生成されたプロセスの終了コードをメインスクリプトに取得できません。私は常に成功としてゼロになっています。

スクリプトは次のとおりです。

 [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"

生成されたスクリプト:

 [Linux Dev:anr ]$ cat tmp_script
 exit 3

Expectスクリプトの実行:

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

問題は、生成された出口の戻りコードを取得してスクリプトを期待できないことです。生成されたスクリプトの終了コード3をメインスクリプトにしたいのですが、メインスクリプトは終了コード3で終了する必要があります。

生成された終了コードをメインスクリプトに取得するのを手伝ってください。

20
ANR

グレンの助けを借りて、私は解決策を得ました...そして私の最終的なスクリプトは::

期待されるスクリプトは

 [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"

生成されたスクリプト:

 [Linux Dev:anr ]$ cat tmp_script
 exit 3

Expectスクリプトの実行:

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

グレンにもう一度感謝します。

11
ANR

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

expect man page から

待機[args]

生成されたプロセス(名前が付いていない場合は現在のプロセス)が終了するまで遅延します。

waitは通常、4つの整数のリストを返します。最初の整数は、待機したプロセスのPIDです。 2番目の整数は、対応するスポーンIDです。 3番目の整数は、オペレーティングシステムエラーが発生した場合は-1、それ以外の場合は0です。 3番目の整数が0の場合、4番目の整数は、生成されたプロセスによって返されるステータスです。 3番目の整数が-1の場合、4番目の整数はオペレーティングシステムによって設定されたerrnoの値です。グローバル変数errorCodeも設定されます。


変化する

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

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

次に、lassignおよびifコマンドを追加します。

31
glenn jackman

Expectヒアドキュメント内で変数を拡張することに数日間苦労した後、最終的に私は別のアプローチに出くわしました。私の要件は、コマンドとパスワードをシェル関数に渡し、期待するヒアドキュメントの一部としてリモートホストでコマンドを実行し、戻り終了コードを取得することでした。

例:

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

Shell_function <cmd> <password>
echo $?

他の人と同じように、ヒアドキュメント内で変数を展開すると問題が発生しました。これは、値を環境変数にエクスポートし、envを使用してヒアドキュメント内の変数を取得する必要があります。以来、パスワードは環境変数の一部として保存したくない引数の1つでした。したがって、ヒアドキュメントの開始を単一引用符で囲む代わりに、ヒアドキュメントの変数をエスケープしました。これにより、渡された引数を直接使用できました。

以下は最終的なスクリプトです。

#! /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 userid@hostname"
cmd_to_run="$cmd_to_run ls .sawfish"
run_with_password $my_password "$cmd_to_run"
echo "Command run code: $?"

上記のコードでは、エスケープされたexpect変数は$resultです。変数を\$resultに変更した後、スクリプトはチャームのように機能し始めました。

次の質問への回答を提供してくれたユーザーに心から感謝します。これは私の解決策に到達するための足がかりとなりました。

Douglas Leeder:期待スクリプトのヘルプ、リモートコンピューターでcatを実行し、変数への出力を取得

glenn jackman:生成されたプロセスの終了コードをExpectスクリプトで返す方法

1
learningloop

シェルで解釈されるように、expect入力で$をエスケープしてください。

0
Alex