I have the below script:
bash Script:
#!/bin/bash
###########
printf "\n"
marker=$(printf "%0.s-" {1..60})
printf "|$marker|\n"
printf "|%-10s | %-13s | %-29s |\n" "Hostname" "RedHat Vesrion" "Perl Version"
printf "|$marker|\n"
remote_connect() {
target_host=$1
marker=$(printf "%0.s-" {1..60})
rhelInfo=$(ssh -i /home/zabbix/.ssh/ssh_key "root@${target_host}" -o StrictHostKeyChecking=no -o PasswordAuthentication=no cat /etc/redhat-release| awk 'END{print $7}')
perlInfo=$(ssh -i /home/zabbix/.ssh/ssh_key "root@${target_host}" -o StrictHostKeyChecking=no -o PasswordAuthentication=no "rpm -qa | grep -i mod_perl")
if [[ $? -eq 0 ]]
then
printf "|%-10s | %-13s | %-20s |\n" "$target_host" "$rhelInfo" "$perlInfo"
else
printf "|%-10s | %-13s | %-20s |\n" "$target_host" "Unable to get the ssh connection"
fi
} 2>/dev/null
export -f remote_connect
< /home/zabbix/hostsList.txt xargs -P30 -n1 -d'\n' bash -c 'remote_connect "$@"' --
The above script runs pretty well for me while running in parallel mode.
Script results:
|------------------------------------------------------------|
|Hostname | RedHat Vesrion | Perl Version |
|------------------------------------------------------------|
|foxnl41 | 6.9 | mod_perl-2.0.4-11.el6_5.x86_64 |
|foxnl84 | 6.9 | mod_perl-2.0.4-11.el6_5.x86_64 |
|foxnl42 | 6.9 | mod_perl-2.0.4-11.el6_5.x86_64 |
|foxnl63 | 6.9 | mod_perl-2.0.4-11.el6_5.x86_64 |
|foxnl10 | 6.7 | mod_perl-2.0.4-11.el6_5.x86_64 |
|foxnl55 | 6.9 | mod_perl-2.0.4-11.el6_5.x86_64 |
|foxnl95 | 6.9 | mod_perl-2.0.4-11.el6_5.x86_64 |
|foxnl85 | 6.9 | mod_perl-2.0.4-11.el6_5.x86_64 |
Concern ?
I have two variables: rhelInfo
and perlInfo
to get store information. But it is using two ssh calls to the servers to get the values.
Could I have only one SSH call to execute multiple commands and set both variables?
ssh
Some remarks
As this function is intended to collect datas, not to connect host (as they don't stay connected), I've renamed them ;-)
Avoid useless forks! use printf -v varname ...
instead of varname=$(printf ...)
Moved STDERR
redirection 2>/dev/null
at more suited place.
use local
to reserve variables names into function scope.
printf
must have correct number of arguments, corresponding to number of %s
see This format string has 3 variable....
Don't use -i
switch to grep
if not needed!
remote_collect() {
local target_host=$1 host_answer rhelInfo perlInfo
{
read -r host_answer
read -r rhelInfo
read -r perlInfo
} < <(
ssh -i /home/zabbix/.ssh/ssh_key "root@${target_host}" \
-o StrictHostKeyChecking=no -o PasswordAuthentication=no \
/bin/sh <<-EOF
hostname
awk 'END{print $7}' </etc/redhat-release
rpm -qa | grep mod_perl
EOF
) 2>/dev/null
if [[ $? -eq 0 ]] ;then
printf "| %-10s | %-14s | %-29s |\n" \
"host_answer" "$rhelInfo" "$perlInfo"
else
printf "| %-10s | %-46s |\n" \
"target_host" "Unable to get the ssh connection"
fi
}
Notice: the EOF
mark could be preceded by tabulations Tab, but not spaces! I've dropped tabulation before posting to ensure they won't be converted in space during cut'n paste.
printf -v marker '%61s' ''
marker=${marker// /-}
printf "+%s+\n| %-10s | %-14s | %-29s |\n+%s+\n" \
"$marker" "Hostname" "RedHat Version" "Perl Version" "$marker"
+-------------------------------------------------------------+
| Hostname | RedHat Version | Perl Version |
+-------------------------------------------------------------+
| hostok | 6.3 | mod_perl-2.0.4-10.el6_5.armf |
| hostbad | Unable to get the ssh connection |
UFT-8
bordersprintf -v sl %31s '';sl=${sl// /$'\U2500'}
printf '%b%-12s%b%-16s%b%-31s%b\n' \
\\U250c "${sl::12}" \\U252c "${sl::16}" \\U252c "$sl" \\U2510 \
\\U2502 ' Hostname' \\U2502 ' RedHat Version' \\U2502 ' Perl Version' \
\\U2502 \\U251c "${sl::12}" \\U253c "${sl::16}" \\U253c "$sl" \\U2524
then:
if [[ $? -eq 0 ]] ;then
printf "\U2502 %-10s \U2502 %-14s \U2502 %-29s \U2502\n" \
"$host_answer" "$rhelInfo" "$perlInfo"
else
printf "\U2502 %-10s \U2502 %-46s \U2502\n" \
"$target_host" " Unable to get the ssh connection"
fi
and finally
# printf -v sl %31s '';sl=${sl// /$'\U2500'} # uncomment if $sl not at main scope
printf '\U2514%s\U2534%s\U2534%s\U2518\n' "${sl::12}" "${sl::16}" "$sl"
should produce:
┌────────────┬────────────────┬───────────────────────────────┐
│ Hostname │ RedHat Version │ Perl Version │
├────────────┼────────────────┼───────────────────────────────┤
│ hostok │ 6.3 │ mod_perl-2.0.4-10.el6_5.armf │
│ hostbad │ Unable to get the ssh connection │
└────────────┴────────────────┴───────────────────────────────┘