실패 후 계단식 파이프라인 명령을 계속하는 방법

실패 후 계단식 파이프라인 명령을 계속하는 방법

명령을 실행하고 자체 스크립트를 사용하여 출력을 조작하고 있지만 스크립트가 실패하더라도 기본 명령이 중지되는 것을 원하지 않습니다.

예를 들어:

a-command | tee logfile.txt | myscript

내 스크립트가 중간에 실패하면 logfile.txt를 보고 내 스크립트가 작동을 멈춘 위치에서 중단되는 것을 확인합니다. 그러나 내가 원하는 것은 a-command가 계속 실행되고 logfile.txt에 전체 로그가 있도록 하는 것입니다. 스크립트를 디버그하고 오류를 수정할 수 있습니다.

처음 두 부분(명령 및 티)이 해당 작업을 수행하도록 마지막 파이프 부분을 선택 사항으로 처리하거나 오류 시 무시되도록 명령을 수정하는 방법은 무엇입니까?

[편집] a-command긴 작업입니다. 내 스크립트는 기본적으로 더 나은 보고 상태를 위해 명령이 실행되는 동안 출력을 조작합니다. 그래서 a-command작업을 마친 후에는 스크립트를 실행 하고 싶지 않습니다 .

답변1

a-command | tee logfile.txt | { myscript; cat >/dev/null; }

myscript그러면 (어떤 이유로든) 종료될 때까지 평소대로 파이프라인이 먼저 실행됩니다 . 이 시점에서는 더 이상 데이터가 도착하지 않을 때까지 cat읽기 작업이 이어집니다 tee. 읽은 데이터는 cat파이프로 연결되어 삭제됩니다 /dev/null.

먼저 종료/실패하지 않고 완료되면 a-command더 이상 데이터를 읽을 수 없으며 종료(?)될 수 있습니다. 종료 시 시작되지만 더 이상 읽을 데이터가 없으므로 즉시 종료되고 파이프가 완료됩니다.myscriptmyscriptmyscriptcat


투티 문제 해결논평파이프에 대한 올바른 종료 상태가 계속 표시되는지 확인하세요.

a-command | tee logfile.txt | ( myscript; err=$?; cat >/dev/null; exit "$err" )

답변2

Tee(Linux)에는 파이프 오류를 무시하는 옵션이 있습니다.

a-command | tee --output-error=warn logfile.txt | myscript

myscript가 실패하거나 종료되면 a-command가 계속 실행되고 로그가 계속해서 늘어납니다.

로그의 마지막 전체 청크가 캡처되면 스크립트를 다시 실행하고 종료할 수 있습니다.

myscript < logfile.txt

스크립트를 다시 실행하고 따라잡는 동안 추가될 때까지 기다리도록 할 수 있습니다.

tail -999999f < logfile.txt | myscript

Bash 스크립트에는 더 복잡한 예가 포함되어 있습니다.

logger는 명령을 나타냅니다. 초당 하나씩 36개의 짧은 문자열 순열을 생성합니다. 모든 출력은 593580.log를 가리킵니다.

awk는 "myscript"를 의미합니다. 입력의 하위 집합을 인쇄합니다.

wdog는 내 감시 유틸리티입니다. -d 5는 작업을 디버깅합니다. -t 25는 SIGUSR1을 사용하여 25초 후에 제어 프로세스(awk)가 시간 초과되도록 합니다. 이를 통해 스크립트 실패를 시뮬레이션하기 위해 수동으로 종료를 실행할 수 있습니다. 저는 반복 가능한 테스트를 좋아합니다.

awk가 사라지면 동일한 복합 명령의 cat이 파이프 읽기를 시작하고 나머지 데이터를 중복 로그에 복사합니다. 따라서 전체 로그 또는 처리되지 않은 데이터에 대해 스크립트를 다시 실행할 수 있으며 두 로그를 비교하여 충돌이 발생한 정확한 위치를 찾을 수 있습니다.

또는 cat >/dev/null파이프라인을 활성 상태로 유지하여 로거가 계속 실행되도록 할 수도 있습니다.

두 로그 파일 복사본 모두 라인 버퍼링된 것으로 나타납니다. tail -f는 이를 실시간으로 보여줍니다.

예시 스크립트:

#! /bin/bash

logger () {

    for Q in {0..1}{A..C}{A..F}; do
        printf '%s\n' "${Q}"
        sleep 1
    done
}
    
AWK='
/C/ { printf ("awk %d %s\n", NR, $0); }
'

    logger | tee 593580.log | 
        { 
            date
            wdog -d 5 -t 25 awk "${AWK}"
            date
            cat > 593580.add 
            date
        }

테스트 실행:

paul $ ./593580
Thu 18 Jun 15:35:24 BST 2020
wdog       25.000| Thu Jun 18 15:35:49.574 2020
wdog 15:35:24.574| Started awk as 14035
awk 3 0AC
wdog 15:35:29.579| Tick
awk 9 0BC
wdog 15:35:34.583| Tick
awk 13 0CA
awk 14 0CB
awk 15 0CC
wdog 15:35:39.586| Tick
awk 16 0CD
awk 17 0CE
awk 18 0CF
wdog 15:35:44.591| Tick
awk 21 1AC
wdog 15:35:49.579| Tick
wdog 15:35:49.579| Timed out child 14035 with signal 10
wdog 15:35:49.580| Child 14035 terminated with signal 10
Thu 18 Jun 15:35:49 BST 2020
Thu 18 Jun 15:36:00 BST 2020
paul $ 

관련 정보