답변:
POSIX에 해당하는 것이 없습니다. exec
포크가 아닌 로만 리디렉션을 수행 할 수 있습니다 . 파이프에는 포크가 필요하고 껍질은 아이가 끝날 때까지 기다립니다.
한 가지 해결책은 모든 코드를 함수에 넣는 것입니다.
all_my_code () {
…
}
{ all_my_code |
logger --priority user.notice --tag "$(basename "$0")"; } 2>&1 |
logger --priority user.error --tag "$(basename "$0")"
(이것은 또한 로거의 stdout 인스턴스에서 stderr 인스턴스로의 모든 오류를 기록합니다. 더 많은 파일 디스크립터 셔플 링으로이를 피할 수 있습니다.)
logger
프로세스가 여전히 실행중인 경우에도 상위 쉘을 종료 &
하려면 logger
호출 끝에 두십시오 .
{ all_my_code |
logger --priority user.notice --tag "$(basename "$0")" & } 2>&1 |
logger --priority user.error --tag "$(basename "$0")" &
또는 명명 된 파이프를 사용할 수 있습니다.
pipe_dir=$(mktemp -d)
mkfifo "$pipe_dir/out" "$pipe_dir/err"
<"$pipe_dir/out" logger --priority user.notice --tag "$(basename "$0")" &
<"$pipe_dir/err" logger --priority user.error --tag "$(basename "$0")" &
exec >"$pipe_dir/out" 2>"$pipe_dir/err"
…
rm -r "$pipe_dir"
logger
하고 동일한 입력을 각 인스턴스에 전달합니다.
_log()( x=0
while [ -e "${TMPDIR:=/tmp}/$$.$((x+=1))" ]
do continue; done &&
mkfifo -- "$TMPDIR/$$.$x" &&
printf %s\\n "$TMPDIR/$$.$x" || exit
exec >&- >/dev/null
{ rm -- "$TMPDIR/$$.$x"
logger --priority user."$1" --tag "${0##*/}"
} <"$TMPDIR/$$.$x" &
) <&- </dev/null
다음과 같이 사용할 수 있어야합니다.
exec >"$(_log notice)" 2>"$(_log error)"
mktemp
명령 을 사용하는 버전은 다음과 같습니다 .
_log()( p=
mkfifo "${p:=$(mktemp -u)}" &&
printf %s "$p" &&
exec <&- >&- <>/dev/null >&0 &&
{ rm "$p"
logger --priority user."$1" --tag "${0##*/}"
} <"$p" &
)
... mktemp
파일 이름을 선택할 수 있다는 점을 제외하고는 거의 동일 합니다. 이것은 프로세스 대체 가 결코 마 법적이지 않기 때문에 작동하며 명령 대체 와 매우 유사한 방식으로 작동합니다 . 명령 대체 가 수행하는대로 확장을 대체하는 명령 실행 값으로 확장을 대체하는 대신 프로세스 대체 는 출력을 찾을 수있는 파일 시스템 링크의 이름으로 대체합니다.
POSIX 쉘은 그러한 것들에 대한 직접적인 결과를 제공하지는 않지만 에뮬레이션은 매우 간단합니다. 파일을 만들고, 명령 대체에서 표준으로 이름을 인쇄하고, 동일한 배경에서 명령을 실행하면 해당 파일로 출력됩니다. - 이제 당신은 그 확장의 값으로 재 지정할 수 있습니다 정확히 당신이 프로세스 대체와 마찬가지로. POSIX 셸은 물론 필요한 모든 도구를 제공합니다. 필요한 것은 도구를 자신에게 맞는 방식으로 사용하기 만하면됩니다.
위의 두 버전은 파일 시스템을 사용하기 전에 작성 / 사용하는 파이프에 대한 파일 시스템 링크를 제거합니다. 즉, 사실 후에 정리가 필요하지 않으며, 더 중요한 것은 스트림을 처음 여는 프로세스에서만 스트림을 사용할 수 있으므로 파일 시스템 링크를 로깅 활동을 스누핑 / 강탈하는 수단으로 사용할 수 없습니다. 파일 시스템에 fs-links를 두는 것은 잠재적 인 보안 허점입니다.
다른 방법은 포장하는 것입니다. 스크립트 내에서 수행 할 수 있습니다.
x=${x##*[!0-9]*}
_log(){
logger --priority user."$1" --tag "${0##*/}"
} 2>/dev/null >&2
cd ../"$PPID.$x" 2>/dev/null &&
trap 'rm -rf -- "${TMPDIR:-/tmp}/$PPID.$x"' 0 ||
{ until cd -- "${TMPDIR:=/tmp}/$$.$x"
do mkdir -- "$TMPDIR/$$.$((x+=1))"
done &&
x=$x "$0" "$@" | _log notice
exit
} 2>&1 | _log error
기본적으로 스크립트가 아직 호출되지 않은 경우 자체 호출하여 작업 디렉토리를 부팅 할 수있게합니다.
mktemp
다른 비표준 명령 을 사용하려는 경우 다음 과 같습니다 _log()( p=; mkfifo "${p:=$(mktemp -u)}"; printf %s "$p"; exec <&- >&- <>/dev/null >&0; { rm "$p"; logger --priority user."$1" --tag "${0##*/}"; } <"$p" &)
.. 나는 당신의 것을 제외하고는 모든 방법으로 완전히 휴대용 명령 언어를 사용하여 그것을 썼습니다. 또한 basename
매우 유용한 유틸리티는 아닙니다. "${0##*/}"
더 강력하고 빠릅니다.
.xprofile
가 함께 실행되는 sh
.
zsh
입니다. 첫 부분은 : { this; can\'t; happen; before; } < this
. 도움이 되나요?