web-dev-qa-db-ja.com

なぜあなたは `cat / dev / null> / var / log / messages`になるのでしょうか?

この bashスクリプトの例のページ に、作者は次のスクリプトを提示します。

# Cleanup
# Run as root, of course.

cd /var/log
cat /dev/null > messages
cat /dev/null > wtmp
echo "Log files cleaned up."

なぜあなたは何かにcat /dev/nullをつけますか?ここで何が意図されているのか理解できません(while TRUE; sleep 1; elihw{some busy program}を使用するようなものですか?)。それでも作者はそれを「異常なことは何もない」と呼んでいます。

77
isomorphismes

実際のファイル状態が中断される危険性が絶対にゼロであることを確認しながら、ファイルの内容を消去したい場合は、通常cat /dev/null > [something]です。ファイルの内容は、cat /dev/nullによって明確に消去されますが、ファイル自体は存在し、存在するファイルシステムに認識されているため、同じiノード番号、所有権、およびアクセス権で引き続き存在します。

ログファイルの場合、ログファイル自体が別のプロセスによって「使用中」とマークされている可能性があります。そのため、たとえばrm /var/log/messages && touch /var/log/messagesを実行すると、他のプロセスに支障をきたすことになり、実行中のプロセスが詰まることがあります。ファイル/var/log/messagesに接続されている特定のiノード番号に何らかの理由でロックされているプロセスが突然パニックになり、「Hey!ファイルがまだ存在していても、/var/log/messages!はどうなりましたか。所有権や許可が誤って再作成された場合の潜在的な問題は言うまでもありません。

ファイルの使用法/状態の不確実性のため、ログを消去したいが潜在的にを使用したくないシステム管理者はcat /dev/null > [something]の使用を推奨します。既存のプロセスの操作.

また、 にリンクしているページの文脈で 作者は次のように述べています。

ここでは珍しいことは何もありません。コンソールまたはターミナルウィンドウのコマンドラインから1つずつ簡単に呼び出すことができる一連のコマンドだけです。スクリプト内にコマンドを配置することの利点は、何度もコマンドを再入力する必要がないことをはるかに超えています。

そのため、作者が言及する「珍しいことではない」のは、その特定のbashスクリプトが何であるかという全体的な概念に関するものです。何度も入力し直す必要はありません。

41
JakeGould

なぜあなたは/ dev/nullをなにかに当てにしますか?

Inodeを損なわずにファイルの内容を切り捨てるためにそれを行います。そのファイルを読み取りまたは書き込み用に開いているすべてのプログラムは、ファイルサイズがゼロにリセットされるという事実以外には影響を受けません。

よくある偽の代替策は、ファイルを削除してから再度作成することです。

rm file
touch file

または同様のもの:

mv file file.old
gzip file.old
touch file

問題は、これらの方法では、削除時に削除されたファイルを開いているプロセスが古いファイルに書き込みを続けることを妨げないことです。 Unixファイルシステムでファイルを削除すると、その名前(パス)とその内容(iノード)のリンクが解除されるだけです。読み取りまたは書き込み用にオープンしているプロセスがある限り、iノードは存続します。

これはいくつかの悪影響をもたらします。削除されたファイルを開くための直接的で移植可能な方法がないため、ファイルの削除後に書き込まれたログが失われます。プロセスが削除されたファイルに書き込んでいる限り、その内容はまだファイルシステム上のスペースを使用しています。つまり、ディスクがいっぱいになったためにファイルを削除または作成しても、ディスクはいっぱいになります。後者の問題を解決する1つの方法はロガープロセスを再起動することですが重要なサービスのためにそれをしたくないかもしれないし中間ログは最終的に失われるでしょう。あなたが作成したファイルがオリジナルのものと同じ許可、所有者、およびグループを持っていないかもしれないという事実による副作用もあります。これは、たとえばログアナライザが新しく作成されたファイルを読み取れないようにしたり、さらに悪いことに、ロギングプロセスが独自のログを書き込むのを妨げる可能性があります。

最初の方法、cat /dev/null > fileは目的を適切に達成します しかし、粘り強い都市伝説にもかかわらず、そのcat /dev/null部分はまったく役に立ちません。 意図的に空の疑似ファイルを開き、そこから何も読み取れず、最後に終了するだけです。このコマンドを使用すると、キーストローク、バイト数、システムコール、およびCPUサイクルが無駄になります。機能を変更することなく、間違いなく高速のno-opコマンド:、またはほとんどのシェルではまったくコマンドを使用できません。

cat /dev/nullが無駄であることを説明するために比喩を試してみましょう。あなたの目標はガラスを空にすることだとしましょう。

  • まずそこから液体を取り除きます。これで十分で、リダイレクトが常に最初に処理されるという事実を考えれば、正確に(> file)が行うことです。

  • 次に、空のボトル(/dev/null)を選び、空のグラス(cat)に入れます。これは無意味なステップです...

あなたのリンクされた文書 を最後まで読んだなら、スクリプトの拡張版からこの行のコメントに気づくでしょう:

 cat/dev/null> wtmp# ':> wtmp'と '> wtmp'は同じ効果があります。

彼らは確かに持っています。あまりにも悪いcat /dev/nullがコードに残っていました。

つまり、次のコードはすべての一般的なシェル(cshファミリーとshファミリーの両方)で機能します。

cd /var/log
: > messages
: > wtmp
echo "Log files cleaned up."

これは、ashbashkshzshなどのBourne構文を使用するすべてのシェルで機能します。

cd /var/log
> messages
> wtmp
echo "Log files cleaned up."

ただし、古代のPOSIX Bourneシェルより前のバージョンでは、cat /dev/nullを含むこれらのコマンドは、ファイルに追加されたまま実行中のシェルスクリプトによって後で書き込まれても、ファイルを切り捨てません。ゼロバイトファイルの代わりに、サイズが変更されていないスパースファイルになります。ファイルが、書き込み前の現在のファイルであると思われる位置にシークするプロセスによって書き込まれた場合も、同じことが起こります。

ファイルを切り捨てるために提案されることが多いいくつかの代替解決策には欠陥があることにも注意してください。

  • 次の2つは、仕事をしないだけです。結果のファイルは空ではありませんが、空の行が含まれています。これは固定幅レコードを格納するwtmpのようなログファイルを壊すでしょう。

    echo > file
    echo "" > file
    
  • BSDのshオプションに基づく次のオプションは移植性がありません。POSIXはechoに許可されたオプションを指定しないので、 "-n"の行を含むファイルになってしまうかもしれません:

    echo -n > file
    
  • System Vのshエスケープシーケンスを使っても移植性がありません。いくつかのシェルは "\c"を含む行を含むファイルを作成します。

    echo "\c" > file
    
  • それは仕事をするように設計されたコマンドを使います。このコマンドはPOSIXでは指定されていないため、Unix/Linuxシステムにはない可能性があるため、truncateの使用は移植性がありません。

    truncate -s 0
    

最後に、移植性があり、適切に仕事をするいくつかの選択肢があります。

  • 空の文字列を明示的にファイルに出力します。

    printf "" > file
    
  • もっと読みやすいにもかかわらず、何もしない:と厳密に同等のtrueコマンドを使用します。

    true > file
    
121
jlliagre

ファイルをゼロサイズにするのは面倒な方法です。

cd /var/log
> messages
> wtmp
echo "Log files cleaned up."
6
Cyrus