【问题标题】:Copying variables to local text file from multiple ssh awk output将变量从多个 ssh awk 输出复制到本地文本文件
【发布时间】:2021-05-16 15:23:49
【问题描述】:

我对 shell 脚本相当陌生,所以我很难将类似问题的答案应用于我的问题。

我正在尝试通过 ssh 连接到远程服务器,执行多个 awk 命令,并将每个命令的值返回到本地 .txt 文件。我也在尝试 ssh 到其他服务器,执行类似的命令,并将它们返回到同一个文本文件。

如果我手动 ssh 进入远程服务器并运行df -h | awk '$6 == "/" {print $5; exit},我会从 df -h 命令获得根目录的 % used 值。 到目前为止,我有以下内容,但是当它进入和退出远程服务器时,它不会保存值。

> testfile.txt

ssh {$CURRENT_ENV} << EOF
VAL=\$(df -h | awk '\$6 == "/" {print \$5; exit}')
echo "\$VAL > testfile.txt"
exit
EOF

我查看了单行 awk 返回,但由于我有多个命令要运行,它似乎不是最优的。如有任何建议,我将不胜感激!

【问题讨论】:

  • 关于I have multiple commands to run - 我强烈建议您只运行需要在远程机器上运行的最少命令,并在本地运行其余命令,以实现稳健性、易于维护等。例如,在这种情况下,您可以使用ssh 'df' | awk 而不是ssh 'df | awk'。然后,例如,如果您必须对其进行调试,您可以将其调整为 ssh 'df' | tee file | awk 以创建 df 输出的本地副本 - 如果您的起点是 ssh 'df | awk',则通常会有更有效的更改。
  • 所以当你说I am trying to ssh to a remote server, perform multiple awk commands, and return the value of each to a local .txt file - 我建议你不要那样做。而是 ssh 到远程服务器,执行收集所需数据所需的绝对最少命令,将该数据保存到本地服务器,然后在本地数据副本上执行多个 awk 命令并返回每个值到本地 .txt 文件。当然要考虑客户对允许的数据传输(如果适用)和数据传输大小/速率的要求。

标签: bash shell awk ssh scripting


【解决方案1】:

首先,您的ssh 命令。使用 here-document 是个好主意。您可以通过以下两种方式对其进行改进:

  • 由于&lt;&lt;- 语法而使用制表符缩进。这纯粹是装饰性的,让您的代码更具可读性。
  • 通过引用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 &gt; testfile.txt" 不会向 textfile.txt 写入任何内容,因为您的重定向在双引号内,因此属于 echo-ed 的文本。正确的命令是echo "$val" &gt; 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之后)

来了!

【讨论】:

  • 谢谢@Ed。这是故意的。恐怕 OP 可能会复制粘贴我的代码,然后得到纯空格而不是制表符,这将触发他们可能无法理解的错误(找不到 EOF)。所以我让 EOF 在我的答案中保持对齐。我只缩进了不受额外前导空格影响的命令。
  • 谢谢,我不知道引用EOF技巧!
  • 谢谢!这对于循环和获取所有终端输出非常有用。当它保存到文本文件时,它还会保存 ssh 初始登录/系统负载信息。有没有办法对此进行调整,以纯粹返回在远程环境中直接运行时显示的df -h | awk '$6 == "/" {print $5; exit}' 的输出!再次感谢您一步一步的详细介绍,因为它让我更清楚了很多事情
  • @ebrithilotho 此横幅仅在您调用ssh 时出现,参数中没有任何命令(即您需要命令行)。您可以给出命令而不是通过此处文档提供命令(即ssh serveur 'df -h'),但由于您的命令相当复杂,您可以将 shell 本身作为命令:ssh serveur bash &lt;&lt;- EOF ...
【解决方案2】:

我认为你可以这样做:

# 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 可能会更慢,我不确定。

【讨论】:

    【解决方案3】:

    如果您想将任何内容打印到本地文件,只需在 EOF 之后立即执行重定向 这是如何将 VAL 写入远程文件和本地文件的示例。您也可以使用 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
    

    【讨论】:

      猜你喜欢
      • 2016-05-23
      • 2014-01-18
      • 2018-04-18
      • 1970-01-01
      • 2014-10-11
      • 2021-02-23
      • 1970-01-01
      • 2020-01-05
      • 2014-06-17
      相关资源
      最近更新 更多