【问题标题】:Pipe command output inside other command管道命令输出在其他命令中
【发布时间】:2021-10-24 09:56:21
【问题描述】:

我正在尝试将第一个命令的输出通过管道传递到第二个命令末尾的引号中。

kubectl --context foo -n foo get secret postgres.foo-db.credentials -o jsonpath={.data.password}

kubectl --context foo -n foo patch secret postgres.foo-db.credentials -p '{"data":{"password":"    Output from command 1    "}}'

我已经尝试过这个:piping output into middle of bash command,但是这个命令出现以下错误:

kubectl --context foo -n foo patch secret postgres.foo-db.credentials -p '{"data":{"`password":"kubectl --context foo -n foo get secret postgres.foo-db.credentials -o jsonpath={.data.password}`"}}'

The request is invalid: patch: Invalid value: "map[data:map[`password:kubectl --context foo  -n foo  get secret postgres.foo-db.credentials -o jsonpath={.data.password}`]]": error decoding from json: illegal base64 data at input byte 7

【问题讨论】:

  • 管道在这里不行。你需要command substitution,因为你的命令的一部分应该被另一个命令的标准输出代替。
  • @WytrzymałyWiktor 是的:)

标签: json shell command kubectl


【解决方案1】:

您可以将命令一分为二以便于理解,并让 bash shell 在第二行扩展变量 pgsecret:

pgsecret="$(kubectl --context foo -n foo get secret \
  postgres.foo-db.credentials -o jsonpath={.data.password})"
kubectl \
  --context foo -n foo patch secret \
  postgres.foo-db.credentials -p '{"data":{"password":"'$pgsecret'"}}'

【讨论】:

  • 你确定你的答案是正确的吗?我已经对此进行了测试,并且在我的环境中收到了一个错误。 IMO "'$pgsecret'" 只能使用双引号:"$pgsecret"。看这里:askubuntu.com/questions/605411
  • 我在 bash 环境中没有这样的问题。单引号被 bash 剥离。
  • 使用pgsecret=$(echo "XXX" | base64); kubectl -n myns patch secret testsecret -p '{"data":{"password":"'$pgsecret'"}}'成功测试
【解决方案2】:

Davide Madrisan 的想法很好。代码将更具可读性。但是使用此解决方案,您可能会收到错误消息。在命令中:

kubectl --context foo -n foo patch secret postgres.foo-db.credentials -p '{"data":{"password":"'$pgsecret'"}}'

对变量"'$pgsecret'" 的引用带有双引号和单引号。双精度很好,因为它必须是"key":"value" 结构。但是在我的环境中,单引号是错误的。我收到一个错误:

Error from server (BadRequest): invalid character '<wrong character>' after object key:value pair

您可以详细了解' 和" here 之间的区别。

我建议去掉单引号:

pgsecret="$(kubectl --context foo -n foo get secret \
  postgres.foo-db.credentials -o jsonpath={.data.password})"
kubectl \
  --context foo -n foo patch secret \
  postgres.foo-db.credentials -p '{"data":{"password":"$pgsecret"}}'

或者如果您想在没有变量的情况下在一行中执行此操作(可读性较差的代码):

kubectl --context foo -n foo patch secret postgres.foo-db.credentials -p '{"data":{"password":"$(kubectl --context foo -n foo get secret postgres.foo-db.credentials -o jsonpath={.data.password})"}}'

也应该与您合作。这种处理方式称为command substitution,正如评论中提到的user1934428:

管道在这里不行。您需要command substitution,因为您的命令的一部分应该被另一命令的标准输出替换。

【讨论】:

  • 如果pgsecret 包含例如WFhYCg==,则 bash 将去掉单引号并将 {"data":{"password":"WFhYCg=="}} 传递给 kubectl,这正是你想要什么。您的版本将通过 {"data":{"password":"$pgsecret"} 而 kubectl 将抱怨以下错误消息 The request is invalid: patch: Invalid value: "map[data:map[password:$pgsecret]]": error decoding from json: illegal base64 data at input byte 0
【解决方案3】:

反引号(又名 $())不用作单引号内的命令替换,而是文字:

$ echo '$(echo foo)'
$(echo foo)

它们被插在双引号内:

$ echo "$(echo foo)"
foo

所以你只需要正确引用你的替换:

$ kubectl --context ... -p '{"data":{"password":"'"$(cmd to get passwd)"'"}}'

你也可以写:

$ kubectl --context ... -p "{\"data\":{\"password\":\"$(cmd to get passwd)\"}}"

【讨论】:

    猜你喜欢
    • 2011-09-13
    • 1970-01-01
    • 2019-11-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-08-11
    • 2018-08-18
    • 1970-01-01
    相关资源
    最近更新 更多