【问题标题】:bash dealing with multiple quotationbash 处理多引号
【发布时间】:2021-12-18 11:13:18
【问题描述】:

我想从 bash 终端登录到计算节点并执行一些命令,例如,我这样做是为了检查正在运行的作业

ssh -t node1 'top -bn1 | grep R | grep -v top'

这会登录到node1 并运行top 命令和grep 所需的输出。
现在我想检查节点的内存负载。我从这里获取了这段代码https://unix.stackexchange.com/questions/119126/command-to-display-memory-usage-disk-usage-and-cpu-load

free -m | awk 'NR==2{printf "Memory Usage: %s/%sMB (%.2f%%)\n", $3,$2,$3*100/$2 }'

现在,我不能只做

ssh -t node1 '<above command>'

因为有多个引号会影响命令。有没有办法执行上面的命令?

【问题讨论】:

    标签: string bash


    【解决方案1】:

    您可以使用 here-doc 来避免引用问题:

    ssh node1 << 'EOF'
    free -m | awk 'NR==2{printf "Memory Usage: %s/%sMB (%.2f%%)\n", $3,$2,$3*100/$2 }'
    EOF
    

    注意 EOF 周围的引号,以便按原样传递内容。

    如果我们只是直接运行命令,我们通常不会使用 ssh 的-t

    【讨论】:

    • 这很好用,但是每次我运行它都会显示Pseudo-terminal will not be allocated because stdin is not a terminal.。可以静音吗?
    • 所以,我使用-T 来消除警告。
    【解决方案2】:

    例如

    ssh -t node1 'free -m | '"awk 'NR==2"'{printf "Memory Usage: %s/%sMB (%.2f%%)\n", $3,$2,$3*100/$2 }'
    

    这里的想法是将字符串分段。当您有一个包含单引号的序列时,请将其包装成双引号。包含变量扩展或双引号的部分被包裹在单引号之间。

    【讨论】:

    • 我认为这缺少最后的双引号单引号。检查的简单方法是将ssh -t node1 部分替换为echo,因为这将在(本地)shell 应用并删除第一层引号后打印其参数,因此输出与远程shell 将匹配查看并执行。 (好吧,除非您的 echo 版本有自己的转义解释,在这种情况下,它只会增加另一层混乱。但这不是问题,因为不涉及任何转义。)
    【解决方案3】:

    您的命令包含单引号,因此您不能将此命令作为单引号字符串传递给ssh(单引号不能在单引号内转义)。

    因此,您的选择如下:

    1. 要么从命令中删除单引号并将其更改为仅使用双引号。
    2. ...或将命令传递给ssh,用双引号(ssh -t node1 "&lt;above command&gt;")。然后,您需要转义 &lt;above command&gt; 中的特殊字符(如 $ 或其他双引号)以防止本地扩展。

    在您的特定情况下,您也可以通过不在远程端运行 awk 而是在本地运行它来解决此问题。所以这会起作用:

    ssh -t node1 'free -m' | awk 'NR==2{printf "Memory Usage: %s/%sMB (%.2f%%)\n", $3,$2,$3*100/$2 }'
    

    在许多情况下,这会导致更简单、更易读的解决方案。 (但是,您需要注意,如果您在本地处理远程数据,那么所有远程数据都会首先通过 ssh 传输——所以当您需要 grep 大量数据时不要这样做)。

    【讨论】:

      【解决方案4】:

      有没有办法执行上面的命令?

      首先用你想执行的命令定义一个函数。只在函数中编写格式良好的可读代码。记得使用 shellcheck 来检查常见错误。

      f() {
          free -m |
          awk '
              NR==2 {
               printf "Memory Usage: %s/%sMB (%.2f%%)\n", $3, $2, $3 * 100 / $2 
             }
          '
      }
      

      那你需要一个简单的小函数转义函数,我也发了here:

      sshqfunc() { echo "bash -c $(printf "%q" "$(declare -f "$1"); $1 \"\$@\"")"; };
      

      那么就:

      ssh -t node1 "$(sshqfunc f)"
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-11-14
        • 2022-11-13
        • 2012-11-05
        • 1970-01-01
        相关资源
        最近更新 更多