0

I've been given a task to gather some information about a number of computers here at work, and while I could manually find out the info I've decided a one liner should be able to do it. I have a list of users, access to an asset database (which has incorrect info about how much RAM is in a machine) and want to print a list where each line lists a username, hostname and amount of RAM. I've managed to get the info I need to output, but it's irritating me I couldn't get it to output as nicely as I would have liked.

The command I would have loved to have worked is below:

"command that outputs user and device info" | grep 'Dell\|HP' | awk '{printf "%-10s %s\n",$1,$NF,system("ssh " $NF " free -m | grep Mem | awk '{print $2}'")}'

It appears to fall over when I try to awk the results of the system call for ssh, with an unterminated string error at the " after $NF... I have no idea if it should fail here, or if I'm not escaping things I should in the system call etc - I've tried inserting random \ everywhere ;)

I can replace the free -m command with a "cat /proc/meminfo | head -n 1" but this puts the output on a separate line or with a "free -m | grep Mem" but this gets the whole line when I want only the second word/total RAM amount. I'd really love to have each result tidily on one line.

Is it possible to awk the output of a system call made from within another awk command? I know I would be able to do this in a script by holding info in variables and building an output line from two separate commands, but my stubborn brain wants to know how to do this as a one-liner if at all possible!

5
  • You should try it step by step, first with severall function, then combining it to a one-liner. Your problem might lie with your nested quotation. Try "ssh \$NF free -m ... " instead Commented Aug 5, 2014 at 9:56
  • use '\' before special characters eg.$ Commented Aug 5, 2014 at 9:58
  • Thanks bachN... I've tried \ but perhaps not in the right places, as I wasn't sure which of ' { and $ would be considered special characters. I will try again when I head back to work in the morning. Commented Aug 5, 2014 at 10:20
  • Thanks also Ploutox... The whole thing works if I drop | awk '{print $2}' from the end. The nested quotations work fine to be able to use $NF as the hostname for the SSH command, my issue only comes about when I try to awk the output from grepping for Mem in the output of the ssh command. If I drop the awk I get a line with username and hostname, then the whoe Mem line from free when I only want the second word/RAM amount Commented Aug 5, 2014 at 10:20
  • awk 'line1;line2;line3' infile | awk 'cmd4;cmd5;cmd6' works Commented Feb 29, 2016 at 22:39

2 Answers 2

0

You can have this:

"command that outputs user and device info" | \
    grep 'Dell\|HP' | \
    awk "{printf \"%-10s %s\\n\",\$1,\$NF,system(\"ssh \" \$NF \" free -m | grep Mem | awk '{print \$2}'\")}"

Or simply:

"command that outputs user and device info" | \
    awk "/Dell|HP/ {printf \"%-10s %s\\n\",\$1,\$NF,system(\"ssh \" \$NF \" free -m | awk '/Mem/ {print \$2}'\")}"
Sign up to request clarification or add additional context in comments.

1 Comment

Thanks... While I still get the RAM number on a separate line, appearing before the line containing the username and hostname, I at least get only the data that I'm looking for :)
0

Unless the "command that outputs user and device info" prints a variable number of fields, I really don't see why you want or need Awk here. (Even with a variable number of fields, it's not hard to avoid.)

"command that outputs user and device info" |
grep 'Dell\|HP' |
# assuming four fields, but easy to adapt, obviously
read -r user _ _ host; do
    printf "%-10s %s %d\n" "$user" "$host" $(\
       ssh "$host" free -m | awk '/Mem/ { print $2 }')
done

This has the additional benefit of inlining the memory output in the same line of output, which I understand is your preference. (Again, easy to change if not. Obviously, your original solution could be adapted to behave the same way easily just as well.)

If you want Awk for postprocessing the initial command's output, you can still avoid nested Awk invocations, which IMHO is both more elegant and readable as well as more maintainable.

"command that outputs user and device info" |
awk '/Dell|HP/ { print $1, $NF }' |
while read -r user host; do
    :

Obvioulsy, one of the key observations here is that printf is (also) a shell command, so you don't need Awk for the print formatting.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.