Reputation: 478
I have below script which returns the output of the some variables, i am using printf
to align the output format but i'm not able to make it correctly formatted either right-justify
or left-justify
.
Any help will be much appreciated.
#!/bin/bash
read -rsp $'Please Enter password below: ' SSHPASS
echo -n ""
export SSHPASS
print "\n"
printf "Hostname CPU MEM SWAP"
remote_connect() {
target_host=$1
mem=$(sshpass -e ssh -o StrictHostKeyChecking=no -q -t "$target_host" free -g | /bin/awk '/^Mem/{print $2}')
swap=$(sshpass -e ssh -o StrictHostKeyChecking=no -q -t "$target_host" free -g | /bin/awk '/^Swap/{print $2}')
cpu=$(sshpass -e ssh -o StrictHostKeyChecking=no -q -t "$target_host" grep -c proc /proc/cpuinfo)
printf "%-20s %10s %10s %5s\n" "$target_host" "${cpu} ${mem} ${swap}"
} 2>/dev/null
export -f remote_connect
< /home/cpls/mb_hosts xargs -P5 -n1 -d'\n' bash -c 'remote_connect "$@"' --
Hostname CPU MEM SWAP
cpl1855.ind-blr01.cpl.com 4 2 8
cpltp064.ind-blr01.cpl.com 2 1 8
cpltp065.cdi.eu-cdc01.cpl.com 2 1 8
cpl1856.cdi.de-hbg01.cpl.com 2 2 8
cpl1853.cdi.eu-cdc01.cpl.com 2 1 8
cpl1854.cn-sha01.cpl.com 2 1 8
cpl1983.cdi.am-cdc01.cpl.com 2 1 8
cpl1984.cdi.am-cdc01.cpl.com 2 1 8
cpl1986.cdi.am-cdc01.cpl.com 2 1 8
There is a utility shipped with RHEL systems called column
which is used to columnate lists.
$ cat tt | column -t
Hostname CPU MEM SWAP
cpl1855.ind-blr01.cpl.com 4 2 8
cpltp064.ind-blr01.cpl.com 2 1 8
cpltp065.cdi.eu-cdc01.cpl.com 2 1 8
cpl1856.cdi.de-hbg01.cpl.com 2 2 8
cpl1853.cdi.eu-cdc01.cpl.com 2 1 8
cpl1854.cn-sha01.cpl.com 2 1 8
cpl1983.cdi.am-cdc01.cpl.com 2 1 8
cpl1984.cdi.am-cdc01.cpl.com 2 1 8
cpl1986.cdi.am-cdc01.cpl.com 2 1 8
Upvotes: 0
Views: 147
Reputation: 19625
read -rsp $'Please Enter password below: ' SSHPASS
echo -n ""
export SSHPASS
Why do you read the password masked but then export expose it to the whole session environment?
I'd use an ssh key pair with a restricted commands set.
mem=$(sshpass -e ssh -o StrictHostKeyChecking=no -q -t "$target_host" free -g | /bin/awk '/^Mem/{print $2}')
swap=$(sshpass -e ssh -o StrictHostKeyChecking=no -q -t "$target_host" free -g | /bin/awk '/^Swap/{print $2}')
cpu=$(sshpass -e ssh -o StrictHostKeyChecking=no -q -t "$target_host" grep -c proc /proc/cpuinfo)
free -g
, you need to set the locale to C
with: LC_ALL=C free -g
, or the awk pattern will fail a match on non-US English locale. read -r mem swap cpu < <(
ssh -o StrictHostKeyChecking=no -q -t "$target_host" \
awk '/^MemTotal/{printf("%d\t", $2/1000000)};/^SwapTotal/{printf("%d\t", $2/1000000)};/^processor/{c++};END{print c}' /proc/meminfo /proc/cpuinfo
)
Or even better with only access to cat
, download the data and parse locally:
read -r mem swap cpu < <(
ssh -o StrictHostKeyChecking=no -q -t "$target_host" \
cat /proc/meminfo /proc/cpuinfo |
awk '/^MemTotal/{printf("%d\t", $2/1000000)};/^SwapTotal/{printf("%d\t", $2/1000000)};/^processor/{c++};END{print c}'
)
Your snippet fixed:
#!/usr/bin/env bash
read -rsp $'Please Enter password below: ' SSHPASS
export SSHPASS
printf '\n%-32s %10s %10s %5s\n' 'Hostname' 'CPU' 'MEM' 'SWAP'
remote_connect() {
target_host=$1
read -r mem swap cpu < <(
sshpass -e ssh -o StrictHostKeyChecking=no -q -t "$target_host" \
cat /proc/meminfo /proc/cpuinfo |
awk '/^MemTotal/{printf("%d\t", $2/1000000)};/^SwapTotal/{printf("%d\t", $2/1000000)};/^processor/{c++};END{print c}'
)
printf "%-32s %10s %10s %5s\n" "$target_host" "$cpu" "$mem" "$swap"
} 2>/dev/null
export -f remote_connect
< /home/cpls/mb_hosts xargs -P5 -l1 bash -c 'remote_connect "$1"' --
Example output:
Hostname CPU MEM SWAP
localhost 8 24 6
Upvotes: 3
Reputation: 15408
Your formatting problem (aside from passing the wrong number of arguments originally) is that you are defining less space for your first field than some of its data elements require.
I put the data in a file called data
(the formatting isn't about how you acquire the field data).
$: fmt="%-30s %10s %10s %5s\n"
$: printf "$fmt" Hostname CPU MEM SWAP &&
while read -r -a dat; do printf "$fmt" "${dat[@]}"; done < data
Hostname CPU MEM SWAP
cpl1855.ind-blr01.cpl.com 4 2 8
cpltp064.ind-blr01.cpl.com 2 1 8
cpltp065.cdi.eu-cdc01.cpl.com 2 1 8
cpl1856.cdi.de-hbg01.cpl.com 2 2 8
cpl1853.cdi.eu-cdc01.cpl.com 2 1 8
cpl1854.cn-sha01.cpl.com 2 1 8
cpl1983.cdi.am-cdc01.cpl.com 2 1 8
cpl1984.cdi.am-cdc01.cpl.com 2 1 8
cpl1986.cdi.am-cdc01.cpl.com 2 1 8
As you obviously already demonstrate, you can set minimum field widths and left-justify with a leading dash (-
): -
$: printf "/%-5s/%4s/%3s/%2s/\n" abc def ghi jkl mno pqr stu vwx yz.
/abc / def/ghi/jkl/
/mno / pqr/stu/vwx/
/yz. / / / /
The issue was that if your data is wider than the minimum width the full field is printed (the last field), but otherwise it space-pads (the first two fields).
As an aside, you can add maximum field widths, at the risk of losing info -
$: printf "/%5.5s/%4.4s/%3.3s/%2.2s/\n" abc def ghi jkl mno pqr stu vwx yz.
/ abc/ def/ghi/jk/
/ mno/ pqr/stu/vw/
/ yz./ / / /
Note that l
and x
are lost when the field length truncates them.
That's probably not what you want, though there are times...
Upvotes: 2