paint-brush
シェルの下で 20,000 マイル@tylerjl
1,651 測定値
1,651 測定値

シェルの下で 20,000 マイル

Tyler2022/06/13
Read on Terminal Reader
Read this story w/o Javascript

長すぎる; 読むには

今日、あなたはターミナルで私とペアを組んでいます。私たちは、Linux ファイルシステムとシェル ツールとトリックの深さを探っています。

Coin Mentioned

Mention Thumbnail
featured image - シェルの下で 20,000 マイル
Tyler HackerNoon profile picture

ほとんどの Linux 愛好家は、時間が経つにつれて、苦労して手に入れたトリックでいっぱいのきらめく軍の宝箱を手に入れます。これは、状況によって端末ですばやく考える必要がある場合に非常に役立ちます。私は何年にもわたって、また Linux に非常に精通している人物の肩越しに見守る機会があればいつでも、これらの知識の多くを隠してきました。


今日、あなたはターミナルで私とペアを組んでいます。私たちは、Linux ファイルシステムとシェル ツールとトリックの深さを探っています。

/procを持っていく

Linux システムで最も便利なディレクトリの 1 つは/procです。 procmanページから:


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と、他のフラグ (私の場合はinitloglevel ) を教えてくれます。


 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 がそれぞれstdinstdout 、および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ページを読んでソースに直接アクセスできます。


楽しく探検しましょう!