次のループの出力を列に印刷したいと思います。誰でもこれを提案できますか?
#!/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
-n
ssh
ssh
$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