はじめに
FRAME Studio は、イベント写真の書き出しに使う Linux ワークステーションを点検しています。長時間のセッションを観察する前に、CPU の非アイドル時間、すぐには利用できないメモリ、書き出し先ディレクトリを含むファイルシステムの使用率を正しく読み取る必要があります。高い値は解釈すべき兆候であり、作業失敗の証明ではありません。
短い Bash 関数を三つ実装し、実際の Linux コマンドを実行する準備済みのアダプターを使います。Shell for Beginners で扱うような、端末のパスと Bash の変数、関数、条件分岐、ループの基礎を前提とします。コマンド間の接続は準備済みです。その接続を読み、割合の計算ロジックを実装します。この独立した Linux インスタンスには、練習用の小さな実際の ext4 ファイルシステムが二つあります。準備とマウントは学習者の作業ではありません。所要時間は、読解とよくある間違いを含む著者の見積もりです。
CPU の非アイドル時間を測る
このステップでは、動作するリソースのスナップショットを確認し、CPU の変換処理を実装します。
Terminal から始めます。このラボのコマンドはすべてここで実行します。準備済みの作業場所に移動してください。pwd は現在位置を、ls はファイル一覧を表示します。後で相対パスのファイルが見つからなくなったら、インスタンスをリセットせず、この完全な cd コマンドで戻ってください。
コマンドの入力方法
入力前に Terminal 内をクリックします。コマンドブロックの中身だけをコピーし、プロンプト、囲みのバッククォート、予想される出力例は入力しません。各コマンドの後に Enter を押し、プロンプトに戻るまで待ってから続けます。正常終了しても何も表示されない場合があります。ラボ中は同じ Terminal を開いたままにしてください。
cd /home/labex/project/resource-watch
pwd
パスの末尾が /resource-watch になっているはずです。準備済みのデモを Bash で実行します。
bash demo.sh
最初の行は四つのフィールド名です。次の行には UTC タイムスタンプと三つの実測割合が表示されます。値は変動します。demo.sh は提供された動作例であり、あなたの関数を完成させたり、解答を保存したりしません。
UTC timestamp | CPU non-idle % | memory pressure % | target filesystem used %
2026-...Z ... ... ...
CPU の割合は、このインスタンスの仮想 CPU の時間を表します。vmstat はシステムの活動を報告します。vmstat 1 2 の 1 は秒単位の間隔、2 は報告回数です。最初の CPU 報告は起動後の平均で、二つ目は新しい測定区間を対象とします。フィールドを抽出する前に実行してください。
LC_ALL=C vmstat 1 2
LC_ALL=C は、このコマンドに安定した英語の数値形式を適用します。CPU の列から id を探してください。これはアイドル時間です。このコースでは 非アイドル = 100 - アイドル と定義します。I/O 待ちとスチール時間も含むため、自分のプログラムの実行時間だけを表すものでも、障害診断でもありません。
アダプターはパイプラインを使います。| はコマンドの出力を次のコマンドに渡します。tail -n 1 は最後の行を選びます。awk '{print $15}' は空白区切りの 15 番目のフィールド、つまりこの準備済み procps バージョンの id 列を表示します。単一引用符によって $15 はシェルで展開されず、awk に渡されます。抽出した値が整数であることを確認します。
LC_ALL=C vmstat 1 2 | tail -n 1 | awk '{print $15}'
次に、用意された関数を編集します。nano は端末エディターです。ファイルを開き、: という仮置きだけを、関数 cpu_nonidle の中で置き換え、ほかの関数は変更しません。このコロンは何もしない仮置きです。
nano metrics.sh
方向キーでカーソルを移動します。最初の関数でコロンの行だけを削除し、下の字下げされた二行を入力します。関数名、開きと閉じの波括弧、ほかの関数は残します。関数全体の例は目標の形です。元の関数の下にもう一つ貼り付けないでください。字下げは読みやすさのためですが、波括弧と綴りは正確に保つ必要があります。
最初の関数を次のようにします。
cpu_nonidle() {
local idle=$1
echo $((100 - idle))
}
$1 は関数の第 1 引数です。local は変数の範囲をその関数内に限定します。$((...)) は整数演算を行い、echo は結果を出力します。Ctrl+O、Enter、Ctrl+X で保存して終了します。後の編集で構文エラーになった場合は、ファイルを開き直して該当する関数を修正してください。準備済みのサンプラーは変更されていません。

この例では最初の関数だけが完成しています。残り二つのコロンは意図的に残しています。nano 下部のキャレットは Ctrl キーを表します。たとえば ^O は Ctrl を押しながら O を押す意味で、この二文字を入力するのではありません。

