2013-03-13 83 views
10

シェルスクリプトのループでは、さまざまなサーバーに接続していくつかのコマンドを実行しています。ここでは例シェルスクリプトsshコマンドの終了ステータス

#!/bin/bash 
FILENAME=$1 
cat $FILENAME | while read HOST 
do 
    0</dev/null ssh $HOST 'echo password| sudo -S 
    echo $HOST 
    echo $?  
    pwd 
    echo $?' 
done 

のために私は、「エコーの$ HOST」と「PWD」コマンドを実行していると私は経由終了ステータス取得しています「エコー$を?」。

私の質問は、リモートでいくつかの変数で実行したコマンドの終了ステータスを保存し、(コマンドが成功したかどうかに基づいて)ログをローカルファイルに書きたいということです。

どのようなヘルプとコードに感謝します。

答えて

19

sshは、リモートコマンドの終了コードで終了します。たとえば:

$ ssh localhost exit 10 
$ echo $? 
10 

だからあなたsshコマンドが終了した後、あなたは単に$?を確認することができます。あなたは戻り値をマスクしないようにする必要があります。

while read HOST; do 
    echo $HOST 
    if ssh $HOST 'somecommand' < /dev/null; then 
    echo SUCCESS 
    else 
    echo FAIL 
done 

あなたはまた、このようにそれを書くことができます::

echo $? 

これは常に返します0あなたはおそらくしたいことより、このようなものである:例えば、あなたのsshコマンドがで仕上げます

while read HOST; do 
    echo $HOST 
    if ssh $HOST 'somecommand' < /dev/null 
    if [ $? -eq 0 ]; then 
    echo SUCCESS 
    else 
    echo FAIL 
done 
+0

終了ステータスを抽出できるように、各コマンドを実行するために個別にsshを実行する必要があると言っていますか?私は実際のコードで同じsshセッションで少なくとも5つのコマンドを実行しようとしています。 –

+0

こんにちは、@ラルス。 'ssh localhost exit 10'が何を意味するのか説明できますか?これは、状態コードとして明示的に10を指定してssh localhostを実行することを意味しますか?ここで、exitはsshまたはlinuxコマンドの 'exit'のオプションですか? –

+0

sshコマンドの基本的な構文は 'ssh 'です。したがって、上記の答えでは、 'exit 10'はリモートシェルに渡されるコマンドです。 – larsks

0

面白いアプローチは、バックスティックを使用してローカル変数内の各sshコマンドセットの全出力を取得することです(簡単に「:」と言う)somあなたは結果にMYVARを分割し、bashのテストを継続するawkを使用することができ、この後

export MYVAR=`ssh $HOST 'echo -n ${HOSTNAME}\:;pwd'` 

:ようething。

ssh -n [email protected] 'x() { local ret; "[email protected]" >&2; ret=$?; echo "[`date +%Y%m%d-%H%M%S` $ret] $*"; return $ret; }; 
x true 
x false 
x sh -c "exit 77";' > local-logfile 

基本的にはちょうどあなたがこのxラッパーを起動するリモート上のすべてを接頭辞:

0

おそらく、このように、それが標準出力にログ反対側のファイルやパイプを準備します。これは、コマンドの終了コードを変更しないため、条件付きでも機能します。

このコマンドは簡単にループできます。あなたはそれがより良い解析可能にするか、ログファイルがどのように見えるものとどのようにあなたのwhishesにそれを適応させることができ

もちろん
[20141218-174611 0] true 
[20141218-174611 1] false 
[20141218-174611 77] sh -c exit 77 

この例のようなログに何かに書き込みます。リモートプログラムのアンカーされた通常stdoutstderrに書き込まれます(リダイレクションはx()を参照してください)。

ログファイルのコマンドの出力をキャッチして出力を準備するためのレシピが必要な場合は、https://gist.github.com/hilbix/c53d525f113df77e323dのようなキャッチャーのコピーがありますが、これは "現在のシェルコンテキストで何かを実行する「リターン・コードを乱すことなく、後処理STDOUT +標準エラー出力:

# Redirect lines of stdin/stdout to some other function 
# outfn and errfn get following arguments 
# "cmd args.." "one line full of output" 
: catch outfn errfn cmd args.. 
catch() 
{ 
local ret o1 o2 tmp 
tmp=$(mktemp "catch_XXXXXXX.tmp") 
mkfifo "$tmp.out" 
mkfifo "$tmp.err" 
pipestdinto "$1" "${*:3}" <"$tmp.out" & 
o1=$! 
pipestdinto "$2" "${*:3}" <"$tmp.err" & 
o2=$! 
"${@:3}" >"$tmp.out" 2>"$tmp.err" 
ret=$? 
rm -f "$tmp.out" "$tmp.err" "$tmp" 
wait $o1 
wait $o2 
return $ret 
} 

: pipestdinto cmd args.. 
pipestdinto() 
{ 
local x 
while read -r x; do "[email protected]" "$x" </dev/null; done 
} 

STAMP() 
{ 
date +%Y%m%d-%H%M%S 
} 

# example output function 
NOTE() 
{ 
echo "NOTE `STAMP`: $*" 
} 

ERR() 
{ 
echo "ERR `STAMP`: $*" >&2 
} 

catch_example() 
{ 
# Example use 
catch NOTE ERR find /proc -ls 
} 

2

は、あなたがやってような単純な変数に終了ステータスを割り当てることができます(スクロールダウン)例えば第二の最後の行を参照してください。

var_name= $? 

検査するコマンドの直後です。前にecho $?を入力しないか、$?の新しい値が終了コードecho(通常は0)になります。

関連する問題