shell 在后续jq命令中同时使用curl的stdout和stderr

ecfsfe2w  于 2023-02-05  发布在  Shell
关注(0)|答案(1)|浏览(146)

我想做以下几点,

command2(stdout)
        /                \
command1                  command4
        \                /
         command3(stderr)

因为它包含在How can I split and re-join STDOUT from multiple processes?
除了,command1向stdout和stderr输出不同的文本,因此,它是上述问题和Pipe stderr to another command的组合
有一个背景,我试图实现:
1.执行 curl
1.捕获原始输出(stdout)base64,并将其嵌入到json中:curl https://someaddress.tld | base64 | jq --raw-input '{"curl_ret" : .}'
1.输出curl json(返回代码等)并将其传递给stderrcurl --write-out '%{stderr}%{json}' https://someaddress.tld
1.假设#2和#3是同一个curl调用,我想合并#2和#3的输出,并将合并后的结果传递给jq:jq --slurp ...
所有这些都在一个管道命令。
stdout和stderr分离是为了避免解析合并的文本,为了避免陷阱,给定的curl输出可以是任何内容。Curl具有--silent开关,因此在任何输出流中都不会出现意外的文本

13z8s7eq

13z8s7eq1#

在实践中,对于手头的用例

您根本不需要这样做。--write-out '%{json}'总是写在body内容之后,所以它总是stdout的最后一行,将它放在同一个流中是安全的。

getExampleAndMetadata() {
  curl --write-out '%{json}' https://example.com |
    jq -RSs '
      split("\n")
      | {"body": .[:-1] | join("\n"),
         "logs": .[-1] | fromjson}'
}

作为练习

这很难看,我不推荐这样做--最好只是从stdout中解析出两组数据,并将stderr保留为空,这样您就可以记录实际的错误--但是,按照您的要求做:

getExampleAndMetadata() {
  local tmpdir retval=0
  # mkfifo is different between operating systems, adjust to fit
  tmpdir=$(mktemp -d sa_query.XXXXXX) || return
  mkfifo "$tmpdir/stdout" "$tmpdir/stderr" || { retval=$?; rm -rf "$tmpdir"; return "$retval"; }
  curl --silent --write-out '%{stderr}%{json}' https://example.com \
    >"$tmpdir/stdout" 2>"$tmpdir/stderr" & curl_pid=$!
  # must read stdout _before_ stderr to avoid a deadlock here
  # to stop caring what order of operations jq uses, we use process substitutions
  # to buffer both stdout and stderr in-memory
  jq -Rn \
    --rawfile content <(out=$(cat "$tmpdir/stdout"); printf '%s\n' "$out") \
    --slurpfile logs <(err=$(cat "$tmpdir/stderr"); printf '%s\n' "$err") \
    '{"body": $content, "logs": $logs}'; (( retval |= $? ))
  rm -rf -- "$tmpdir"; (( retval |= $? ))
  wait "$curl_pid"; (( retval |= $? ))
  return "$retval"
}

...给你一个简单的命令,getExampleAndMetadata。当然,如果你去掉了注解和续行符,你可以通过适当地添加;把整个内容压缩成一行。

相关问题