システムの1つにログファイルが増えています(アドレス指定します)が、現在、アプリケーションの所有者はrm
を使用してファイルを削除し、次のメンテナンスウィンドウが再起動するのを待ちます。次のメンテナンスウィンドウと100%使用率のディスクまで数週間かかります。
この投稿 からのガイダンスに従って、ファイルを見つけて切り捨てました。現在の問題は、プログラム/プロセスがどこにもログに書き込まれていないように見えることです。このプロセスで古いファイルの使用を停止し、「新しいファイル」の使用を開始するための最良の方法は何ですか?
# find /proc/*/fd -ls | grep '(deleted)'|grep path
112567191 0 l-wx------ 1 user1 group1 64 Feb 20 14:10 /proc/27312/fd/2 -> /path/file.log\ (deleted)
# > "/proc/27312/fd/2"
# find /proc/*/fd -ls | grep '(deleted)'|grep path
112567191 0 l-wx------ 1 user1 group1 64 Feb 20 14:10 /proc/27312/fd/2 -> /path/file.log\ (deleted)
# stat /path/file.log
File: ‘/path/file.log’
Size: 0 Blocks: 0 IO Block: 4096 regular empty file
Device: 811h/2065d Inode: 2890717 Links: 1
Access: (0644/-rw-r--r--) Uid: (54322/loc_psoft) Gid: (54321/oinstall)
Context: unconfined_u:object_r:unlabeled_t:s0
Access: 2019-02-20 12:44:42.738686325 -0500
Modify: 2019-02-08 11:38:19.741494973 -0500
Change: 2019-02-08 11:38:19.741494973 -0500
Birth: -
# stat /proc/27312/fd/2
File: ‘/proc/27312/fd/2’ -> ‘/path/file.log (deleted)’
Size: 64 Blocks: 0 IO Block: 1024 symbolic link
Device: 3h/3d Inode: 112567191 Links: 1
Access: (0300/l-wx------) Uid: (54322/loc_psoft) Gid: (54321/oinstall)
Context: unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023
Access: 2019-02-20 14:10:45.155518866 -0500
Modify: 2019-02-20 14:10:45.154518886 -0500
Change: 2019-02-20 14:10:45.154518886 -0500
Birth: -
現時点では、ディスク容量の問題はありません。ログが書き込まれないという問題だけがあります。
UPDATE 1:PIDはlsof +L1|grep $path
を使用して見つけることができ、「保持された」ファイルパスにもproc/$PID/fd/N
にあります。 。 init 6
またはkill 1 $PID
として、決定者に中断を販売することはまだできていません。私は他の場所で問題を再現してみて、ここでいくつかの推測を与えるつもりです、そして私は掘り下げました。
問題のプログラムを変更するか、単に再起動する必要があります。
起こっているように見えるのは、プログラムがログに書き込むためにファイルハンドルを開いており、その間、同じファイルハンドルを開いたままにしていることです。あなたが説明するように、ファイルが削除された場合、それは一時停止で「保持」され、実際にはファイルハンドルが閉じられるまで書き込まれます。
プログラムを変更して(擬似コード)から変更できる場合:
LogFileHandle = OpenFileHandle( Logfile, 'wa' )
UpdateLog( log_entry ) {
LogFileHandle.Write( log_entry )
}
do_literally_everything_forever()
LogFileHandle.Close()
to(擬似コード):
UpdateLog( log_entry ) {
LogFileHandle = OpenFileHandle( Logfile, 'wa' )
LogFileHandle.Write( log_entry )
LogFileHandle.Close()
}
do_literally_everything_forever()
それで問題は解決します。
それができない場合は、システム全体を再起動するのではなく、ファイルハンドルを開いたままにしているすべてのプロセスを閉じると、rm
されたファイルは正常に機能しなくなります(具体的には、ファイルハンドルが閉じられました)。
よく書かれたデーモンのほとんどは、SIGHUPが送信されると、偶然にファイルハンドルを循環させます(プログラムのドキュメントを読んでください!)。ただし、プログラムを停止(または終了)して再起動するだけでも、開いているファイルハンドルが解放されます。
デバッガーを使用してそのプロセスにアタッチし、ファイル記述子2を別の場所に強制的にリダイレクトすることができます。
gdb -batch -p PID -ex 'p $f=open("/path/to/log", 01101, 0666), dup2($f, 2), close($f)'
PID
をプロセスのpid
に置き換え、"/path/to/log"
をfd2(stderr)がリダイレクトされるファイルに置き換えます。 01101
はO_WRONLY|O_CREAT|O_TRUNC
です。プロセスのumaskが正しくない場合は、0666
パーマをより制限的なものに変更できます。プロセスがバッファリングしている可能性があり、その出力がstderrがリダイレクトされたファイルにすぐに表示されない場合があります。
これはハックです。 [〜#〜] ymmv [〜#〜]。
根本的な問題は、ファイルのiノードが削除された後も同じであり、ログを書き込んでいるソフトウェアによって使用されていることにあるようです。ファイルを復元するのは簡単ですが、これにより、新しいiノードを含む新しいファイルが生成され、プロセスは元のファイルへの書き込みを続行します。ロギングプログラムが削除されたファイルをオフにして新しいファイルの使用を開始するように、iノードを交換する方法をまだ見つけていません。これが、プロセスの強制終了または再起動が必要な理由です。
一時的な解決策として、/proc/$PID/fd/#
の現在のコンテキストを元のログの場所にコピーすることが最善の解決策のようです。 @mosvyによって提案されたソリューションを使用しようとした後、別の方法を見つけました
# Nohup tail -c +0 -f /proc/$PID/fd/# > /path/file.log &
たくさん出てきた2つの参照は Linux.com からのもので、何が起こったのか、そして静的ファイルを回復する方法をカバーしていました。 2番目はこの スーパーユーザー 投稿で参照されました。
システムの変更がオプションである場合は、システムにファイルへの新しい参照を取得させるシグナルハンドラーを追加できます。これにより、次のようなことができます。
hup=1
pid=$(get-the-pid-somehow)
kill -n $hup $pid
アプリケーションサービスを再起動することはできますか?はいの場合、再起動してみましたか。これにより、古いPIDが解放され、新しいPIDが作成されます。
これにより、アプリケーションサービスもリセットされ、上記のファイルにログが書き込まれるはずです。