그래서 다음과 같은 백업 스크립트가 있습니다.
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_FILE
스크립트 exit 1
가 종료되었습니다.
우리는 당신의 명령이 무엇을 하는지 모르지만 logging
, 내가 아는 한 그것은 쓰여질 의도가 아니었다 $LOG_FILE
. 만약 그렇다면, 이렇게 쓰는 것은 약간 어리석은 일이다.로그 파일 확인: ${LOG_FILE}거기.
편집하다
이제 함수를 게시했으므로 logging
여기서는 string( )을 사용하는 것을 볼 수 있습니다 <<<
.
에서 bash
here-strings 및 here-documents는 임시 파일을 사용하여 구현됩니다( $TMPDIR
또는 /tmp
if 에서는 정의되지 않음 $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은 해당 내용이 포함된 이메일을 보내려고 시도합니다). 따라서 ENOSPC 오류로 인해 모든 명령이 write(1, ...)
실패 할 수도 write(2, ...)
있으며, 이로 인해 치명적인 오류라고 판단되면 오작동하거나 조기 종료될 수 있습니다.
답변2
문제는 가능성이 가장 높습니다.
PACKING_EXITCODE=${PIPESTATUS[0]}
유효한 쉘 코드는 아니지만 bash
특정 코드입니다.
Cron은 /bin/sh
다른 명령을 호출합니다 bash
.
스크립트를 다음으로 시작할 수 있습니다.
#!/bin/bash
기본 쉘 이 아닌 기본 쉘 에서 특정 코드가 실행 chmod +x scriptname
되도록 스크립트를 실행 가능하게 만듭니다 .bash
bash