如何使用 ssh 连接创建具有多个变量的粒度 bash 脚本
How to create a granular bash script with multiple variables with ssh connections
我有以下脚本:
bash 脚本:
#!/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=
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 }')
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 "$@"' --
在 运行 并行模式下,上面的脚本对我来说运行得很好。
脚本结果:
|------------------------------------------------------------|
|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 |
关注 ?
我有两个变量:rhelInfo
和 perlInfo
来获取商店信息。但它使用对服务器的两次 ssh 调用来获取值。
我可以只有一个 SSH 调用来执行多个命令并设置两个变量吗?
Could I have only one SSH call to execute multiple commands and set both variables?
当然可以。你可以这样做:
# this looks too long - so a function
_ssh() {
ssh -i /home/zabbix/.ssh/ssh_key \
-o StrictHostKeyChecking=no \
-o PasswordAuthentication=no \
"root@$target_host" \
"$@"
}
export -f _ssh
# the function to-be-executed on the remote
remotework() {
rhelinfo=$(awk 'END{print }' /etc/redhat-release)
perlinfo=$(rpm -qa | grep -i mod_perl)
# output elements separated by byte 0x01
printf "%s[=10=]1" "$rhelinfo" "$perlinfo"
}
export -f remotework
remote_connect() {
# execute bash on the remote
# with `remotework` function serialized
# and execute the `remotework` function
# properly `printf %q` quote everything for unquoting done by ssh+remote shell
tmp=$( _ssh "$(printf "%q " bash -c "$(declare -f remotework); remotework")" )
# split the output of ssh by byte 0x01
{
IFS= read -d $'\x01' -r rhelInfo &&
IFS= read -d $'\x01' -r perlInfo
} <<<"$tmp"
}
或它的类似变体。基本上 ssh
为您提供双向数据流 - 您可以在中间使用分隔符(“自定义协议”)传输任何内容,然后在该分隔符上拆分数据。 IE。问题不仅限于 ssh - bash 中的研究数据 serialization/deserialization。上面我选择了字节 0x01 作为分隔符 - 你可以使用具有唯一 uuid 的单独行,使用 base64 -w0
将数据转换为单行,或类似或使用其他格式。
remotework() {
awk ... | base64 -w0
echo ' '
rpm ... | base64 -w0
echo
}
...
IFS=' ' read -r rhelInfo perlInfo <<<"$tmp"
rhelInfo=$(<<<"$rhelInfo" base64 -d)
perlInfo=$(<<<"$perlInfo" base64 -d)
您还可以使用 declare -p
序列化变量,然后 eval
它们 - 我认为这更危险,因此最好使用分隔符。
建议替换以下行:
rhelInfo=$(ssh -i /home/zabbix/.ssh/ssh_key "root@${target_host}" -o StrictHostKeyChecking=no -o PasswordAuthentication=no cat /etc/redhat-release| awk 'END{print }')
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
具有以下几行:
sshResponseArr=( $(ssh -i /home/zabbix/.ssh/ssh_key "root@${target_host}" -o StrictHostKeyChecking=no -o PasswordAuthentication=no "awk 'END{print}' /etc/redhat-release; rpm -aq|grep -i mod_perl") )
if [[ $? -eq 0 ]]; then
printf "|%-10s | %-13s | %-20s |\n" "$target_host" "${sshResponseArr[6]}" "${sshResponseArr[8]}"
else
printf "|%-10s | %-13s | %-20s |\n" "$target_host" "Unable to get the ssh connection"
fi
说明
首先,我在 ssh
请求中调用 multi-line 命令。将所有命令放在带有 "
的单个参数中(就像您所做的那样)。
真正的技巧是将 multi-line ssh
响应读入 bash
数组变量 sshResponseArr
默认情况下,数组由
个空格解析。
我假设(和你一样)数组中的单词定位在所有主机上都是一致的因此:
$rhelInfo
是 ${sshResponseArr[6]}
而$perlInfo
是${sshResponseArr[8]}
sshResponseArr
的替代保守处理作为来自 ssh
命令的 2 行响应的数组:
mapfile -t sshResponseLinesArr < <(ssh -i /home/zabbix/.ssh/ssh_key "root@${target_host}" -o StrictHostKeyChecking=no -o PasswordAuthentication=no "awk 'END{print}' /etc/redhat-release; rpm -aq|grep -i mod_perl")
lastLineInReleaseFile=${sshResponseLinesArr[0]}
mod_perl_response=${sshResponseLinesArr[1]}
您可以 运行 在一个 ssh 运行 中执行这两个命令,然后解析结果,例如:
...
remote_data=($(
ssh -i /home/zabbix/.ssh/ssh_key "root@${target_host}" -o StrictHostKeyChecking=no -o PasswordAuthentication=no "
rhelInfo=$(cat /etc/redhat-release | awk 'END{print $7}')
perlInfo=$(rpm -qa | grep -i mod_perl)
echo $rhelInfo $perlInfo
"))
rhelInfo=${remote_data[0]}
perlInfo=${remote_data[1]}
...
说明:
remote_data=( $(ssh ...) )
- 将创建一个数组 'remote_data' 并用 $()
中命令输出的值填充它 数组将自动按 space、制表符或新行拆分值。所以在这种情况下,我们将有 remote_data=( 6.9 mod_perl-2.0.4-11.el6_5.x86_64 )
然后将这些值赋值给变量:
rhelInfo=${remote_data[0]}
perlInfo=${remote_data[1]}
顺便说一句,echo(and cat)) 在这里有点矫枉过正,因此可以简化为:
...
remote_data=($(
ssh -i /home/zabbix/.ssh/ssh_key "root@${target_host}" \
-o StrictHostKeyChecking=no \
-o PasswordAuthentication=no "
awk 'END{print $7}' /etc/redhat-release
rpm -qa | grep -i mod_perl
"
))
rhelInfo=${remote_data[0]}
perlInfo=${remote_data[1]}
...
下面是我如何使用 ssh
远程数据 collection
一些评论
因为此功能旨在收集数据,而不是连接主机(因为它们不会停留已连接),我已将它们重命名 ;-)
避免无用的分叉!使用 printf -v varname ...
而不是 varname=$(printf ...)
将 STDERR
重定向 2>/dev/null
移动到更合适的位置。
使用local
将变量名保留到函数作用域中。
printf
必须有正确数量的参数,对应于 %s
的数量见 This format string has 3 variable....
不要使用-i
如果不需要则切换到grep
!
remote_collect() {
local target_host= 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 }' </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
}
注意:EOF
标记之前可以有制表符 Tab,但 不能 spaces!我在发布之前删除了制表以确保它们不会在剪切和粘贴期间在 space 中转换。
标题可以是
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 |
漂亮 table 使用 UFT-8
边框
printf -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
然后:
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
最后
# 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"
应该产生:
┌────────────┬────────────────┬───────────────────────────────┐
│ Hostname │ RedHat Version │ Perl Version │
├────────────┼────────────────┼───────────────────────────────┤
│ hostok │ 6.3 │ mod_perl-2.0.4-10.el6_5.armf │
│ hostbad │ Unable to get the ssh connection │
└────────────┴────────────────┴───────────────────────────────┘
在我这边用@F 测试后,我将它保留在这里。 Hauri 回答..
#!/bin/bash
###########
printf -v sl %32s '';sl=${sl// /$'\U2500'}
printf '%b%-12s%b%-16s%b%-32s%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
remote_collect() {
target_host=
{
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
cat /etc/redhat-release | awk 'END{print $7}'
rpm -qa | grep mod_perl
EOF
) 2>/dev/null
if [[ $? -eq 0 ]] ;then
printf "\U2502 %-10s \U2502 %-14s \U2502 %-28s \U2502\n" \
"$target_host" "$rhelInfo" "$perlInfo"
else
printf "\U2502 %-10s \U2502 %-14s \U2502 %-29s \U2502\n" \
"$target_host" "?" "Unable to connect"
fi
# 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"
} 2>/dev/null
export -f remote_collect
< /home/zabbix/hostsList.txt xargs -P30 -n1 -d'\n' bash -c 'remote_connect "$@"' --
输出 1:
┌────────────┬────────────────┬────────────────────────────────┐
│ Hostname │ RedHat Version │ Perl Version │
├────────────┼────────────────┼────────────────────────────────┤
│ foxnl46 │ ? │ Unable to connect │
└┴┴┘
│ foxnl27 │ 6.7 │ mod_perl-2.0.4-11.el6_5.x86_64 │
└┴┴┘
│ foxnl32 │ 6.7 │ mod_perl-2.0.4-11.el6_5.x86_64 │
如果我删除最后一个 printf
一切都会好起来期待 table.
的最后一行
输出 2
┌────────────┬────────────────┬────────────────────────────────┐
│ Hostname │ RedHat Version │ Perl Version │
├────────────┼────────────────┼────────────────────────────────┤
│ foxnl46 │ ? │ Unable to connect │
│ foxnl27 │ 6.7 │ mod_perl-2.0.4-11.el6_5.x86_64 │
│ foxnl32 │ 6.7 │ mod_perl-2.0.4-11.el6_5.x86_64 │
我有以下脚本:
bash 脚本:
#!/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=
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 }')
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 "$@"' --
在 运行 并行模式下,上面的脚本对我来说运行得很好。
脚本结果:
|------------------------------------------------------------|
|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 |
关注 ?
我有两个变量:rhelInfo
和 perlInfo
来获取商店信息。但它使用对服务器的两次 ssh 调用来获取值。
我可以只有一个 SSH 调用来执行多个命令并设置两个变量吗?
Could I have only one SSH call to execute multiple commands and set both variables?
当然可以。你可以这样做:
# this looks too long - so a function
_ssh() {
ssh -i /home/zabbix/.ssh/ssh_key \
-o StrictHostKeyChecking=no \
-o PasswordAuthentication=no \
"root@$target_host" \
"$@"
}
export -f _ssh
# the function to-be-executed on the remote
remotework() {
rhelinfo=$(awk 'END{print }' /etc/redhat-release)
perlinfo=$(rpm -qa | grep -i mod_perl)
# output elements separated by byte 0x01
printf "%s[=10=]1" "$rhelinfo" "$perlinfo"
}
export -f remotework
remote_connect() {
# execute bash on the remote
# with `remotework` function serialized
# and execute the `remotework` function
# properly `printf %q` quote everything for unquoting done by ssh+remote shell
tmp=$( _ssh "$(printf "%q " bash -c "$(declare -f remotework); remotework")" )
# split the output of ssh by byte 0x01
{
IFS= read -d $'\x01' -r rhelInfo &&
IFS= read -d $'\x01' -r perlInfo
} <<<"$tmp"
}
或它的类似变体。基本上 ssh
为您提供双向数据流 - 您可以在中间使用分隔符(“自定义协议”)传输任何内容,然后在该分隔符上拆分数据。 IE。问题不仅限于 ssh - bash 中的研究数据 serialization/deserialization。上面我选择了字节 0x01 作为分隔符 - 你可以使用具有唯一 uuid 的单独行,使用 base64 -w0
将数据转换为单行,或类似或使用其他格式。
remotework() {
awk ... | base64 -w0
echo ' '
rpm ... | base64 -w0
echo
}
...
IFS=' ' read -r rhelInfo perlInfo <<<"$tmp"
rhelInfo=$(<<<"$rhelInfo" base64 -d)
perlInfo=$(<<<"$perlInfo" base64 -d)
您还可以使用 declare -p
序列化变量,然后 eval
它们 - 我认为这更危险,因此最好使用分隔符。
建议替换以下行:
rhelInfo=$(ssh -i /home/zabbix/.ssh/ssh_key "root@${target_host}" -o StrictHostKeyChecking=no -o PasswordAuthentication=no cat /etc/redhat-release| awk 'END{print }')
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
具有以下几行:
sshResponseArr=( $(ssh -i /home/zabbix/.ssh/ssh_key "root@${target_host}" -o StrictHostKeyChecking=no -o PasswordAuthentication=no "awk 'END{print}' /etc/redhat-release; rpm -aq|grep -i mod_perl") )
if [[ $? -eq 0 ]]; then
printf "|%-10s | %-13s | %-20s |\n" "$target_host" "${sshResponseArr[6]}" "${sshResponseArr[8]}"
else
printf "|%-10s | %-13s | %-20s |\n" "$target_host" "Unable to get the ssh connection"
fi
说明
首先,我在 ssh
请求中调用 multi-line 命令。将所有命令放在带有 "
的单个参数中(就像您所做的那样)。
真正的技巧是将 multi-line ssh
响应读入 bash
数组变量 sshResponseArr
默认情况下,数组由
个空格解析。
我假设(和你一样)数组中的单词定位在所有主机上都是一致的因此:
$rhelInfo
是 ${sshResponseArr[6]}
而$perlInfo
是${sshResponseArr[8]}
sshResponseArr
的替代保守处理作为来自 ssh
命令的 2 行响应的数组:
mapfile -t sshResponseLinesArr < <(ssh -i /home/zabbix/.ssh/ssh_key "root@${target_host}" -o StrictHostKeyChecking=no -o PasswordAuthentication=no "awk 'END{print}' /etc/redhat-release; rpm -aq|grep -i mod_perl")
lastLineInReleaseFile=${sshResponseLinesArr[0]}
mod_perl_response=${sshResponseLinesArr[1]}
您可以 运行 在一个 ssh 运行 中执行这两个命令,然后解析结果,例如:
...
remote_data=($(
ssh -i /home/zabbix/.ssh/ssh_key "root@${target_host}" -o StrictHostKeyChecking=no -o PasswordAuthentication=no "
rhelInfo=$(cat /etc/redhat-release | awk 'END{print $7}')
perlInfo=$(rpm -qa | grep -i mod_perl)
echo $rhelInfo $perlInfo
"))
rhelInfo=${remote_data[0]}
perlInfo=${remote_data[1]}
...
说明:
remote_data=( $(ssh ...) )
- 将创建一个数组 'remote_data' 并用 $()
中命令输出的值填充它 数组将自动按 space、制表符或新行拆分值。所以在这种情况下,我们将有 remote_data=( 6.9 mod_perl-2.0.4-11.el6_5.x86_64 )
然后将这些值赋值给变量:
rhelInfo=${remote_data[0]}
perlInfo=${remote_data[1]}
顺便说一句,echo(and cat)) 在这里有点矫枉过正,因此可以简化为:
...
remote_data=($(
ssh -i /home/zabbix/.ssh/ssh_key "root@${target_host}" \
-o StrictHostKeyChecking=no \
-o PasswordAuthentication=no "
awk 'END{print $7}' /etc/redhat-release
rpm -qa | grep -i mod_perl
"
))
rhelInfo=${remote_data[0]}
perlInfo=${remote_data[1]}
...
下面是我如何使用 ssh
远程数据 collection
一些评论
因为此功能旨在收集数据,而不是连接主机(因为它们不会停留已连接),我已将它们重命名 ;-)
避免无用的分叉!使用
printf -v varname ...
而不是varname=$(printf ...)
将
STDERR
重定向2>/dev/null
移动到更合适的位置。使用
local
将变量名保留到函数作用域中。printf
必须有正确数量的参数,对应于%s
的数量见 This format string has 3 variable....不要使用
-i
如果不需要则切换到grep
!
remote_collect() {
local target_host= 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 }' </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
}
注意:EOF
标记之前可以有制表符 Tab,但 不能 spaces!我在发布之前删除了制表以确保它们不会在剪切和粘贴期间在 space 中转换。
标题可以是
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 |
漂亮 table 使用 UFT-8
边框
printf -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
然后:
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
最后
# 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"
应该产生:
┌────────────┬────────────────┬───────────────────────────────┐
│ Hostname │ RedHat Version │ Perl Version │
├────────────┼────────────────┼───────────────────────────────┤
│ hostok │ 6.3 │ mod_perl-2.0.4-10.el6_5.armf │
│ hostbad │ Unable to get the ssh connection │
└────────────┴────────────────┴───────────────────────────────┘
在我这边用@F 测试后,我将它保留在这里。 Hauri 回答..
#!/bin/bash
###########
printf -v sl %32s '';sl=${sl// /$'\U2500'}
printf '%b%-12s%b%-16s%b%-32s%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
remote_collect() {
target_host=
{
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
cat /etc/redhat-release | awk 'END{print $7}'
rpm -qa | grep mod_perl
EOF
) 2>/dev/null
if [[ $? -eq 0 ]] ;then
printf "\U2502 %-10s \U2502 %-14s \U2502 %-28s \U2502\n" \
"$target_host" "$rhelInfo" "$perlInfo"
else
printf "\U2502 %-10s \U2502 %-14s \U2502 %-29s \U2502\n" \
"$target_host" "?" "Unable to connect"
fi
# 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"
} 2>/dev/null
export -f remote_collect
< /home/zabbix/hostsList.txt xargs -P30 -n1 -d'\n' bash -c 'remote_connect "$@"' --
输出 1:
┌────────────┬────────────────┬────────────────────────────────┐
│ Hostname │ RedHat Version │ Perl Version │
├────────────┼────────────────┼────────────────────────────────┤
│ foxnl46 │ ? │ Unable to connect │
└┴┴┘
│ foxnl27 │ 6.7 │ mod_perl-2.0.4-11.el6_5.x86_64 │
└┴┴┘
│ foxnl32 │ 6.7 │ mod_perl-2.0.4-11.el6_5.x86_64 │
如果我删除最后一个 printf
一切都会好起来期待 table.
输出 2
┌────────────┬────────────────┬────────────────────────────────┐
│ Hostname │ RedHat Version │ Perl Version │
├────────────┼────────────────┼────────────────────────────────┤
│ foxnl46 │ ? │ Unable to connect │
│ foxnl27 │ 6.7 │ mod_perl-2.0.4-11.el6_5.x86_64 │
│ foxnl32 │ 6.7 │ mod_perl-2.0.4-11.el6_5.x86_64 │