cronjobで実行すると、スクリプトは期待どおりに機能しません。

cronjobで実行すると、スクリプトは期待どおりに機能しません。

まず、毎日のバックアップファイルのファイル名の例を次に示します。

website-db-backup06-June-2020.tar.gz

以下のスクリプトは、端末を介して手動で実行すると正しく実行されます。ただし、cronを介してスクリプトが実行されると、次のcronデーモンメッセージが電子メールで受信されます。

tar: website-db-backup*: Cannot stat: No such file or directory
tar: Exiting with failure status due to previous errors

毎週すべての毎日のバックアップを圧縮するスクリプトは次のとおりです。

#!/bin/bash
#
# Weekly compression for database backups
BACKUP_PATH=~/backup/web/database
BACKUP_FILE_DATE=`date '+%d-%B-%Y'`
tar -czf $BACKUP_PATH/website-db-weekly-compress$BACKUP_FILE_DATE.tar.gz \
    -C $BACKUP_PATH/ website-db-backup* && rm $BACKUP_PATH/website-db-backup*

毎日のバックアップにはファイル名があるため、スクリプトで使用するdate必要があります。*これが理由なのでしょうか?

答え1

問題はスクリプトの現在の作業ディレクトリです。website-db-backup*パスがないため、現在のディレクトリで実行されます。スクリプトに以下を追加する必要があります。

SOURCE_DIR_PATH='/path/to/backup_source'
cd "$SOURCE_DIR_PATH" || exit 1

また、以下を実行する前に、一致するファイルがあることを確認する必要がありますtar

shopt -s nullglob
set -- website-db-backup*
test $# -eq 0 && { echo 'ERROR: No matching files; aborting'; exit 1; }

これは問題ではないかもしれませんが、danielleontievがコメントで指摘したように、スクリプトが~他のユーザーによって実行される可能性がある場合、スクリプトで使用するのは危険です。予想されるルートに置き換えることをお勧めします。

答え2

グローバル拡張が失敗すると、failglobコマンド全体が失敗します(何もしません)。シェルのランダム演算子:(コロン)と組み合わせると、globの結果(成功または失敗)をテストするのに最適な方法です。

shopt -s failglob
: website-db-backup*

# The following code is purely indicative
if [ $? -eq 0 ]; then
  echo "Success, website-db-backup* exists"
else
  echo "Failed, nothing matches website-db-backup*"
fi

これより良いホクラキンの答え内部に$1既存の位置パラメータ(など)を破壊しません。しかし、次の関数を使用してこの問題を解決できます。

shopt -s nullglob

argc() {
  return $#
}
argc website-db-backup*

# Now check $? the same way as above
# $1, $2, ... remain untouched

Bash配列も良い選択です。

shopt -s nullglob
FILES=(website-db-backup*)
echo "${#FILES[@]}"  # gives number of matched files

私の考えでは、これが最も簡単でエレガントな解決策です。

関連情報