
ホーム ディレクトリに保存されているスクリプトを crontab 経由で実行しようとしていますが、うまくいきません。実行するたびに、CRON ログに次のように表示されます。
Sep 3 18:30:01 backup CRON[6778]: (root) CMD (/home/hannes/script > /tmp/yc.log)
Sep 3 18:30:01 backup CRON[6777]: (CRON) info (No MTA installed, discarding output)
クローンタブ:
*/1 * * * * /home/hannes/script > /tmp/yc.log
.sh ファイル拡張子を追加しようとしても、何も変わりません。yc.log ファイルは空のままです。
これは私が実行しようとしているスクリプトです (手動で実行すると正常に動作します):
#!/bin/sh
cp -r -p mnt/main-nas/PATH-TO-FILE mnt/backup-nas/01/temp/server
zip -r mnt/backup-nas/01/1.19_Test.`date +%d.%m.%Y_%H.%M.%S`.zip mnt/backup-nas/01/temp/server
rm -r mnt/backup-nas/01/temp/server
どのような助けでも大歓迎です! :)
答え1
あなたのスクリプトは実際には実行中ですが、どこかでエラーが発生しています。また、出力をキャプチャしていないためstderr
、ローカルでスクリプトを実行しているユーザーに stderr が送信されますcron
。(そして、これも失敗します)
根本的な原因は、スクリプトがstdout
ファイルにリダイレクトするだけであることです。しかし、失敗するスクリプトやプログラムの多くは、エラー メッセージを出力するために を使用します。実行するコマンド ラインの末尾に をstderr
追加してこれをキャッチする必要があります。これにより、エラーもキャプチャされ、ファイルに記録されます。2>&1
cron
stderr
以前に捕捉しなかったため、stderr はメール経由で配信されていましたroot
が、ローカル配信用のローカル MTA (メール転送エージェント、別名 Local Mail Transport Protocol (LMTP) サーバー) がないため、cron エラーが発生しました。キャプチャにより、stderr
エラーとスクリプトが適切に実行されなかった理由が表示されます。
ログにエラー出力が記録されたら、スクリプトをさらにデバッグして、問題を「修正」するために何を行う必要があるかを判断できます。
答え2
問題はいくつかありました。まず、ログが実際に保存されるように2>&1
の末尾を追加するのを忘れていました。次に、スクリプトにタイプミスがあり、すべてのパスの最初のスラッシュを忘れていました。これはからになりました。これが同様の問題を抱えている他の人の助けになれば幸いです。回答してくれた皆さんに感謝します :)/home/hannes/script > /tmp/yc.log
home/hannes/...
/home/hannes/...
答え3
承認された回答は正しく、述べられた質問に当てはまります。ただし、質問で提供された情報には、このスクリプトに関係のない潜在的な問題があることが示されており、OP に警告することが重要だと感じています。また、それを適切に説明するにはコメントが長すぎるため、特にその点をカバーする回答を追加します。
ログの問題以外にも、この配置には潜在的に厄介な競合状態があります。スクリプトはアーカイブするファイルをステージングするために常に同じディレクトリを使用するため、スクリプトの複数のインスタンスが同時に実行されると、最初のインスタンスの実行によって、後続のインスタンスが現在処理しているファイルが削除される可能性が高く、追加の障害が発生し、アーカイブが不完全になる可能性が高くなります (ファイルがzip
処理される前に消えてしまうため)。
これは、スクリプト自体が呼び出しごとのディレクトリを使用するか、ファイル ロックを使用して同時実行を防ぐという 2 つの方法のいずれかで解決できます。
最初のアプローチははるかに簡単で、使用しているディレクトリに日付を追加するだけです。次のようになります (これにより、がdate
1 回だけ呼び出されることも保証されます)。
#!/bin/sh
now="$(date +%d.%m.%Y_%H.%M.%S)"
cp -r -p mnt/main-nas/PATH-TO-FILE mnt/backup-nas/01/temp/server/${now}
zip -r mnt/backup-nas/01/1.19_Test.${now}.zip mnt/backup-nas/01/temp/server/${now}
rm -r mnt/backup-nas/01/temp/server/${now}
ファイル ロックのアプローチは、少し複雑ですが、複数のzip
コマンドを同時に実行して誤ってシステムを圧倒することもないため、よりクリーンであると言えます。これには、 というコマンドflock
(Ubuntu および Debian のパッケージの一部でutil-linux
、すでにインストールされています) を使用する必要があり、次のようになります (何が起こっているかを説明するコメント付き)。
#!/bin/sh
# All of this gets run in a subshell so we can hold a file descriptor open
# for all the commands. We're using file descriptor 9 here, but any number
# higher than 2 will work.
(
# This flock command is what actually takes the lock. The lock itself
# persists until the file descriptor is closed when the subshell exits.
# The -x means it's an exclusive lock (so only one instance can hold it).
# The -w says to try for that many seconds before failing if something
# else is holding the lock (this is an important safety net to ensure you
# don’t get a long queue of these scripts waiting to run).
# The -n indicates which file descriptor to take the lock on.
flock -x -w 30 -n 9 || exit 1
cp -r -p mnt/main-nas/PATH-TO-FILE mnt/backup-nas/01/temp/server
zip -r mnt/backup-nas/01/1.19_Test.`date +%d.%m.%Y_%H.%M.%S`.zip mnt/backup-nas/01/temp/server
rm -r mnt/backup-nas/01/temp/server
# And this line closes the subshell, and also sets the path to be used for
# the lock file by opening it as file descriptor 9 for the subshell. /run
# is generally the place you want to put stuff like this, because it will
# get cleaned up automatically every time the system reboots.
) 9> /run/backup-nas.lock