tar가 실패하면 오류를 처리하지 않고 스크립트가 종료됩니다.

tar가 실패하면 오류를 처리하지 않고 스크립트가 종료됩니다.

따라서 다음과 같은 백업 스크립트가 있습니다.

tar -cf "${BACKUP_TAR}" "${LATEST_SUCCESSFUL_BACKUP}" 2>&1 | tee -a "${LOG_FILE}"

  local PACKING_EXITCODE=${PIPESTATUS[0]}
  if [ ${PACKING_EXITCODE} -eq 0 ]; then 
    logging 'Packing successful'
  else
    logging "ERROR: Packing failed! ERROR: ${PACKING_EXITCODE}. Disk space?"
    df -h 2>&1 | tee -a "${LOG_FILE}"
    logging "Check the log file: ${LOG_FILE}"
    set_lockfile 'destroy'
    backup_remove_package
    exit 1
  fi

logging내 로그 파일에 제대로 로그인하는 기능입니다.

logging () {
  local now="$(date)"
  local logfile=$2
  local logfile=${logfile:-$LOG_FILE}
  cat <<< "${now} $@" | tee -a "${logfile}"
}

set_lockfile "destroy"`는 잠금 파일을 제거하는 함수입니다.

set_lockfile () {
  local lockfile_action=$1
  local lockfile=$2
  local lockfile=${lockfile:-$LOCK_FILE}

  if [ "${lockfile_action}" == "create" ]; then
    #...
  elif [ "${lockfile_action}" == "destroy" ]; then
   destroy_lockfile $lockfile
  else
    logging 'ERROR: Wrong argument for locking file: use create or destroy'
    exit 1
  fi
}

destroy_lockfile () {
  local lockfile=$1

  if [ ! -f ${lockfile} ]; then
    logging "WARNING: Lockfile ${lockfile} not found!"
  else
    logging "Removing lockfile ${lockfile}"
    rm -f "${lockfile}"
  fi
}

backup_remove_package생성된 임시 파일을 제거하는 기능입니다.

디스크가 가득 차서 패킹에 실패했습니다. df -h.

흥미로운 점은 백업 로그입니다. 그것은 다음과 같이 말합니다:

tar: /tmp/backup/20180827T223001.tar: Wrote only 4096 of 10240 bytes
tar: Error is not recoverable: exiting now
Filesystem      Size  Used Avail Use% Mounted on
/dev/xvda1      788G  788G     0 100% /
devtmpfs        3.9G   60K  3.9G   1% /dev
tmpfs           3.9G     0  3.9G   0% /dev/shm

즉, tar실패하고 조건을 통과하여 if어떻게든 건너뛰고 logging "ERROR: ..."실행 df -h하고 죽었습니다. 나머지는 생략합니다.

어떻게 든 기능을 건너 뛰고 명령을 실행하는 것처럼 보입니다.

백업은 파일에서 호출됩니다 cron.d. 설정하지 않았 set -e으므로 오류가 발생해도 종료되지 않습니다.

왜 이런 일이 발생하는지 아시나요?

답변1

스크립트가 예상대로 작동하는 것 같습니다. 의 출력 으로 인해 스크립트가 종료되는 것이 분명해 df졌습니다 .$LOG_FILEexit 1

귀하의 명령이 무엇을 하는지는 모르지만 loggingAFAICT는 $LOG_FILE. 그랬다면 글을 쓰는 게 좀 바보같았을 텐데.로그 파일 확인: ${LOG_FILE}거기.

편집하다

이제 함수를 게시했으므로 logging여기 문자열( <<<)을 사용하는 것을 볼 수 있습니다.

에서 bashhere-strings 및 here-documents는 임시 파일을 사용하여 구현됩니다(in $TMPDIR또는 정의되지 않은 /tmp경우 ). $TMPDIR그것이 꽉 찬 파일 시스템이라면 왜 logging아무것도 출력하지 않았는지 설명될 것입니다.

$ sudo mount -o size=1 -t tmpfs empty /mnt/1
$ yes > /mnt/1/fill-up
yes: standard output: No space left on device
$ TMPDIR=/mnt/1 bash -c 'cat <<< test'
bash: cannot create temp file for here-document: No space left on device

대신에:

local now="$(date)"
cat <<< "${now} $@" | tee -a "${logfile}"

그냥 사용:

printf '%(%FT%T%z)T %s\n' -1 "$*"
printf '%(%FT%T%z)T %s\n' -1 "$*" >> "$logfile"

또는:

local msg
printf -v msg '%(%FT%T%z)T %s' -1 "$*"
printf '%s\n' "$msg"
printf '%s\n' "$msg" >> "$logfile"

( $IFS설정되지 않았거나 공백으로 시작한다고 가정)

이렇게 하면 임시 파일이 저장되지만 프로세스를 분기하거나 외부 명령을 실행하는 것도 방지됩니다(일부 병리학적 조건에서는 실패할 수도 있음)(더 유용한 날짜 형식을 제공하므로 자유롭게 조정하세요).

더 일반적으로 말하면, 전체 /tmp 및 /var 파일 시스템을 갖춘 시스템은 손상된 시스템이므로 제대로 작동하지 않을 많은 일이 발생할 수 있습니다.

여기서 로그가 있다는 것은 행운입니다. 파일을 위한 디스크 공간은 블록 단위로 할당됩니다(일반적으로 ext4에서는 4K). 이것이 아마도 `$LOG_FILE에 일부 출력이 있는 이유일 것입니다(파일 시스템이 가득 차기 전에 마지막 블록이 할당되었기 때문에).

cron에 의해 실행되는 스크립트는 임시 파일에 stdout 및 stderr도 포함합니다(그런 다음 cron은 해당 내용이 비어 있지 않은 경우 내용이 포함된 이메일을 보내려고 시도합니다). 따라서 모든 명령이 실패 write(1, ...)하거나 write(2, ...)(ENOSPC 오류로 인해) 치명적인 오류로 간주되면 오작동하거나 조기 종료될 수 있습니다.

답변2

문제가 있을 확률이 높다.

PACKING_EXITCODE=${PIPESTATUS[0]}

유효한 쉘 코드는 아니지만 bash특정한 것입니다.

Cron은 /bin/sh와 다른 명령을 호출합니다 bash.

스크립트를 다음과 같이 시작할 수 있습니다.

#!/bin/bash

특정 코드가 기본 셸이 아니라 실행되는지 chmod +x scriptname확인하기 위해 스크립트를 실행 가능하게 만듭니다 .bashbash

관련 정보