【问题标题】:producing a bash command with awk giving runaway string constant - awk使用 awk 生成一个 bash 命令,给出失控的字符串常量 - awk
【发布时间】:2015-03-31 19:42:07
【问题描述】:

我正在使用awk 解析/etc/hosts 并生成一个命令,该命令将为我格式化MapR。这是在Chefbash 实用程序中完成的:

egrep '^[0-9]' /etc/hosts | grep -v 127.0.0.1 \
      | awk 'NR==1{ips=$1} 
              NR>1{ips=ips ", " $1} 
              $2=="namenode"{nn=$1} 
              END{ printf "/opt/mapr/server/configure.sh -C %s -Z %s -N mycluster --create-user -D /dev/xvdb\n", ips, nn}' \
      | bash
  sleep 60

上面的命令应该执行以下命令:

/opt/mapr/server/configure.sh -C 10.32.237.251 -Z 10.32.237.251 -N mycluster --create-user -D /dev/xvdb

但是,查看我的 chef 输出我看到:

==> namenode: Executing awk utility
==> namenode: awk: line 1: runaway string constant "/opt/mapr/ ...

该命令从未在MapR 节点中执行...但是,当我直接在终端上执行它时,它以应有的方式很好地工作。我究竟做错了什么? 我正在更新问题以显示执行该实用程序的完整 bash 脚本:

DISK_CONFIG=/home/ubuntu/disk_config
if [ -f $DISK_CONFIG ];
then
  echo "File already exists"
else
  echo "Executing awk utility\n"
  touch $DISK_CONFIG
  egrep '^[0-9]' /etc/hosts | grep -v 127.0.0.1 \
      | awk 'NR==1{ips=$1} 
              NR>1{ips=ips ", " $1} 
              $2=="namenode"{nn=$1} 
              END{ printf "/opt/mapr/server/configure.sh -C %s -Z %s -N mycluster --create-user -D /dev/xvdb\n", ips, nn}' \
      | bash
  sleep 60
fi

【问题讨论】:

  • 你写的东西看起来无可挑剔(好吧,足够干净,无论如何它不应该产生那个错误)。因此,我们必须猜测您以某种方式执行了与您向我们展示的脚本不同的东西。我建议暂时放弃| bashsleep 60,并通过bash -x 运行脚本的其余部分。看看它给了你什么。 (当我在 Mac 上尝试时,它“工作”,虽然没有“namenode”值,所以该命令在-Z-N 之间只有空格。)
  • | bashsleep 60 都不会导致您的问题,但是在测试时,您不想意外执行 configure.sh 脚本,也不想在尝试之间等待 60 秒试试你的脚本。要么“厨师”把你搞砸了,要么它没有运行你认为它正在运行的代码。我不熟悉“厨师”。在命令行测试您的脚本(不使用 bash 或 sleep)。使用bash -x yourscript.sh 看看发生了什么。如果这是您显示的内容,则不应出现错误。您是否不小心使用了文字处理双引号()而不是 "
  • 这是-v 上的awk - 你没有变量。
  • @MarkSetchell:是的;那可以做到。同样值得注意的是,代码的原始演示文稿中缺少-v。当缺少关键信息时,调试代码是如此困难! ……但是……话虽如此,使用 BSD awk,我得到“无效的 -v 选项”,使用 GNU awk,我得到一个完整的使用消息,并添加了 -v
  • \n 中的awk 语句可能会导致问题。你能改用\\n 吗?

标签: linux bash awk chef-infra


【解决方案1】:

假设您在 bash 资源中使用 HEREDOC 语法:

bash "whatever" do
  code <<-EOH
    DISK_CONFIG=/tmp/disk_config
    if [ -f $DISK_CONFIG ];
    then
      echo "File already exists"
    else
      echo "Executing awk utility\n"
      touch $DISK_CONFIG
      egrep '^[0-9]' /etc/hosts | grep -v 127.0.0.1 \
          | awk 'NR==1{ips=$1}
                  NR>1{ips=ips ", " $1}
                  $2=="namenode"{nn=$1}
                  END{ printf "/opt/mapr/server/configure.sh -C %s -Z %s -N mycluster --create-user -D /dev/xvdb\n", ips, nn}' \
          | bash
    fi
  EOH
end

这会导致你的错误:

Executing awk utility

awk: line 4: runaway string constant "/opt/mapr/ ...

这是由于您的命令中的 \n (awk 命令中的那个也可能有问题)

这个资源应该做(警告我确实为我的测试替换了 DISK_CONFIG 路径):

bash "whatever" do
  code <<-EOH
    DISK_CONFIG=/tmp/disk_config
    if [ -f $DISK_CONFIG ];
    then
      echo "File already exists"
    else
      echo "Executing awk utility"
      touch $DISK_CONFIG
      egrep '^[0-9]' /etc/hosts | grep -v 127.0.0.1 \
           | awk 'NR==1{ips=$1}
              NR>1{ips=ips ", " $1}
              $2=="namenode"{nn=$1}
              END{ printf "/opt/mapr/server/configure.sh -C %s -Z %s -N mycluster --create-user -D /dev/xvdb", ips, nn}' \
           | bash
      sleep 60
    fi
  EOH
end

原因是 Chef 已经解释了代码中的 \n,因此 awk 看到了一个永不结束的字符串(失控)。

当您通过管道连接到 bash 时,您可以省略 \n,因为管道将结束该行。

【讨论】:

  • 读者注意:如果您使用&lt;&lt;-word heredoc 表单,请确保word 之前只有tab 字符来结束文档。
  • @glennjackman 这是heredoc 参考,但在ruby 中,只要结尾词单独出现在它的行上,任何数量的空格都可以工作。 (并且在起始词之前没有-,结束词必须在行首,我们已经完成了我认为的警告;))。
猜你喜欢
  • 2014-07-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-11-24
  • 1970-01-01
  • 1970-01-01
  • 2017-11-25
  • 2019-10-28
相关资源
最近更新 更多