プログラムが削除されたファイルを書き込むのを防ぐ

プログラムが削除されたファイルを書き込むのを防ぐ

私たちのシステムの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: -

現時点では、ディスク容量の問題はなく、ログが記録されない問題のみがあります。

アップデート1: PIDはを使用して見つけることlsof +L1|grep $pathができ、「hold」ファイルパスにもありますproc/$PID/fd/N。私は意思決定者に混乱init 6kill 1 $PID。私はこの問題を他の場所で再現しようとし、ここに私が掘り下げたいくつかの提案を提示します。

答え1

そのプログラムを変更または再起動する必要があります。

何が起こっているのかは、プログラムがログに書き込むためにファイルハンドルを開き、その間に同じファイルハンドルを開いたままにすることです。説明したようにファイルが削除されると、そのファイルは「一時停止」され、ファイルハンドルが閉じられるまで実際に記録され続けます。

プログラムを(医師コード)に変更できる場合:

LogFileHandle = OpenFileHandle( Logfile, 'wa' )
UpdateLog( log_entry ) {
    LogFileHandle.Write( log_entry )
}
do_literally_everything_forever()
LogFileHandle.Close()

(医師コード):

UpdateLog( log_entry ) {
    LogFileHandle = OpenFileHandle( Logfile, 'wa' )
    LogFileHandle.Write( log_entry )
    LogFileHandle.Close()
}
do_literally_everything_forever()

これにより問題が解決します。

そうでない場合は、システム全体を再起動する必要はありません。rm開いたファイルハンドルを持つすべてのプロセスが閉じられると(具体的には、そのファイルハンドルが閉じられると)、編集されたファイルは実際に消えます。

ほとんどのよく書かれたデーモンは、SIGHUPが送信されたときに誤ってファイルハンドルを繰り返します(プログラムのマニュアルを読んでください!)。ただし、単にプログラムを停止(または終了)して再起動すると、開いているすべてのファイルハンドルも解放されます。

答え2

デバッガを使用してプロセスに接続し、ファイル記述子2を別の場所に強制的にリダイレクトできます。

gdb -batch -p PID -ex 'p $f=open("/path/to/log", 01101, 0666), dup2($f, 2), close($f)'

リダイレクトする必要があるプロセスとfd2(stderr)PIDファイルに置き換えます。はい。プロセスのumaskが間違っている場合は、権限をより制限的なものに変更できます。プロセスがバッファリングされている可能性があり、その出力がstderrリダイレクトファイルにすぐに表示されない可能性があります。pid"/path/to/log"01101O_WRONLY|O_CREAT|O_TRUNC0666

これはハッキングです。青少年MMV

答え3

根本的な問題は、削除後にファイルのinodeがログを書き込むソフトウェアで使用するのと同じであることです。ファイルを復元するのは簡単ですが、新しいinodeを含む新しいファイルが作成され、プロセスは引き続き元のファイルに書き込まれます。ロギングプログラムが削除されたファイルを閉じて新しいファイルの使用を開始するようにinodeを交換する方法が見つかりませんでした。そのため、プロセスを終了または再開する必要があります。

一時的な解決策として、現在のコンテキストを/proc/$PID/fd/#元のログの場所にコピーするのが最善の解決策であるようです。 @mosvyが提案した解決策を試した後、別の方法が見つかりました。

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

繰り返される 2 つの参照の 1 つは、次のようになります。Linux.com発生する状況と静的ファイルを復元する方法について説明します。 2番目は、この記事で引用したものです。郵便はがき。

答え4

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

これにより、アプリケーションサービスもリセットされ、上記のファイルにログを記録する必要があると思います。

関連情報