賞金將在 6 天后到期。此問題的答案有資格獲得 100聲望賞金。 kulfi想要獎勵現有的答案。
我有以下腳本:
重擊 腳本:
#!/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 "$@"' --
上面的腳本在并行模式下運行時對我來說運行得很好。
腳本結果:
|------------------------------------------------------------|
|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 呼叫來執行多個命令并設定兩個變數嗎?
uj5u.com熱心網友回復:
我可以只有一個 SSH 呼叫來執行多個命令并設定兩個變數嗎?
當然。你可以這樣做:
# 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 $7}' /etc/redhat-release)
perlinfo=$(rpm -qa | grep -i mod_perl)
# output elements separated by byte 0x01
printf "%s\001" "$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為您提供雙向資料流 - 您可以在中間使用分隔符(“自定義協議”)流式傳輸任何內容,然后在該分隔符上拆分資料。即問題不僅限于 ssh - 研究 bash 中的資料序列化/反序列化。上面我選擇了位元組 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- 我認為這更危險,因此最好使用分隔符。
uj5u.com熱心網友回復:
建議替換以下行:
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
使用以下幾行:
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首先我在請求中呼叫多行命令。將所有命令放在一個引數中"(就像你做的那樣)。
真正的技巧是將多行ssh回應讀入bash陣列變數sshResponseArr
默認情況下,陣列由 空格決議。
我假設(正如你所做的那樣)陣列中的單詞定位在所有主機中都是一致的,因此:
$rhelInfo是${sshResponseArr[6]}
并且$perlInfo是${sshResponseArr[8]}
替代保守處理作為來自命令sshResponseArr的 2 行回應的陣列:ssh
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]}
uj5u.com熱心網友回復:
您可以在一次 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]}
...
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/429757.html
