簡體   English   中英

在bash和ssh中轉義復雜的命令行參數

[英]escaping complicated command line arguments in bash and ssh

我正在使用bash腳本來檢索服務器列表的正常運行時間。 它只是從文件中讀取並在服務器上執行遠程命令。 有些服務器可能已啟動很長時間,而有些服務器可能剛剛重啟。 我使用的是非常簡單的方法:

uptime | awk '{print \$2,\$3,\$4}'

如果服務器至少已啟動一天,則此方法有效,但是如果僅啟動了幾個小時,則正常運行時間的輸出將不包括工作日,而僅使用hour:minute格式。

我發現了一些我很喜歡的東西,但是似乎無法在ssh命令中正確地轉義它,更不用說嘗試在bash腳本中傳遞它了:

uptime | awk -F'( |,|:)+' '{d=h=m=0; if ($7=="min") m=$6; else {if ($7~/^day/) {d=$6;h=$8;m=$9} else {h=$6;m=$7}}} {print d+0,"days,",h+0,"hours,",m+0,"minutes."}'

我已經嘗試了幾件事,但是對我來說這應該起作用,並且似乎無法弄清我所缺少的內容:

ssh user@IP "uptime | awk -F'( |,|:)+' '{d=h=m=0; if (\$7==\"min\") m=\$6; else {if (\$7\~\/^day\/) {d=\$6;h=\$8;m=\$9} else {h=\$6;m=\$7}}} {print d+0,\"days,\",h+0,\"hours,\",m+0,\"minutes.\"}'"

我得到的輸出是:

awk: {d=h=m=0; if ($7=="min") m=$6; else {if ($7\~\/^day\/) {d=$6;h=$8;m=$9} else {h=$6;m=$7}}} {print d+0,"days,",h+0,"hours,",m+0,"minutes."}
awk:                                            ^ backslash not last character on line

最后,我嘗試將其放入bash腳本中,如下所示:

while IFS= read -r server; do
    ssh -tt user@$server  "uptime command" < /dev/null >> /home/user/uptime
done < "$file"

只需將命令發送到ssh的標准輸入即可:

cat <<'EOF' | ssh user@machine
uptime | awk -F'( |,|:)+' '{d=h=m=0; if ($7=="min") m=$6; else {if ($7~/^day/) {d=$6;h=$8;m=$9} else {h=$6;m=$7}}} {print d+0,"days,",h+0,"hours,",m+0,"minutes."}'
EOF

在我看來,您逃避了太多:

ssh user@IP "uptime | awk -F'( |,|:)+' '{d=h=m=0; if (\$7==\"min\") m=\$6; else {if (\$7~/^day/) {d=\$6;h=\$8;m=\$9} else {h=\$6;m=\$7}}} {print d+0,\"days,\",h+0,\"hours,\",m+0,\"minutes.\"}'"

我得到:

6 days, 11 hours, 21 minutes.

更新:

由於同一命令將被發送到多個不同的遠程主機,因此我建議將其保存到一個變量中以方便重用。

command="uptime | awk -F'( |,|:)+' '{d=h=m=0; if (\$7==\"min\") m=\$6; else {if (\$7~/^day/) {d=\$6;h=\$8;m=\$9} else {h=\$6;m=\$7}}} {print d+0,\"days,\",h+0,\"hours,\",m+0,\"minutes.\"}'"
ssh user@IP1 "$command"
ssh user@IP2 "$command"

測試運行:

$ bash script.sh
0 days, 2 hours, 26 minutes.
7 days, 4 hours, 18 minutes.

等待,還有更多:

我經常需要向遠程主機發送多個命令:為此,我發現choroba在他的回答中建議的 引號的heredoc語法非常方便。

command=$(cat <<'EOF'
hostname
uptime | awk -F'( |,|:)+' '{d=h=m=0; if ($7=="min") m=$6; else {if ($7~/^day/) {d=$6;h=$8;m=$9} else {h=$6;m=$7}}} {print d+0,"days,",h+0,"hours,",m+0,"minutes."}'
EOF
)
ssh user@IP1 "$command"
ssh user@IP2 "$command"

這是輸出:

$ bash script.sh
server1
0 days, 2 hours, 26 minutes.
server2
7 days, 4 hours, 18 minutes.

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM