列別にSSHループ出力を印刷

列別にSSHループ出力を印刷

次のループの出力を列に印刷したいと思います。誰でもこれを提案できますか?

#!/bin/bash
DATE=`date "+%d-%m-%Y_%H-%M-%S"`

### Find User from Server with Expiry Date 
for i in `cat /home/sandeepj/Project_user_count/serverlist2`;
do
echo -e "**********"
echo -e "$i"
ssh sandeepj@${i} "awk -F\: '{print \$1}' /etc/passwd" 
done >> /tmp/user_count.txt

現在の出力:

**********  
10.25.59.3
root
bin
daemon
adm
lp
sync
**********
10.25.59.13
root
bin
daemon
adm
lp
sync

予想出力:

**********  **********
10.25.59.3  10.25.59.13
root        root
bin         bin
daemon      daemon
adm         adm
lp          lp
sync        sync

私の目標は上記の形式を達成することです。

答え1

場合は、代わりに

>> /tmp/user_count.txt

各サーバーに新しいファイルが作成されます。

do
   (
   printf '%s\n%s\n' '**********' "$i"
   ssh sandeepj@${i} "awk -F\: '{print \$1}' /etc/passwd" 
   ) > "/tmp/user_count_${i}.txt"
done

これは簡単です:

paste user_count_*.txt | column -tn

答え2

これ硬い問題は、実際には列ごとに出力形式を指定することです。

別々の列を含む既存のファイルがあり、|ここに新しい列を追加したいとします。paste次のように使用する場合

paste -d '|' file newdata

ファイルの長さが既存のファイルと異なる場合は、出力の列数が異なり、列を追加すると状況が悪化する可能性があります。最終結果を正しく読むのは難しいです。

代わりに、ここのプログラムはawk既存のファイルを読み込み、標準入力から読み取ったデータをファイルの新しい列に追加します。出力には、新しい列データに既存のデータより少ない行があるかどうかに関係なく、最初の行から最後の行まで固定数の列が含まれます。

BEGIN { OFS = FS }

FNR == 1 {
    # We assume that all lines have the same number of columns.
    nf = NF
}

{
    # Read new column from stdin (clear col if failing).
    if ((getline col <"/dev/stdin") != 1)
        col = ""

    # Add new column (possibly empty) and print.
    $(nf + 1) = col
    print
}

END {
    # We only need to do something here if the new column
    # data is longer than the existing data.

    $0 = "" # Clear current line.

    # Add data from stdin until there is no more to read.
    while ((getline col <"/dev/stdin") == 1) {
        $(nf + 1) = col
        print
    }
}

さて、これを使用して、ファイルに名前がリストされている複数のサーバーにSSHで接続し、/etc/passwd各サーバーのファイルからユーザーを抽出する小さなシェルスクリプトを作成しましょう。

#!/bin/sh

outfile=/tmp/outfile
serverlist=servers.list

tmpfile=$( mktemp )

while read -r server; do
    ssh -n "$server" cat /etc/passwd |
    cut -d : -f 1 |
    {
        echo '****************'
        printf '%s\n\n' "$server"
        cat
    } |
    awk -F '|' -f append_column.awk "$tmpfile" >"$outfile"
    cp "$outfile" "$tmpfile"
done <"$serverlist"

awk -F '|' '{ for (i=1; i<=NF; ++i) $i = sprintf("%-20s", $i); print }' "$tmpfile" >"$outfile"

rm -f "$tmpfile"

append_column.awkこの回答の上部にあるプログラムで構成されたファイルは次のとおりです。awk

スクリプトは$serverlistループからファイルを読み取り、ファイルをインポートssh -nするために呼び出します。このオプションは必須です。それ以外の場合は、ループが繰り返されると同じファイルから読み込まれます。/etc/passwd-nsshssh$serverlist

ユーザー名はを使用して抽出されますcut

この{ ... }ビットは短いヘッダーを出力し、呼び出しによって変更されていないユーザー名を渡しますcat

このawkプログラムは、一時ファイル(これまでに収集された結果を含む)を読み取り、結果データを一時ファイルにコピーして出力ファイルに列を追加するために使用されます。

ループが終わると、ファイルには目的のデータが別々のフィールドとして含まれます$tmpfile(実際には含まれます)。この問題を解決するには、出力ファイルの列を左揃えの20文字のテキストフィールドにフォーマットする別の短いインラインスクリプトを呼び出します。$output|awk

答え3

次の方法を試すことができます。

for i in `cat serverlist`
do
echo " "| sed "s/.*/====================================/g"
echo $i
ssh -o  'StrictHostKeyChecking no' $i -A "cat /etc/passwd| awk -F ':' '{print $1}'">$i_host_username_details.txt
done
paste *_host_username_details.txt

関連情報