1

I want to print output of below loop into columns, Can anybody please adivse me on this.

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

Current Output :

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

Expected Output:

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

My Goal is to achieve above formatting.

  • how many columns do you expect to have ? is it fixed or is it ever growing ? – pLumo Mar 8 at 13:26
  • Hi Rovo, thanks for reply. It’s growing, depends on number of ip in loop list. – Sandeep Singh Mar 8 at 13:47
2

If you instead of

>> /tmp/user_count.txt

would write in a new file for each server:

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

it would be very easy:

paste user_count_*.txt | column -tn
1

The difficult bit with this question is actually to format the output in columns.

Suppose that you have an existing file with|-delimited columns, and you want to append a new column to that. If you use paste as

paste -d '|' file newdata

and your file is not of the same length as the existing file, then the number of columns in the output will vary, and adding further columns would potentially make it even worse. Reading the final result would be difficult to do correctly.

Instead, here's an awk program that reads an existing file, and adds the data read from standard input to a new column in that file. The output will have a fixed number of columns, all the way from the first line to the last, regardless of whether the new column data has fewer or more lines than the existing data.

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
    }
}

Ok, let us then use this to create a small shell script that will SSH over to a number of servers, whose names are listed in a file, and extract the users from the /etc/passwd file on each:

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

Here, append_column.awk is a file consisting of the awk program at the top of this answer.

The script reads the $serverlist file in a loop and calls ssh -n to get the /etc/passwd file. The -n option is needed with ssh as ssh would otherwise read from the same $serverlist file as the loop is iterating over.

The usernames are extracted using cut.

The { ... } bit outputs a short header, and then passes on the usernames unmodified through a call to cat.

The awk program is used to add columns to the output file by reading from a temporary file (which will contain the result collected so far), and the resulting data is copied back to the temporary file.

After the end of the loop, the file in $tmpfile (as well as $output actually) will contain the data that you want as |-delimited fields. To clean this up, we call another short in-line awk script that formats the columns of the output file as left-justified, 20 character long, text fields.

0

You can try by below method

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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.