web-dev-qa-db-ja.com

プログラムが削除されたファイルに書き込むのを停止します

システムの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として、決定者に中断を販売することはまだできていません。私は他の場所で問題を再現してみて、ここでいくつかの推測を与えるつもりです、そして私は掘り下げました。

1
RunThor

問題のプログラムを変更するか、単に再起動する必要があります。

起こっているように見えるのは、プログラムがログに書き込むためにファイルハンドルを開いており、その間、同じファイルハンドルを開いたままにしていることです。あなたが説明するように、ファイルが削除された場合、それは一時停止で「保持」され、実際にはファイルハンドルが閉じられるまで書き込まれます。

プログラムを変更して(擬似コード)から変更できる場合:

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
DopeGhoti

デバッガーを使用してそのプロセスにアタッチし、ファイル記述子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)がリダイレクトされるファイルに置き換えます。 01101O_WRONLY|O_CREAT|O_TRUNCです。プロセスのumaskが正しくない場合は、0666パーマをより制限的なものに変更できます。プロセスがバッファリングしている可能性があり、その出力がstderrがリダイレクトされたファイルにすぐに表示されない場合があります。

これはハックです。 [〜#〜] ymmv [〜#〜]

2
mosvy

根本的な問題は、ファイルのiノードが削除された後も同じであり、ログを書き込んでいるソフトウェアによって使用されていることにあるようです。ファイルを復元するのは簡単ですが、これにより、新しいiノードを含む新しいファイルが生成され、プロセスは元のファイルへの書き込みを続行します。ロギングプログラムが削除されたファイルをオフにして新しいファイルの使用を開始するように、iノードを交換する方法をまだ見つけていません。これが、プロセスの強制終了または再起動が必要な理由です。

一時的な解決策として、/proc/$PID/fd/#の現在のコンテキストを元のログの場所にコピーすることが最善の解決策のようです。 @mosvyによって提案されたソリューションを使用しようとした後、別の方法を見つけました

# Nohup tail -c +0 -f /proc/$PID/fd/# > /path/file.log &

たくさん出てきた2つの参照は Linux.com からのもので、何が起こったのか、そして静的ファイルを回復する方法をカバーしていました。 2番目はこの スーパーユーザー 投稿で参照されました。

1
RunThor

システムの変更がオプションである場合は、システムにファイルへの新しい参照を取得させるシグナルハンドラーを追加できます。これにより、次のようなことができます。

hup=1
pid=$(get-the-pid-somehow)
kill -n $hup $pid
0
ant

アプリケーションサービスを再起動することはできますか?はいの場合、再起動してみましたか。これにより、古いPIDが解放され、新しいPIDが作成されます。

これにより、アプリケーションサービスもリセットされ、上記のファイルにログが書き込まれるはずです。

0
Atul