쉘 명령에서 stdout 및 sterr과 올바른 파이프 종료 상태를 캡처하는 방법은 무엇입니까?

쉘 명령에서 stdout 및 sterr과 올바른 파이프 종료 상태를 캡처하는 방법은 무엇입니까?

나는 다음을 할 수 있기를 원합니다:

command 2>&1 | shell_script.sh "subject line"

실행의 stdout 및 sterr이 command파이프로 연결되어 shell_script.sh이메일 본문으로 전송됩니다. 내가 얻고 싶은 것은 command 2>&1이메일 제목에 올바른 작업 상태를 추가할 수 있도록 종료 상태입니다. 현재 구현에서는 항상 command 2>&1when piping ${PIPESTATUS[0]}으로 설정 됩니다 0. 그러나 해당 항목을 제거하면 2>&1stderr 출력이 이메일 본문으로 파이프되지 않습니다. 몇 가지 다른 변형을 시도했지만 여전히 알아낼 수 없습니다.

다음은 내 것입니다 shell_script.sh.

#!/usr/bin/env bash
SUBJ="$@"
read EMAIL_BODY
jobsuccess=${PIPESTATUS[0]}

if [ $jobsuccess -eq 0 ]  # Job succeeded
then
        echo $EMAIL_BODY | mail -s "$SUBJ Success" [email protected]
else
        echo $EMAIL_BODY | mail -s "$SUBJ Fail" [email protected]
fi

답변1

#!/bin/bash

subject="subject line"

tmpfile=$(mktemp)
trap 'rm -f "$tmpfile"' EXIT

if command >"$tmpfile" 2>&1; then
    subject+=" Success"
else
    subject+=" Failure"
fi

mail -s "$subject" [email protected] <"$tmpfile"

따라서 출력을 임시 파일에 저장한 다음 파일을 메일로 보내십시오. 보내기 전에 명령의 종료 상태에 따라 제목 줄을 설정합니다. 두 개의 스크립트가 필요하지 않습니다.

PIPESTATUS파이프라인이 아직 실행을 완료하지 않았기 때문에 파이프라인 내부에 액세스할 수 없습니다 . 게다가 자체 환경에서 실행되기 때문에 외부 스크립트는 어떤 상황에서도 접근할 수 없습니다.

일반 명령에서 입력을 파이프한 다음 해당 명령의 종료 상태에 대해 작업하는 것도 불가능합니다. 파이프라인에서 이전 명령의 종료 상태는 파이프라인 자체에서 액세스할 수 없습니다.

너 뭐야할 수 있다do는 성공 또는 실패를 나타내는 텍스트를 출력하는 코드로 명령을 래핑합니다. 이 텍스트는 나머지 데이터와 함께 파이프됩니다(필요한 경우 끝에 추가 정보로).

{ if command 2>&1; then echo SUCCESS; else echo FAILURE; } | shell_script.sh

...그리고 shell_script.sh존재

#!/bin/bash

subject="subject line"

tmpfile=$(mktemp)
trap 'rm -f "$tmpfile"' EXIT

cat >"$tmpfile"

if [[ $(tail -n 1 "$tmpfile") == *SUCCESS* ]]; then
    subject+=" Success"
else
    subject+=" Failure"
fi

sed '$d' "$tmpfile" | mail -s "$subject" [email protected]

마지막 줄에 액세스하려면 데이터를 임시 파일에 저장해야 합니다(이 작업은 cat기본적으로 읽혀지는 표준 입력을 사용하여 수행됩니다). 그런 다음 성공 여부를 결정하고 이에 따라 테마를 설정합니다. 그러면 마지막 행이 제거된 데이터가 메일로 전송됩니다.

또 다른 옵션은 메일 스크립트를 실행하는 것입니다.뒤쪽에명령을 실행한 다음(파이프라인의 명령이 동시에 실행됨) 종료 상태를 명령줄 인수로 전달합니다.

command >command.log 2>&1
shell_script.sh "$?" <command.log
rm -f command.log

스크립트는 다음과 같습니다

#!/bin/bash

subject="subject line"

if [[ $1 == 0 ]]; then
    subject+=" Success"
else
    subject+=" Failure"
fi

mail -s "$subject" [email protected]

이 경우 메일로 보낼 데이터는 표준 입력을 통해 전달되며 mail유틸리티는 기본적으로 이를 읽습니다( cat이전 예에서와 마찬가지로).

관련 정보