私はUnixにかなり慣れていません。 Solaris 10を使用して、次の問題に直面しました。
サイズが9.5Gの大きなログファイルがあります。以下のコマンドでファイルを空にしてみました。
# cat /dev/null file_log.txt
これを行うことで、ファイルシステムのスペースを取り戻しましたが、ファイルのサイズは同じで、増加しています。プロセスがまだログファイルに実行されていると思いました。
ファイルサイズを修正する方法はありますか?これはファイルシステムに影響しますか?
あなたが言うつもりだったと仮定して
_cat /dev/null > file_log.txt
_
または
_cp /dev/null file_log.txt
_
これは同じことですが、答えは、ファイルを書き込み用にオープンしているプロセスが_O_APPEND
_なしでオープンしたか、またはファイルにオフセットを任意に設定することです。その場合はsparseファイルが作成されます。
write(2)
のマニュアルページには、かなり明確な説明があります:
シーク可能なファイル(つまり、lseek(2)が適用される可能性があるファイル、たとえば通常のファイル)の場合、書き込みはファイルオフセットで行われ、ファイルオフセットは実際に書き込まれたバイト数だけインクリメントされます。ファイルがO_APPENDでオープン(2)された場合、ファイルオフセットは、書き込み前に最初にファイルの終わりに設定されます。ファイルオフセットの調整と書き込み操作は、アトミックステップとして実行されます。
上記のオフセットはプロパティです対応するファイル記述子の書き込みプロセスのプロパティです。別のプロセスがファイルを切り捨てるか、ファイルに自分自身を書き込んだ場合、これはオフセットに影響を与えません。 (さらに、同じプロセスが_O_APPEND
_なしで書き込み用にファイルを開く場合、そのために別のファイル記述子を受け取り、新しいファイル記述子を介してファイルに書き込むと同じ効果があります。 )
プロセス[〜#〜] p [〜#〜]がファイルを追加せずに書き込み用に開き、ファイル記述子fdを生成するとします。次に、(_/dev/null
_をファイルにコピーするなどして)ファイルを切り捨てることによる(stat()
の報告による)ファイルサイズへの影響は、[〜#〜]とすぐに元に戻されますp [〜#〜]fdに書き込みます。具体的には、write()
からfdに移動すると、システムはfdに関連付けられたオフセットに移動し(「シーク」)、現在の末尾からスペースを埋めますファイル(完全に切り捨てられている場合は、先頭まで)からゼロまでのオフセットまで。ただし、ファイルのサイズが大きいに増加した場合、fdに書き込むと、オフセットからファイルの内容が上書きされます。
スパースファイルとは、「穴」を含むファイルです。つまり、システムは、実際にはディスクに書き込まれていないゼロの大きな領域があることを「認識」しています。これがdu
とls
が同意しない理由です-du
は実際のディスク使用量を調べ、ls
は単にstat()
を使用してファイルサイズ属性。
対処法:プロセスを再起動します。可能であれば、ファイルが開かれている部分を書き直して、_O_APPEND
_(またはfopen()
を使用する場合はモードa
)を使用します。
cat /dev/null
は何も出力しないため、no opです。 cp /dev/null file
も同様に無意味です。
ファイルのコンテンツを空白にするより簡単な方法は、nullコマンドをその方法でファイルにリダイレクトすることです。
: > file
または、ほとんどのシェルでは、コマンドを指定せずにリダイレクトのみを使用します。
> file
ls
によって報告されたサイズが依然として大きいという事実は、書き込みプロセスが、ファイルの終わりを書き込む前にどうあるべきかという予想されたアイデアを求めているためです。シークポイントの前には「何もない」ので、これは害になりません。唯一のリスクは、非スパースファイル対応ツールを使用して、影響を受けるファイルのバックアップまたはコピーを実行することです。
書き込みプロセスを再起動しても、ファイルが「完全」のままであるため、スペースが「回復」されないことに注意してください。
報告されたファイルサイズをゼロにしたい場合は、ファイルをブランクにする前に書き込みプロセスを停止(kill)する必要があります。
cat/dev/null file_log.txt
これは猫だけを読んだ/dev/null
とすぐに読むfile_log.txt
を実行し、結果を画面のstdout
に出力します。これは何も削除しません。
テストしたい場合は、cat /dev/null non_existent_file
すると、エラーが発生することがわかります。
ファイルを切り捨てる正しい方法は、シェルリダイレクターまたは任意の種類のエディターを使用して行を削除することです。あなたがやろうとしていたことは:
cat /dev/null > file_log.txt
最初の方法を説明します。