【问题标题】:Exiting if a command returns an empty string when run in a heredoc (ssh ... <<EOF)如果命令在 heredoc 中运行时返回空字符串,则退出 (ssh ... <<EOF)
【发布时间】:2018-12-30 07:14:09
【问题描述】:

如果命令在EOF 中没有返回任何输出,我希望我的命令以失败状态 (1) 退出。但我无法使用变量来存储命令或将输出存储在文件中。

例如:

#!/bin/bash
a='Some other commands in local machine'
ssh ubuntu@xx.xx.xx.xx << EOF
echo $a;
ldt=$(date +'%Y%m%d')
awk -v start="$(date +'%Y/%m/%d %H:%M' --date '-1000 min')" - F'[[:space:]]*[|][[:space:]]*' '
(\$4>=start) && /INFO: Server startup in/
' /some/file/path-\$ldt.log
EOF

现在,如果命令给出一个空输出,它应该是exit 1,如果显示一些文本,它应该是exit 0

我无法将awk 命令存储在变量中。如果我将它存储在变量中,awk 命令不起作用。尝试将输出存储在文件中,但这也失败了。

请帮我找到解决办法。

【问题讨论】:

  • 它“不起作用”,因为未引用的 heredoc 导致在远程代码运行之前发生扩展。不要那样做。
  • 我假设ldt 应该是“本地”日期时间?最初不是——date 是由本地机器运行的,而不是远程机器。
  • 本地机器或远程机器上的日期相同,所以@CharlesDuffy 没有关系
  • ...但是如果您的日期格式中包含空格,这很重要 -- ldt=$(date '+%Y%m%d %H%M%S') 如果作为本地命令运行很好,但会尝试运行您的%H%M%S 结果为带有环境变量 ldt 的命令,否则导出,因为在本地运行扩展时,远程 shell 将空间视为语法上重要的,而不是数据。也就是说,这是一个值得内化并养成思考习惯的差异。
  • @CharlesDuffy 是的,你是对的,是我的错误。我会更加小心。

标签: bash shell eof exit-code heredoc


【解决方案1】:

当您使用未引用的 heredoc -- &lt;&lt;EOF -- 在将其输入到 stdin 到被调用的命令之前运行其中的扩展。

这包括$(awk ...),因此很难正确捕获以这种方式生成的代码的输出并在以后对其进行操作。

因此,您可以做的一件事是使用引用的 heredoc,然后返回您之前尝试过的方法(捕获 awk 结果并对其进行分支),它应该可以正常工作。

您可以做的另一件事是让awk 根据是否找到任何匹配项来设置自己的退出状态。

awk中设置退出状态

#!/bin/bash
a='Some other commands in local machine'
printf -v args_q '%q ' "$a"

ssh ubuntu@xx.xx.xx.xx "bash -s $args_q" <<'EOF'
  a=$1
  echo "$a"
  ldt=$(date +'%Y%m%d')
  awk -v start="$(date +'%Y/%m/%d %H:%M' --date '-1000 min')" -F'[[:space:]]*[|][[:space:]]*' '
    BEGIN { found=0 }
    ($4>=start) && /INFO: Server startup in/ { print $0; found=1; }
    END { if (found == 0) { exit(1) } else { exit(0) } }
  ' "/some/file/path-$ldt.log"
EOF

设置退出状态之后 awk

#!/bin/bash
a='Some other commands in local machine'
printf -v args_q '%q ' "$a"

ssh ubuntu@xx.xx.xx.xx "bash -s $args_q" <<'EOF'
  a=$1
  echo "$a"
  ldt=$(date +'%Y%m%d')
  awk_result=$(
    awk -v start="$(date +'%Y/%m/%d %H:%M' --date '-1000 min')" -F'[[:space:]]*[|][[:space:]]*' '
      BEGIN { found=0 }
      ($4>=start) && /INFO: Server startup in/ { print $0; found=1; }
      END { if (found == 0) { exit(1) } else { exit(0) } }
    ' "/some/file/path-$ldt.log"
  )
  [[ $awk_result ]] && echo "$awk_result"
  [[ $awk_result ]] # success only if awk_result is nonempty
EOF

请注意,这&lt;&lt;EOF 已更改为 &lt;&lt;'EOF' 时才有效,以便远程评估 awk 命令。

【讨论】:

  • %q 是做什么的?它是语法的一部分吗?让我试试这个。
  • printf %qeval-safe 形式发出一个字符串。如果您没有使用足够有趣的字符串进行测试,它可能不会看起来在做任何事情,但它对于面对异常或恶意数据时的正确性至关重要。
  • 感谢您提供有用的信息!这有效,但如果找到,则不会打印字符串的输出。我尝试了Setting Exit Status After awk 方法。
  • echo "$awk_result",然后。
  • (如果 "Could not resolve host:" 之后没有任何内容,则表示实际上没有主机名传递给 curl;也许您依赖于未通过参数列表?)
猜你喜欢
  • 1970-01-01
  • 2016-12-30
  • 2018-11-16
  • 1970-01-01
  • 2019-12-17
  • 2023-01-26
  • 2017-03-22
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多