サーバーコマンド出力を次の行に分割

サーバーコマンド出力を次の行に分割

"pssh"を使用して1000を超えるサーバーでコマンドを実行するbashスクリプトを準備しています(/tmp/hostsに保存されています)。

pssh -h /tmp/hosts -i "uname;date"

[1] 13:10:56 [FAILURE] SERVER1 Exited with error code 255
Stderr: @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@       WARNING: POSSIBLE DNS SPOOFING DETECTED!          @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
The ECDSA host key for SERVER1 has changed,
and the key for the corresponding IP address 10.238.36.42
has a different value. This could either mean that.............
......................
[2] 13:10:56 [SUCCESS] SERVER2
Linux
Fri Jan 25 12:10:56 UTC 2019
[3] 13:10:56 [SUCCESS] SERVER3
Linux
Fri Jan 25 13:10:56 CET 2019
[4] 13:10:56 [SUCCESS] SERVER4
Linux
Fri Jan 25 12:10:56 UTC 2019
[5] 13:10:56 [SUCCESS] SERVER5
Linux
Fri Jan 25 12:10:56 UTC 2019
[6] 13:10:56 [SUCCESS] SERVER6
Linux
Fri Jan 25 12:10:56 UTC 2019

以下の出力が予想されます。警告がある場合は警告を抑制します。

[FAILURE], SERVER1, Exited with error code 255
[SUCCESS], SERVER2,Linux,Fri Jan 25 12:10:56 UTC 2019
[SUCCESS], SERVER3,Linux,Fri Jan 25 12:10:56 UTC 2019
[SUCCESS], SERVER4,Linux,Fri Jan 25 12:10:56 UTC 2019
[SUCCESS], SERVER5,Linux,Fri Jan 25 12:10:56 UTC 2019
[SUCCESS], SERVER6,Linux,Fri Jan 25 12:10:56 UTC 2019
[FAILURE], HOST1, Exited with error code 255
[FAILURE], HOST2, Exited with error code 255

答え1

@Imorgのおかげで、次のことができます。

pssh -h /tmp/hosts -i "uname;date"  | grep -o \[[A-Z][A-Z][A-Z]*\].* | sed -Ee 's/(^\[FAILURE\]) (SERVER[0-9]*) (.*)/\1, \2, \3/g' -Ee 's/(^\[SUCCESS\]) (.*)/\1, \2,'"$(uname)"','"$(date)"'/g'

したがって、grep -o \[[A-Z][A-Z][A-Z]*\].*出力は次のようになります。

[FAILURE] SERVER1 Exited with error code 255
[SUCCESS] SERVER2
[SUCCESS] SERVER3
[SUCCESS] SERVER4
[SUCCESS] SERVER5
[SUCCESS] SERVER6

そしてFAILUREとSERVERとEXITEDの間にありますsed -Ee 's/(^\[FAILURE\]) (SERVER[0-9]*) (.*)/\1, \2, \3/g'between strings containing

最初の2つの単語の間にsed -Ee 's/(^\[SUCCESS\]) (.*)/\1, \2,'"$(uname)"','"$(date)"'/g'追加して追加します。,,output of uname command, output of date command

したがって、最終出力は次のようになります。

[FAILURE], SERVER1, Exited with error code 255
[SUCCESS], SERVER2,Linux,Fri Jan 25 19:27:30 UTC 2019
[SUCCESS], SERVER3,Linux,Fri Jan 25 19:27:30 UTC 2019
[SUCCESS], SERVER4,Linux,Fri Jan 25 19:27:30 UTC 2019
[SUCCESS], SERVER5,Linux,Fri Jan 25 19:27:30 UTC 2019
[SUCCESS], SERVER6,Linux,Fri Jan 25 19:27:30 UTC 2019

答え2

質問した内容が100%確かではありませんが、次の内容が役に立つと思います。

# What you get
$ uname; date
Linux
Fri 25 Jan 13:09:13 GMT 2019

# What you want
$ echo "$(uname), $(date)"
Linux, Fri 25 Jan 13:09:42 GMT 2019

したがって、あなたのコマンドは次のようになります

pssh -h /tmp/hosts -i 'echo "$(uname), $(date)"'

(単一引用符を使用してください。ローカルシェルがプロセスサブシェルを拡張しないようにすることが重要です。)

これが行うことは、サブシェルで実行され、uname結果dateechoコマンドに変数として返すことです。上記のように:

echo "$(uname), $(date)"
# expands as
echo Linux, Fri 25 Jan 13:10:57 GMT 2019

ところで、私はpsshに慣れていません。ユーザーが/etc/groupリモートサーバーファイル(または共有認証サーバー)で定義した$ SHELLが何でも実行されているとします。そうしないと、上記のトリックが機能しない可能性があります。ただし、サーバーファームを管理するには、他のシステムを調べることをお勧めします。たとえば、SSHを使用する傾向がある場合は、Ansibleが適している可能性があります。


編集:良いです。今、いくつかの追加要件を理解しました。

失敗した最初の行だけが必要な場合は、それを削除できます。

pssh -h /tmp/hosts -i 'echo "$(uname), $(date)"' | grep -Eo '\[(SUCCESS|FAILURE)\].*$'

-E拡張正規表現をサポートするために、行全体ではなく一致するパターンのみを返すことができます(SUCCESS|FAILURE)-o

本当にカンマが必要な場合は、次の場所に追加することもできますsed

pssh -h /tmp/hosts -i 'echo "$(uname), $(date)"' | egrep -o '\[(SUCCESS|FAILURE)\].*$' | sed -r 's:(\[(SUCCESS|FAILURE)\]):\1,:'

:(上記の例でこの文字を使用したsed理由は、この文字がより読みやすく、何をしているのかを見ることができるためですが、必要に応じてより/一般的な文字に置き換えることができます。)

それがすることは、(逆参照を介して)文字列とコンマを検索または[SUCCESS]返すことです。[FAILURE]\1

例:

$ echo -e "sdfsdfsdf[FAILURE] $(uname), $(date)\nsdfsdf\nasdfsdf" | grep -Eo '\[(SUCCESS|FAILURE)\].*$' | sed -r 's:(\[(SUCCESS|FAILURE)\]):\1,:'
[FAILURE], Linux, Fri 25 Jan 16:15:03 GMT 2019

何らかの理由でthen以外のものを返すことができる場合、[SUCCESS]コード[FAILURE]は(一般的に)さらに短くなる可能性があります[A-Z]+

pssh -h /tmp/hosts -i 'echo "$(uname), $(date)"' | egrep -o '\[[A-Z]+\].*$' | sed -r 's:(\[[A-Z]+\]):\1,:'

(SUCCESS|FAILURE)[A-Z]+しかし、いくつかの偽の肯定が返される場合に備えて、今はこのバージョンを使用することをお勧めします。

関連情報