【问题标题】:Read line from stdin and run command on it从标准输入读取行并在其上运行命令
【发布时间】:2017-03-11 18:37:31
【问题描述】:

我正在尝试使用以下命令

gcloud compute instances list --format=json --regexp .*gluster.* | jq '.[].networkInterfaces[].networkIP' | tr -d '\"' | while read i; do gcloud compute ssh --zone $ZONE ubuntu@gluster-1 -- "sudo gluster peer probe $i && cat >> peers.txt"; done

基本上 gcloud 命令给出:

gcloud compute instances list --format=json --regexp .*gluster.* | jq '.[].networkInterfaces[].networkIP' | tr -d '\"'
10.128.0.2
10.128.0.3
10.128.0.4

但是运行上述命令似乎只在主机的第一个 ip 上运行,并给出警告

peer probe: success. Probe on localhost not needed

其他节点都没有连接。

注意事项: 奇怪的是在第二个节点上运行 gcloud 命令会连接到第一个节点,在第三个节点上运行根本不会做任何事情

除了第三个节点之外的所有节点上的 peers.txt 文件再次奇怪地只有后两个 ips

ubuntu@gluster-1:~$ cat peers.txt
10.128.0.3
10.128.0.4

对循环中的值运行 echo 给出

gcloud compute instances list --format=json --regexp .*gluster.* | jq '.[].networkInterfaces[].networkIP' | tr -d '\"' | while read i; do echo ip: $i; done
ip: 10.128.0.2
ip: 10.128.0.3
ip: 10.128.0.4

【问题讨论】:

  • 请注意,gcloud 融合了 jq 的许多特性。以下产生相同的结果gcloud compute instances list --format="value(networkInterfaces.networkIP)" --filter="name~gluster"

标签: bash shell gcloud


【解决方案1】:

管道进入循环没有任何问题(假设您不需要循环体在当前外壳中执行)。不过,您不想为这样的事情使用for 循环;请参阅Bash FAQ 001 了解更多信息。使用while 循环。

gcloud compute instances list --format=json --regexp .*gluster.* | 
  jq -r '.[].networkInterfaces[].networkIP' |
  while IFS= read -r ipaddr; do
    echo "$ipaddr"
  done

(请注意,将-r 选项与jq 一起使用无需将输出通过管道传输到tr 以删除双引号。)

您可能会看到的问题是您放入while 循环的命令 从标准输入读取,这会在read 读取数据之前从您的管道中读取数据。在这种情况下,您可以从/dev/null 重定向标准输入:

gcloud compute instances list --format=json --regexp .*gluster.* | 
  jq -r '.[].networkInterfaces[].networkIP' |
    while IFS= read -r i; do
      gcloud compute ssh --zone $ZONE ubuntu@gluster-1 \
        -- "sudo gluster peer probe $i < /dev/null &&
      cat >> peers.txt"
    done

或者,使用进程替换从不同的文件描述符中读取。

while IFS= read -r i <&3; do
  gcloud ...
done 3< <(gcloud compute instances .. | jq -r '...')

【讨论】:

    【解决方案2】:

    让它与 for 循环一起工作。

    还了解到 for 循环不适用于管道:)

    for item in $(gcloud compute instances list --format=json --regexp .*gluster.* | jq '.[].networkInterfaces[].networkIP' | tr -d '\"'); do gcloud compute ssh --zone $ZONE ubuntu@gluster-1 -- "sudo gluster peer probe $item && echo $item >> peers.txt"; done
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-08-06
      • 2014-11-30
      • 1970-01-01
      • 1970-01-01
      • 2014-12-16
      相关资源
      最近更新 更多