ファイルにリダイレクトした出力を常に提供するスクリプトがあります。私がやろうとしているのは、リダイレクトされたファイルを回転することです。以下は、スクリプトを開始してリダイレクトする場所です。
.
somecode
.
su - username -c "command >> /path/to/directory/output.txt" &
.
.
code continues..
以下は私が作成しようとしている crontab です:
cd /path/to/directory/
timestamp=`date "+%Y%m%d"`
mv ./output.txt ./logs/output.txt_$timestamp
touch output.txt
chmod 757 ./output.txt
gzip ./logs/output.txt_$timestamp
find ./logs/output.txt* -type f -mtime +2 | xargs rm
あるいはこれも役に立たなかった:
timestamp=`date "+%Y%m%d"`
cp ./output.txt ./logs/output.txt_$timestamp
echo "" > ./output.txt
gzip ./logs/output.txt_$timestamp
最初のコードでは元のスクリプトが失敗して動作しなくなり、2 番目のスクリプトでは output.txt ファイルがクリーンアップされません。
スクリプトを実行したままそれを実行する方法はありますか? 注: Unix Solaris を実行しています。
前もって感謝します。
答え1
これは通常、SIGHUPコマンドを再開するハンドラ他のコマンド (通常はlogrotate
) によってファイルが移動された後。 *nix オペレーティング システムでは、書き込み中にファイルを移動できます (ただし、同じファイル システム上にある必要があるという注意点があると思います)。追加の行は、新しい場所のファイルに追加されます。
答え2
実行中のプロセスのリダイレクトされたファイルstdout
やstderr
新しいファイルに変更することはできません(以下の注記を参照)(これが、長時間実行されるプロセスのログファイルとしてリダイレクトされたファイルstdout
やログファイルを使用することがstderr
悪いアイデア。)
プロセスが開始されると、コマンドのリダイレクト要素は、プロセスを開始したシェルによって実行されます。ターゲット ファイルは、必要に応じて適切なモード (追加または上書き) で開かれ、作成され、リダイレクト モードに応じて 0 バイトに切り捨てられる可能性があります。次に、開いているファイル記述子が子プロセスに渡されます。その開いているファイル記述子は、子プロセスが持つリダイレクトされたファイルへの唯一のリンクです (文字通り)。これはファイルへのリンクです。
そして、これは重要なポイントです。ファイルへの直接リンクとして、オープン記述子はファイルのディレクトリ エントリ (「ファイル名」) と同等です。コマンドなどでその名前を変更したり、そのディレクトリ エントリを削除したりしてもrm
、プロセス内のオープン ファイル記述子にはまったく影響しません。
@l0b0 さんの回答は、ログをローテーションする必要があるプロセスは、SIGHUP
そのようなローテーションを行うためにハンドラーを使用する傾向があるという点で正しいですが、リダイレクトされた出力の場合、「ログのローテーション」は実際にはそれほど単純ではありません。新しい出力ファイルの名前は何になりますか? 子プロセスは、その「名前」が何であるかを知らずstdout
、stderr
出力「ファイル」はそもそもファイルではない可能性があります。
ログローテーションスキームは設計プロセスに - たとえば、ログ ファイルのローテーション中にログ エントリが失われないように、ログ記録を統合する必要があります。
(そうかもしれない可能stdout
実行中のプロセスの/ストリームを変更するstderr
- しかし、これは - 繰り返しになりますが -設計プロセスに組み込まれます。これは、...のような既成のバイナリが、bash
送信した場合に自動的に実行されるようなものではありません。SIGHUP
答え3
皆さんの返信に本当に感謝しています。それを実行する方法が見つからなかったので、回避策として、元のスクリプトを停止し、ローテーションを実行して、オフピーク時に再度開始するように crontab を設定しました。