スクリプトの実行中にリダイレクトパスを変更する

スクリプトの実行中にリダイレクトパスを変更する

ファイルにリダイレクトする場所から常に出力を提供するスクリプトがあります。私がやりたいことは、リダイレクトされたファイルを回転させることです。以下は、スクリプトを起動してリダイレクトする場所です。

.
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

これは通常、以下を追加することによって行われます。ため息をつくコマンドハンドラの再起動別のコマンド(通常logrotate)の後にファイルを移動します。 *nix オペレーティング・システムでは、ファイルの作成中にファイルを移動できます。 (私の考えでは、ファイルはまだ同じファイルシステムに存在する必要があることに注意する必要があります。)追加の行はファイルの新しい場所に追加されます。

答え2

実際に実行されているプロセスのリダイレクトおよびstdout/または新しいファイルを変更することはできません(下記の注を参照)。これは、リダイレクトを使用したり、長期実行プロセスのログファイルとしてstderr使用したりする理由の1つです。stdoutstderr悪いアイデア。 )

プロセスが開始されると、コマンドのリダイレクト要素がプロセスを開始したシェルによって実行されます。必要に応じて、ターゲットファイルは適切なモード(追加または上書き)で開かれて作成され、リダイレクトモードに応じてゼロバイトに切り捨てることができます。その後、開かれたファイル記述子は子プロセスに渡されます。文字通り、開いているファイル記述子は、サブプロセスがリダイレクトされたファイルに対して持っている唯一のリンクです。以下はファイルへのリンクです。

これは重要な点です。ファイルへの直接リンクなので、開かれた記述子はファイルのディレクトリエントリ「ファイル名」と同じです。その名前を変更したり、ディレクトリエントリを削除したりすること(コマンドを使用するなどrm)は、プロセスで開いているファイル記述子にはまったく影響しません。

@l0b0の答えは正しいです。ログを回転させる必要があるプロセスはSIGHUPハンドラを使用してこれらの回転を実行する傾向がありますが、リダイレクトされた出力の場合、「ログの回転」はそれほど単純ではありません。新しい出力ファイルの名前は何ですか?子プロセスは、自分の「名前」が何であるstdoutか何であるかを知りませんstderr。出力「ファイル」はファイルではない場合があります。

ログ循環スキームは次のようにする必要があります。デザイン済みプロセスへ - たとえば、ログファイルの回転中にログエントリが失われないようにログを統合する必要があります。

(わかりました。可能実行中のプロセスのstdout/ストリームを変更しますstderr。しかし、これは必須です。デザイン済みプロセスに入ります。bash送信するとすぐに使えるバイナリではありませんSIGHUP...)

答え3

みんなの回答ありがとうございます。これを行う方法が見つかりませんでした。したがって、回避策として元のスクリプトを停止して回転した後、使用量が少ない時間に再起動するようにcrontabを設定しました。

関連情報