そのため、次のバックアップスクリプトがあります。
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