변수에서 stderr를 리디렉션하지만 콘솔에서 stdout을 유지하는 방법

변수에서 stderr를 리디렉션하지만 콘솔에서 stdout을 유지하는 방법

내 목표는 명령을 호출하고 변수에서 stderr을 가져오되 화면에는 stdout(및 stdout만)을 유지하는 것입니다. 예, 그것은 대부분의 사람들이 하는 것과 반대입니다 :)

현재 내가 가진 최고는 다음과 같습니다.

#!/bin/bash
pull=$(sudo ./pull "${TAG}" 2>&1)
pull_code=$?

if [[ ! "${pull_code}" -eq 0 ]]; then
  error "[${pull_code}] ${pull}"
  exit "${E_PULL_FAILED}"
fi

echo "${pull}"

그러나 이는 성공 시와 명령이 완료된 후에만 표준 출력을 표시합니다. 표준 출력을 스트리밍하고 싶습니다. 이것이 가능합니까?

편집하다

@sebasth와 도움을 받아 감사드립니다.임시 파일 없이 STDERR 및 STDOUT을 다른 변수로 리디렉션, 나는 다음과 같이 씁니다.

#!/bin/bash
{
  sudo ./pull "${TAG}" 2> /dev/fd/3
  pull_code=$?
  if [[ ! "${pull_code}" -eq 0 ]]; then
    echo "[${pull_code}] $(cat<&3)"
    exit "${E_PULL_FAILED}"
  fi
} 3<<EOF
EOF

나는 이것이 실제로 "아름답지" 않다는 것을 인정하고, 까다로워 보이며, heredoc이 왜 필요한지 정말로 이해하지 못합니다...

이것이 이것을 달성하는 더 좋은 방법입니까?

답변1

그냥 사용:

{ err=$(cmd 2>&1 >&3 3>&-); } 3>&1

cmdstdout을 변경하지 않고 stderr을 얻으려면 (여기서 fd 3을 사용하여)가져오다3>&1명령 대체의 원본 stdout(복사본)( >&3fd 2를 명령 대체에 의해 생성된 파이프로 리디렉션한 후 복원됨 2>&1)).

답변2

아래 제공된 답변을 사용할 수 있습니다스티븐 차제라스약간의 수정: stderr를 리디렉션하고 명령 대체 없이 명령을 실행합니다.

{
  command 2> /dev/fd/3
  res=$?
  err=$(cat<&3)
} 3<<EOF
EOF

printf 'stderr: %s\n' "$err"

의 출력은 command일반적으로 stdout에 있고 stderr은 err변수에 있습니다.

답변3

stderr을 캡처하는 명령으로 stdout과 stderr을 바꾸십시오.

pull=$(sudo ./pull "${TAG}" 3>&2 2>&1 1>&3)

그런 다음 stderr를 다시 stdout으로 리디렉션합니다.

{ pull=$(sudo ./pull "${TAG}" 3>&2 2>&1 1>&3; } 2>&1

설명하다:

명령의 표준 출력만 캡처할 때와 같은 방식으로:

var=$(cmd)

stderr에 대한 출력은 여전히 ​​명령줄로 이동합니다. 두 채널을 교환하여 stderr만 캡처할 수 있습니다.

var=$(cmd 3>&2 2>&1 1>&3)

그런 다음 stderr를 다시 stdout으로 리디렉션합니다(출력이 있는 경우 표시하기 위해).

{ var=$(f 3>&2 2>&1 1>&3); }  2>&1

답변4

양쪽의 답변을 결합하세요출력을 화면 오버레이로 리디렉션하는 방법그리고bash 키워드(예: 시간)의 표준 오류를 캡처하는 방법은 무엇입니까?,나는 얻다

var=$( (cmd >/dev/tty) 2>&1)

내장된 함수나 키워드를 사용하지 않는 경우 다음과 같이 단순화할 수 있습니다.

var=$( cmd 2>&1 >/dev/tty )

관련 정보