종료 코드가 0인 경우 파일에 stdout을 어떻게 쓸 수 있나요?

종료 코드가 0인 경우 파일에 stdout을 어떻게 쓸 수 있나요?

이것스펀지"표준 입력을 받아 파일에 기록하는" 명령을 사용하면 동일한 파일 간에 파이프를 연결할 수 있습니다. 나는 스폰지 같은 유틸리티에 파이프하는 비슷한 작업을 하고 싶지만 소스 명령이 실패하면(0이 아닌 종료가 있는 경우) 스폰지 같은 유틸리티가 대상 파일을 변경하지 않고 그대로 두기를 원합니다.

대략 다음과 같습니다.

cue export package.cue | prettier --stdin-filepath .json
 | spongelike --abort-on-non-zero package.json

(이 특정 파이프라인을 두 개의 개별 명령으로 다시 작성할 수 있다는 것을 알고 있지만 이것이 다른 까다로운 시나리오에서도 유용할 수 있음을 알 수 있습니다.)

답변1

에서 동시에 시작 cmd1 | cmd2되었으며 모두 쉘의 하위 항목입니다 cmd1 .cmd2

cmd2언제 죽는지 알 수 없으며 cmd1종료 상태를 얻을 수도 없습니다. 부모(여기서는 셸)만 가능합니다.

따라서 원하는 작업을 수행하는 명령이 있는 경우 다음과 같이 호출할 수 없습니다.

cmd | that-command output-file

다음과 같아야 합니다.

that-command output-file cmd

하위 프로세스에서 시작하고, 파이프를 통해 표준 출력을 수집하고/하거나 어딘가(메모리 또는 임시 파일)에 저장하고, 하위 프로세스를 기다리고, 성공하면 that-command거기에 저장된 출력을 열고 덤프합니다.cmdoutput-file

이는 쉘 스크립트를 통해 수행할 수 있습니다. 예를 들면 다음과 같습니다.

#! /bin/sh -
usage() {
  printf >&2 'Usage: %s <output> <cmd> [<args>...]\n' "${0##*/}"
  exit 1
}
[ "$#" -ge 2 ] || usage
output=$1; shift

tmp=$(mktemp) || exit
exec > "$tmp" 3< "$tmp"
rm -f -- "$tmp" || exit

"$@" 3<&- && cat <&3 3<&- > "$output"

( mktemp아직 표준은 아니지만 일반적입니다).

여기에 사용됨:

cue export package.cue | that-script package.json prettier --stdin-filepath .json

또는 둘 다 성공 cue했는지 확인하세요 prettier.

that-script package.json ksh -o pipefail -c '
  cue export package.cue | prettier --stdin-filepath .json'

또는 ksh 옵션이 설치되어 있고 이 기능을 지원하는 다른 쉘 pipefail(적어도 zsh, bash, mksh, yash 포함). 이 옵션은 POSIX 표준의 다음 버전에 나타날 예정이므로 sh이미 갖고 있을 수도 있습니다. 이 경우 다음을 수행할 수도 있습니다.

that-script package.json eval 'set -o pipefail
  cue export package.cue | prettier --stdin-filepath .json'

이 문 내에서 실행되는 코드는 eval출력 파일이 생성되는 방식에 영향을 미칠 수 있습니다. 예를 들어 를 사용하면 umask를 설정하고 손상을 방지하는 데 사용할 수 있는 that-script output eval 'cd /some/dir; cmd'출력 파일이 에 생성됩니다 ./some/dirthat-script output eval 'umask 077; set -o noclobber; cmd'

관련 정보