我在谷歌云有一组机器。我的本地人:
gcloud compute instance-groups list-instances workers
OUTPUT:
NAME ZONE STATUS
workers-lya2 us-central1-a RUNNING
workers-23d4 us-central1-a RUNNING
...
workers-3asd3 us-central1-a RUNNING 我希望从该列表中获得一个随机的工作人员名称(比如workers-23d4),并将第一个命令中的区域us-central1-m粘贴到下面的命令中:
gcloud compute --project "my-project" ssh --zone "<zone_name_from_first_command> "<machine_name_from_first_command>"有点虚弱的巴什。请帮帮忙
发布于 2017-01-22 13:36:57
gcloud compute instance-groups list-instances workers | grep -v "^NAME" | shuf -n 1 | awk '{print $1, $2}' |
while read machine zone; do
export SELECTED_MACHINE="$machine"
export SELECTED_ZONE="$zone"
done
gcloud compute --project "my-project" ssh --zone "$SELECTED_ZONE" "$SELECTED_MACHINE"grep -v "^NAME"剥离所有以NAME开头的行(假设它只是您想要删除的第一行)shuf从剩下的行中取一条随机行awk '{print $1, $2}'在空格处拆分行并打印第一列和第二列while read将awk的输出读入变量$machine和$zone。Update:上面的代码适用于zsh,但不适用于bash,因为bash在子doesn (zsh不运行)和只将变量传递给子进程吗? (而不是父进程)中运行管道。下面的脚本通过在父进程中运行read来解决这个问题:
machine_zone=$(gcloud compute instance-groups list-instances workers |
grep -v "^NAME" | shuf -n 1 | awk '{print $1, $2}')
read machine zone <<< $machine_zone
gcloud compute --project "my-project" ssh --zone "$zone" "$machine"发布于 2017-01-22 16:15:18
以下命令从gcloud命令的输出中选择一个随机行(不包括标头),然后将前两个“单词”存储到machine和zone变量中:
read -r machine zone unused <<< $(
gcloud compute instance-groups list-instances workers | \
perl -e '@_ = <>; shift @_; print $_[rand @_]'
)在这个命令之后,就可以使用machine和zone变量了,例如:
gcloud compute --project "my-project" ssh --zone "$zone" "$machine"解释
perl命令使用菱形操作符<>将标准输入的所有行读入<>数组。然后shift函数从@_中移除第一项。rand@_在零和@_中的项目数之间返回一个随机十进制数。十进制数在索引上下文中隐式转换为整数。因此,$_[rand @_]的结果是@_的一个随机项,即从gcloud命令输出的随机行。
使用命令替换捕获gcloud和perl命令的输出,并通过这里串传递给read命令。
我引用了第一段中的单词,因为shell根据IFS (输入字段分隔符)变量将字符序列解释为单词。因此,这里字符串中的IFS-separated单词被分配给machine (第一个单词)、zone (第二个单词)和unused (行的其余部分)变量。
-r选项禁用反斜杠的特殊含义。换句话说,在给定此选项时,read将不会尝试解释输入中的转义序列。
--大数线的情形
注意,该解决方案意味着gcloud命令的输出相对较小,即足够小,足以将整个文件读入数组。此操作速度快,但需要更多内存,而不是使用while <>循环逐行读取。如果输出非常大,或者内存非常有限,下面是另一种可能的解决方案:
read -r machine zone unused <<< $(
gcloud compute instance-groups list-instances workers | \
perl -e '<>; $. = 0; rand($.) < 1 && ($line = $_) while <>; print $line'
)其中<>读取标头;$.是保持当前行号的内建变量;其余的则从这本食谱获取。
发布于 2017-01-22 17:17:30
如果从其中提取随机行的输入很大,并且您希望避免像shuf那样将其作为一个整体读入内存,那么请考虑罗斯兰·奥斯马诺夫的有益回答中的第二个perl解决方案。
否则,hansaplast的有用答案使用一种基于shuf的多实用程序方法,该方法易于理解,但可以简化(而且,在撰写本文时,它存在缺陷):
read -r machine zone _ < \
<(gcloud compute instance-groups list-instances workers | tail +2 | shuf -n 1)
gcloud compute --project "my-project" ssh --zone "$zone" "$machine"read读取进程替换(<(...))的输出,可以确保在当前shell中执行read,这意味着它创建的变量对其余命令是可见的,特别是第二个gcloud调用。- By contrast, if you use a pipeline (`gcloud ... | read ...`), `read` executes in a _subshell_, and the variables it creates won't be seen by subsequent commands.
tail +2跳过输入中的第一行(标题行)。shuf -n 1从输入中提取一个随机选择的行。_作为传递给read的第三个变量的名称,在将前2个空格分隔的令牌读入$machine和$zone之后,该变量接收输入行的(未使用)其余部分。- If we only specified `machine` and `zone`, the `$zone` would receive not just the 2nd token, but the entire rest of the input line.
https://stackoverflow.com/questions/41791386
复制相似问题