Ctrl+O の後、下部でファイル名を確認します。既存の名前を変更せず Enter で確定し、Ctrl+X でシェルのプロンプトに戻ります。違うファイルを開いたら Ctrl+X を押し、保存するか聞かれたときに N と答えてから正しいファイルを開きます。エディターを開いたままシェルコマンドを入力しないでください。
source は現在のシェルに定義を読み込みます。Terminal は Zsh で起動しますが、この練習は Bash を使います。bash -c で引用符内のテストを Bash で実行してください。外側の単一引用符は内側のコマンドをそのまま保持します。
bash -c 'source ./metrics.sh; cpu_nonidle 97'
3
この入力済みのアイドル値は計算のテスト用です。現在の割合がちょうど 3% だという意味ではありません。両端の値も確認します。
bash -c 'source ./metrics.sh; cpu_nonidle 0; cpu_nonidle 100'
100
0
関数は 0 から 100 までのどの整数アイドル値でも動作します。実際のサンプラーが新しく測定した値を渡します。
利用可能メモリと空きメモリを区別する
このステップでは、Linux が新しいアプリケーションに利用可能と見積もるメモリを使って、メモリの逼迫度を計算します。
Terminal の /home/labex/project/resource-watch に留まります。free -k はメモリを KiB、つまり 1024 バイト単位で表示します。解析する前にコマンドを実行します。
LC_ALL=C free -k
Mem: 行を読んでください。free は完全に未使用のメモリです。available は、回収可能なキャッシュの一部も含め、スワップせずに新しいアプリケーションで使える量の推定です。キャッシュすべてが恒久的に使えないと考えないでください。このコースでは floor((total - available) * 100 / total) を逼迫度の割合とします。特定の将来のメモリ確保が成功するかどうかの予測ではありません。
アダプターは同じ行から合計と利用可能量を選びます。awk の /^Mem:/ は Mem: で始まる行に一致し、$2 と $7 は第 2、第 7 フィールドを選びます。
LC_ALL=C free -k | awk '/^Mem:/ {print $2, $7}'
出力は合計、利用可能量の順です。同じ単位なので比率を計算できます。たとえば合計 1000、利用可能 750 なら 25% であり、75% ではありません。
ファイルを開き、memory_pressure の仮置きだけを置き換えます。
nano metrics.sh
memory_pressure() {
local total=$1 available=$2
echo $(((total - available) * 100 / total))
}
Bash の整数除算は小数部分を捨てます。入力は非負で合計は正なので、切り捨てになります。途中で小数部分を失わないよう、除算より先に乗算します。Ctrl+O、Enter、Ctrl+X で保存します。
bash -c 'source ./metrics.sh; memory_pressure 1000 750; memory_pressure 3 2'
25
33
3 単位のうち 1 単位が利用できない場合、結果が 33 なのは意図どおりです。この契約では同じ大きさの整数単位を使い、利用可能量は 0 以上、合計以下とします。不正入力の解析は、この小さな練習の外で扱います。
最初のテストでは利用できない量は 1000 - 750 = 250 なので、250 × 100 ÷ 1000 = 25 です。二つ目では三単位の一つが利用できず、33.333… は整数を返すため 33 になります。第 2 引数は利用可能量であり、計算済みの割合ではありません。前のステップで完成させた CPU 関数を保持してください。
正しいファイルシステムを測定する
このステップでは、ファイルシステム用の関数を完成させ、完全な観測結果を保存します。
Terminal の /home/labex/project/resource-watch に留まります。exports と reference は、それぞれ別の準備済み ext4 ファイルシステムにあります。両方の元データとメモを保持してください。空き容量を観察するだけなので、データを削除したり、マウントを変更したり、ファイルシステムをいっぱいにしたりしません。
df は指定したパスを含むファイルシステムを報告します。-P オプションは、各ファイルシステムを 1 行にする予測可能な形式を提供します。パスを比較します。
df -P exports reference
ディレクトリ内のファイル数ではなく Capacity を読みます。exports の使用率は reference より低いはずです。df / は別のファイルシステムを表すため、選んだ対象の代わりにはなりません。
nano で filesystem_used だけを置き換えます。
nano metrics.sh
filesystem_used() {
df -P "$1" | awk 'NR == 2 {gsub(/%/, "", $5); print $5}'
}
二重引用符はパスを一つの引数として保ちます。NR == 2 はヘッダーの次の行を選びます。gsub は第 5 フィールドから % を取り除いてから表示します。Ctrl+O、Enter、Ctrl+X で保存します。指定したファイルシステムについて同じ整数を返す別の実装も認められます。
bash -c 'source ./metrics.sh; filesystem_used exports; filesystem_used reference'
二つの数値は、それぞれ対応する df の行と一致する必要があります。最後に準備済みプログラムを実行します。
bash snapshot.sh
UTC タイムスタンプ、CPU 非アイドル、メモリ逼迫度、対象ファイルシステム使用率がタブ区切りで表示されます。CPU とメモリはコマンド間でも変化します。アダプターを読み、個別の観測のつながりを確認します。
cat capture.sh
アダプターは vmstat と free を実行し、あなたの関数を呼び出して、df で対象を読みます。$(...) は出力を取得します。read -r は空白区切りの値を変数に割り当て、<<< は取得した文字列をその読み取りに渡します。接続は準備済みで、割合を決めるのはあなたの関数です。
実際のスナップショットを保存します。> は出力をリダイレクトしてこの一つのファイルを置き換えますが、元のオペレーター履歴は変更しません。
拡張子 .tsv はタブ区切り値を意味します。一行に一つの観測を置き、フィールド間をタブで区切ります。スナップショットの四フィールドは UTC タイムスタンプ、CPU 非アイドル率、メモリ逼迫率、対象ファイルシステム使用率の順です。UTC は共通の時刻標準で、末尾の Z は UTC を表します。異なるリソースの割合なので、足し合わせたり合計 100 を期待したりしないでください。
bash snapshot.sh > snapshot.tsv
cat snapshot.tsv
ファイル名や関数名を間違えたら、ls を使い、metrics.sh を開き直し、修正してスナップショットのコマンドを再実行します。失敗した観測を架空の数値で埋めないでください。計算と対象が明確な Bash サンプラーができました。
まとめ
新しい区間の CPU 非アイドル時間を測り、利用可能メモリから逼迫度を計算し、実際の対象を含むファイルシステムを選びました。三つの Bash 関数で実際のスナップショットを作成できます。次の独立したラボではこれらの関数が提供され、警告ルールと履歴の保持を追加します。



