ほとんどの Linux 愛好家は、時間が経つにつれて、苦労して手に入れたトリックでいっぱいのきらめく軍の宝箱を手に入れます。これは、状況によって端末ですばやく考える必要がある場合に非常に役立ちます。私は何年にもわたって、また Linux に非常に精通している人物の肩越しに見守る機会があればいつでも、これらの知識の多くを隠してきました。
今日、あなたはターミナルで私とペアを組んでいます。私たちは、Linux ファイルシステムとシェル ツールとトリックの深さを探っています。
/proc
を持っていくLinux システムで最も便利なディレクトリの 1 つは/proc
です。 proc
のman
ページから:
proc ファイルシステムは、カーネル データ構造へのインターフェイスを提供する疑似ファイルシステムです。
man
ページに「疑似ファイルシステム」と書かれている場合、ディスクの下をのぞくと、 /tmp/launch-codes.txt
のテキストファイルの場合と同様に、ファイルを表すビットが見つかると予想される場合、そこにあることを意味します/proc
には何もありません。それは実行中の Linux システム上に存在し、生きていますが、ディスクを取り出して検査すると、まったく存在しません。 /proc
実行中のカーネルのコントロール パネル!
今自分の/proc
を調べてみると、次のような多くのディレクトリが見つかるかもしれません:
ls /proc
1 10 10021 10059 10144 ...hundreds more files...
これらの数字はそれぞれ、プロセス ID ( PID
) を表します。はい、ブラウザーまたはターミナル プログラムのプロセスを識別するのと同じPID
です。実際、プロセス自体に関する多くの情報を調べることができます。たとえば、Linux システムのプロセス1
は伝統的に最上位のinit
プロセスであり、最近のほとんどのシステムでは systemd ベースであることを思い出すかもしれません。私のシステムでPID 1
を開始したコマンドを見てみましょう。
cat /proc/1/cmdline
/run/current-system/systemd/lib/systemd/systemd
cmdline
は、プロセス1
を開始したコマンド (この場合はsystemd
自体) を示すファイルです。
/proc
には特に便利なcmdline
ファイルがあります - /proc/cmdline
は、起動時にカーネル自体に渡される引数を実際に示します。私は非常に冗長ですが、私のシステムが起動したinitrd
と、他のフラグ (私の場合はinit
とloglevel
) を教えてくれます。
cat /proc/cmdline
initrd=\efi\nixos\hx5g5rmvq748m64r32yjmpjk3pmgqmr1-initrd-linux-5.17.11-initrd.efi init=/nix/store/9zvklk45yx41pak2hdxsxmmnq12n712k-nixos-system-diesel-22.05.20220604.d9794b0/init loglevel=4
私の NixOS ホスト名はdiesel
です。ラップトップに石油を入れていないことに注意してください。
/proc
は読み取り専用だけではありません。そのマニュアルページにあるように、 /proc
はカーネルへのインターフェースであり、カーネル自体との対話が含まれます。 /proc/sys
ディレクトリにはさまざまなノブやダイヤルがありますが、カーネルの仮想メモリを確認できる/proc/sys/vm
を紹介したいと思います。もっと冒険したいですか?
私のマシンの現在のメモリ使用量を考慮してください。
free -h
total used free shared buff/cache available Mem: 31Gi 22Gi 3.0Gi 4.4Gi 5.6Gi 3.6Gi Swap: 31Gi 130Mi 31Gi
ここではそれほど珍しいことはありませんが、メモリを積極的に解放したい場合はどうすればよいでしょうか?ほとんどの場合、キャッシュにメモリを使用することに関しては、カーネルが最もよく知っていますが、クリアしても安全なメモリをクリアしたい状況がいくつかあります。実行中のプロセスを壊したくはありません。可能であれば、メモリを再利用します。
そのためのファイルがあることがわかりました。通常、 /proc/sys/vm
は書き込み保護されており、必要なファイルに書き込むことができるのはroot
のみであるため、 echo
コマンドをsudo tee
にパイプします。
echo 1 | sudo tee -a /proc/sys/vm/drop_caches
このコマンドが行うことは、実質的に、「システムで実行中のプロセスを中断せずに失われてもよいメモリ内のキャッシュを削除してください」ということをカーネルに通知することです。私のマシンでは、これにより約 500M のメモリが開きます。
total used free shared buff/cache available Mem: 31Gi 22Gi 3.5Gi 4.4Gi 5.1Gi 3.6Gi Swap: 31Gi 130Mi 31Gi
涼しい! /proc
には、このような興味深いことを実行できるあらゆる種類の便利なファイルのようなオブジェクトがあります。詳細を知りたい場合は、お気軽にman proc
を開いてください。
curl
としての/dev
/dev/sda
のようなキャラクター デバイスは接続されたディスクを表しますが、 /dev
パスには別の用途があります。ネットワーク リクエストを送信するあまり知られていない方法です。
パス/dev/tcp
は、実際には Linux カーネルによって公開されるファイルのようなデバイスではありませんが、実際にはbash
などの選択したシェルの機能です。シェルは、ポート80
でリッスンしている Web サーバーなどのリモート エンドポイントへの低レベルのソケット接続を開くために、このパス上の操作をインターセプトできます。
まず、目的のエンドポイントとポートを示す/dev/tcp
のファイル パスに接続された新しいファイル記述子を開きます。ファイル記述子番号 0、1、および 2 がそれぞれstdin
、 stdout
、およびstderr
を表すのと同じように、この新しいファイル記述子 3 は、リモート ネットワーク エンドポイントへのパイプを表すと考えることができます。ここからはbash
の使用を前提とします。
exec 3<>/dev/tcp/httpbin.org/80
次に、単純な HTTP 要求の平文形式をオープン ファイル記述子に送信します。 /status/200
へのこのGET
リクエストでは、ほとんどのリバース プロキシで適切に処理するために、 Host
ヘッダーを設定する必要もあります。 2 つの改行は、リクエストの終了を示します。
echo -e "GET /status/200 HTTP/1.1\r\nHost: httpbin.org\r\n\r\n" >&3
最後に、単純な読み取り操作で HTTP 応答を取得します。
cat <&3
次のような応答が表示されます。
HTTP/1.1 200 OK Date: Fri, 10 Jun 2022 21:39:43 GMT Content-Type: text/html; charset=utf-8 Content-Length: 0 Connection: keep-alive Server: gunicorn/19.9.0 Access-Control-Allow-Origin: * Access-Control-Allow-Credentials: true
おめでとう!シェルだけを使用して HTTP リクエストを送信しました。
/sys
で泳ぐ/proc
と/dev
に飛び込んだ後、探索すべきルートレベルのディレクトリがもう 1 つあります。謎めいた/sys
ディレクトリです。
/proc
や/dev
と同様に、 /sys
は、オペレーティング システムに非常に近い低レベル メカニズムへの別のファイルのようなインターフェイスです。比較的プロセス中心の/proc
や、ブロック デバイスなどをモデル化する/dev
とは異なり、 /sys
は、カーネルがモデル化する多くの抽象化への便利なインターフェイスです。
たとえば、ディレクトリ/sys/class/net
を取り上げます。このディレクトリ内に、ホストのネットワーク インターフェイスを表すリンクのリストがあります。これが私のものです:
ls /sys/class/net
enp0s20f0u6u4u1 lo tailscale0 wlan0
ご覧のとおり、システムが管理しているアクティブなネットワーク接続には、有線インターフェイス ( en
で始まるインターフェイス)、 lo
ループバック インターフェイス、 Tailscaleインターフェイス、ワイヤレス インターフェイスwlan0
が含まれます。これらのディレクトリのいずれかの内容を一覧表示すると、ファイルの長いリストが表示されますが、特に私の有線ネットワーク インターフェイスの 2 つのファイルを詳しく見てみましょう。
cat /sys/class/net/enp0s20f0u6u4u1/statistics/rx_bytes cat /sys/class/net/enp0s20f0u6u4u1/statistics/tx_bytes
11281235262 274308842
これらの各ファイルは、それぞれ受信バイト数と送信バイト数を表します。数秒後に同じコマンドを使用すると、数値がどのように変化するかを確認してください。
cat /sys/class/net/enp0s20f0u6u4u1/statistics/rx_bytes cat /sys/class/net/enp0s20f0u6u4u1/statistics/tx_bytes
11289633209 274760138
もっと大きな数字!どうやら私は自分の帯域幅を最大限に活用しています。これはどのように役立ちますか?
ネットワーク使用状況ウィジェットがどのように作成されるのか疑問に思ったことはありませんか?では、自作してみませんか?
statistics
ディレクトリ内の前述のファイルを使用してネットワーク アクティビティ レートを導き出すこの小さなbash
スクリプトを確認してください。
interval=1 interface=$1 rx_bytes=$(cat /sys/class/net/$interface/statistics/rx_bytes) tx_bytes=$(cat /sys/class/net/$interface/statistics/tx_bytes) rx_bytes_rate=0 tx_bytes_rate=0 function fmt() { numfmt --to=iec-i --suffix=B $1 } while true do echo -en " $(fmt $tx_bytes_rate)/s ⬆ $(fmt $rx_bytes_rate)/s ⬇\t\r" sleep $interval old_rx_bytes=$rx_bytes old_tx_bytes=$tx_bytes rx_bytes=$(cat /sys/class/net/$interface/statistics/rx_bytes) tx_bytes=$(cat /sys/class/net/$interface/statistics/tx_bytes) tx_bytes_rate=$(( ($tx_bytes - $old_tx_bytes) / $interval )) rx_bytes_rate=$(( ($rx_bytes - $old_rx_bytes) / $interval )) done
このスクリプトを$PATH
のどこかに配置し、 chmod +x <script>
で実行可能にして、 script.sh <interface name>
で試すことができます。私のマシンでの出力は次のようになります。
13KiB/s ⬆ 379KiB/s ⬇
それはいいね!これにはいくつかの用途が考えられます。たとえば、コマンド出力をレンダリングできるツールのウィジェットとして、または特定のネットワーク インターフェイスのネットワーク アクティビティをすばやく確認する方法として使用できます。どちらの場合でも、このデータへのファイルベースのインターフェイスにより、データへのアクセスと使用が非常に簡単になります。
これは、最新の Linux システムの機能をさらに詳しく調べる際に利用できる情報の種類を少し掘り下げただけです。 /
内のさまざまなディレクトリの機能と目的を読むために、このような追加のガイドを検索するか、 man hier
のようなエントリのman
ページを読んでソースに直接アクセスできます。
楽しく探検しましょう!