Linux 在bash和ssh中转义复杂的命令行参数

Linux 在bash和ssh中转义复杂的命令行参数,linux,bash,awk,ssh,Linux,Bash,Awk,Ssh,我正在使用bash脚本来检索服务器列表的正常运行时间。它只是读取文件并在服务器上执行远程命令。有些服务器可能已经运行了很长时间,而有些服务器可能刚刚重新启动。我用了一些非常简单的东西: uptime | awk '{print \$2,\$3,\$4}' 如果服务器已运行至少一天,则此方法有效,但如果服务器仅运行了几个小时,则正常运行时间的输出不包括工作日,仅使用小时:分钟格式 我发现了一些我非常喜欢的东西,但似乎无法在ssh命令中正确地避开它,更不用说尝试在bash脚本中传递它了: upti

我正在使用bash脚本来检索服务器列表的正常运行时间。它只是读取文件并在服务器上执行远程命令。有些服务器可能已经运行了很长时间,而有些服务器可能刚刚重新启动。我用了一些非常简单的东西:

uptime | awk '{print \$2,\$3,\$4}'
如果服务器已运行至少一天,则此方法有效,但如果服务器仅运行了几个小时,则正常运行时间的输出不包括工作日,仅使用小时:分钟格式

我发现了一些我非常喜欢的东西,但似乎无法在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"
而IFS=read-r服务器;做
ssh-tt user@$server“正常运行时间命令”>/home/user/uptime
完成<“$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

cat我觉得你逃得太多了:

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.
等等,还有更多:

我经常需要向远程主机发送多个命令:为此,我发现his中建议的最方便的方法是

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"

是的,heredoc是一条路要走。请参见中的示例19-7。这是一种有趣的方法,它在bash中可以独立工作,但我在将其集成到我已经使用的内容中时遇到了问题,因为我是针对一系列服务器运行此方法的。稍后我会有更多的时间来处理这个问题,然后再看一看。@ChrisSchneider您可以将命令保存在一个变量中,然后在您的服务器列表中运行它。谢谢。这使我能够将它集成到我现有的bash脚本中,效果很好!事实上,我在最初的帖子中提到,我已经有了一个脚本,我正在使用它并试图将其集成,所以我不知道“它出现”是否准确,但我真的很欣赏这样做的不同方式,它帮助我学习bash@克丽丝·施奈德你完全正确,我要纠正这一点。
$ bash script.sh
server1
0 days, 2 hours, 26 minutes.
server2
7 days, 4 hours, 18 minutes.