23

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

#!/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

ここでは、「echo $HOST」および「pwd」コマンドを実行しており、「echo $?」で終了ステータスを取得しています。

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

ヘルプとコードをいただければ幸いです。

4

4 に答える 4

37

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

$ ssh localhost exit 10
$ echo $?
10

したがって、sshコマンドが終了した後、単にチェックすることができます$?。戻り値をマスクしないようにする必要があります。たとえば、sshコマンドは次のように終了します。

echo $?

これは常に0を返します。おそらく必要なのは次のようなものです。

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

次のように書くこともできます。

while read HOST; do
  echo $HOST
  if ssh $HOST 'somecommand' < /dev/null
  if [ $? -eq 0 ]; then
    echo SUCCESS
  else
    echo FAIL
done
于 2013-03-13T16:50:37.443 に答える
2

次のように簡単に終了ステータスを変数に割り当てることができます。

variable=$?

検査しようとしているコマンドの直後。echo $?または新しい値が$?終了コードecho(通常は 0)になる前にしないでください。

于 2016-06-02T18:14:34.883 に答える
0

おそらく、反対側でログ ファイルを準備し、次のように stdout にパイプします。

ssh -n user@example.com 'x() { local ret; "$@" >&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基本的に、このラッパーで呼び出したいリモートのすべてにプレフィックスを付けるだけです。コマンドの終了コードを変更しないため、条件に対しても機能します。

このコマンドは簡単にループできます。

この例では、次のようにログに書き込みます。

[20141218-174611 0] true
[20141218-174611 1] false
[20141218-174611 77] sh -c exit 77

もちろん、より解析しやすくしたり、ログファイルがどのように見えるかを希望に合わせたりすることができます。stdoutリモート プログラムのキャッチされていない法線が に書き込まれることに注意してstderrください ( のリダイレクトを参照x())。

ログファイルのコマンド出力をキャッチして準備するためのレシピが必要な場合は、https://gist.github.com/hilbix/c53d525f113df77e323dからのキャッチャーのコピーを参照してください。 「シェルの現在のコンテキストで何かを実行し、リターンコードを乱すことなく stdout + stderr を後処理します」:

# 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 "$@" "$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 番目の行を参照してください (下にスクロール)

于 2014-12-18T17:01:32.497 に答える
0

興味深いアプローチは、バッククォートを使用してローカル変数に設定された各 ssh コマンドの出力全体を取得することです。

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

この後、使用して結果awkを分割MYVARし、bash テストを続行できます。

于 2013-03-13T17:46:16.803 に答える