问题描述
我对 shell 脚本相当陌生,所以我很难将类似问题的答案应用到我的问题中。
我正在尝试通过 ssh 连接到远程服务器,执行多个 awk 命令,并将每个命令的值返回到本地 .txt 文件。我也在尝试 ssh 到其他服务器,执行类似的命令,并将它们返回到同一个文本文件。
如果我手动 ssh 进入远程服务器并运行 puppeteer.launch
,我会从 df -h 命令获得根目录的 % used 值。
到目前为止,我有以下内容,但是当它进入和退出远程服务器时,它不会保存值。
df -h | awk '$6 == "/" {print $5; exit}
我看过单行 awk 返回,但由于我有多个命令要运行,它似乎不是最佳的。如有任何建议,我将不胜感激!
解决方法
首先,您的 ssh
命令。使用 here-document 是个好主意。您可以通过以下两种方式改进它:
- 由于
<<-
语法而使用制表符缩进。这纯粹是装饰性的,使您的代码更具可读性。 - 通过引用
$
避免转义诸如EOF
之类的特殊字符。这不仅是装饰性的,而且使您的代码不易出错。
这给出:
ssh {$CURRENT_ENV} <<- 'EOF'
VAL=$(df -h | awk '$6 == "/" {print $5; exit}')
echo "$VAL > testfile.txt"
exit
EOF
(我们甚至可以在 EOF 之前放一个表格)
现在你的代码:
- 您没有告诉我们 CURRENT_ENV 是什么。我认为这类似于
user@server
。要使用该变量,请写入"$CURRENT_ENV"
,而不是“{CURRENT_ENV}”。除非您知道自己在做什么,否则在使用变量时,请始终将其括在双引号中,以避免任何不良副作用。 - 您将
df
的结果放入变量VAL
并将其内容写入textfile.txt
:- 作为通用约定,变量名使用小写(除非它们被导出到环境中,而这里不是这种情况);即这应该是
val
,而不是VAL
。 -
echo "$val > testfile.txt"
不会向 textfile.txt 写入任何内容,因为您的重定向位于双引号内,因此属于echo
-ed 的文本。正确的命令应该是echo "$val" > testfile.txt
- 现在,想一想:所有这些,包括这个
echo
都是在远程服务器上执行的,因此这将在远程服务器上创建文件testfile.txt
,而不是在您的机器上。这不是您想要的,所以让我们删除echo
行。我们也删除val=
,因为不再需要val
。 - 不需要
exit
命令。读取并执行最后一个命令后,ssh
会话无论如何都会结束。
- 作为通用约定,变量名使用小写(除非它们被导出到环境中,而这里不是这种情况);即这应该是
我们只剩下这个了;
ssh "$CURRENT_ENV" <<- 'EOF'
df -h | awk '$6 == "/" {print $5; exit}'
EOF
(记住这是 df
之前的表格,但在这种情况下单个空格不会造成伤害)
就像现在一样,您的代码将所有内容输出到您的终端。现在让我们将其重定向到您的本地文件 testfile.txt
:
ssh {$CURRENT_ENV} <<- 'EOF' > testfile.txt
df -h | awk '$6 == "/" {print $5; exit}'
EOF
好的,这适用于一台服务器。你告诉我们实际上有几个。您没有向我们展示您的代码,因此我假设某处存在循环:
for ssh_target in u1@server1 u2@server2 ...; do
ssh "$ssh_target" <<- 'EOF' > testfile.txt
df -h | awk '$6 == "/" {print $5; exit}'
EOF
done
快到了!此命令的问题在于每个循环都会覆盖 testfile.txt
的内容。解决方案是重定向 for
循环,而不是其中的 ssh
命令:
for ssh_target in u1@server1 u2@server2 ...; do
ssh "$ssh_target" <<- 'EOF'
df -h | awk '$6 == "/" {print $5; exit}'
EOF
done > testfile.txt
(重定向必须放在 done
之后)
来了!
,我认为你可以这样做:
# Write all of this script's stdout to testfile.txt
> testfile.txt
# Run df -h on remote host,and pipe the stdout of df -h to awk
ssh "$host" df -h | awk '$6 == "/" {print $5; exit}'
请注意,如果您使用 df
指定文件路径,那么您可以获得该文件路径的信息。在您的情况下,您只对 /
感兴趣,因此您可以指定它。
如果您只对使用的百分比感兴趣,可以使用 --ouput=pcent
选项,然后使用 tail
只获取百分比部分(省略 Use%
标头):
df --output=pcent / | tail -n 1
如果使用的百分比小于 100%,这将产生带有一两个前导空格的输出。可以使用 tr
:
df --output=pcent / | tail -n 1 | tr -d ' '
如果由于某种原因你想避免有两个管道,但你仍然想删除前导空格,你可以使用awk
:
df --output=pcent / | awk 'NR == 2 {print $1}'
但是使用 awk
可能会更慢,我不确定。
如果要将任何内容打印到本地文件,只需在 EOF 后立即重定向 这是如何将 VAL 写入 remotefile 和 localfile 的示例。您也可以使用 df --output pcent 仅显示百分比列。不幸的是没有隐藏标题的选项,所以 tail -n1
ssh {$CURRENT_ENV} << EOF >>localfile.txt
VAL=\$(df --output=pcent /|tail -n1)
echo "$VAL" > remotefile.txt
echo "$VAL" # for localfile
exit
EOF