はじめに
「Linuxコマンドは、解説記事を読んだだけでは絶対に身につかない」
インフラ運用の実務(オンプレ運用・仮想化基盤・監視・障害対応)を長くやってきて、これは強く実感していることです。実際に手を動かしてコマンドを打ち、エラーを出し、直す。このプロセスを踏まないと定着しません。
そこで、ブラウザだけで実機さながらのコマンド練習ができる疑似ターミナル環境を個人開発しました。
- 31言語・カテゴリ / 3,000本超のレッスン
- 理解度チェック問題 9,000問超
- 完全無料・登録不要
- Python/JavaScript/HTML・CSS/SQLはブラウザで実際にコードが動く
- Git/Linux/Docker/AWS CLI/Terraform/Cisco/Claude Codeは疑似ターミナルで実際にコマンドを打てる
本記事では「サーバーを立てずに、どうやってコマンド入力型の学習環境を作ったか」という技術的な部分を中心に紹介します。
疑似ターミナルに必要だった要件
実際のLinuxサーバーやDockerコンテナをユーザーごとに用意する方法(いわゆるクラウドIDE型)も検討しましたが、以下の理由で見送りました。
- ユーザー数が増えるとサーバーコストが跳ね上がる
- 起動待ち時間が発生し、学習体験としてテンポが悪い
- セキュリティ面(任意のコマンド実行を許可するリスク)の担保が難しい
そこで採用したのが、**「本物のシェルは動かさず、コマンド文字列を解析して"それらしい"出力を返すシミュレーター」**という方式です。
アーキテクチャの基本方針
ユーザー入力(コマンド文字列)
↓
パーサー(コマンド名・オプション・引数に分解)
↓
仮想ファイルシステム/仮想状態と照合
↓
擬似的な標準出力を生成
↓
画面に表示 + 正誤判定
実際のOSは一切動かさず、フロントエンドのJavaScriptだけで完結する設計にしています。これによりサーバーコストがほぼゼロで、同時アクセスが増えても問題なく捌けます。
1. コマンドのパース
例えば以下のようなコマンドが入力されたとします。
$ grep -i error access.log
これを
{
command: "grep",
options: ["-i"],
args: ["error", "access.log"]
}
のような構造に分解します。オプションの結合表記(-la のような複数オプションの合体)や、パイプ(|)、リダイレクト(>)にも対応させる必要があり、ここが最初の山場でした。特にパイプで複数コマンドを繋ぐケース(cat access.log | grep error | wc -l)は、各コマンドの出力を次のコマンドの入力として順番に処理するチェーン構造にする必要があります。
2. 仮想ファイルシステムの用意
ls や cd 、cat などのコマンドを成立させるには、そのレッスンごとに「仮想的なディレクトリ構造とファイルの中身」をあらかじめ定義しておく必要があります。
const virtualFS = {
"/home/user": {
type: "dir",
children: {
"access.log": {
type: "file",
content: "192.168.1.1 - - [error] Failed login\n192.168.1.2 - - [info] OK\n"
},
"logs": { type: "dir", children: { /* ... */ } }
}
}
};
レッスンごとにこの仮想ファイルシステムのJSONを用意し、grepやcatはこの中身を読みに行く形にしています。cdやpwdは現在地を表す状態変数を持たせて、コマンドの実行結果によって更新する形にしました。
3. 正誤判定のロジック
単純な文字列の完全一致だけだと、以下のようなケースで正しく判定できません。
# どちらも正解にしたい
$ grep error access.log
$ grep "error" access.log
そのため、パース結果(コマンド名・オプション・対象ファイル)を構造化した状態で比較し、**「意味的に同じコマンドかどうか」**で正誤判定するようにしています。オプションの順序違い(-la と -al)も同一視するなど、細かい表記ゆれを吸収するのがポイントでした。
4. Git/Docker/Terraformなど、状態を持つコマンドへの対応
Linuxコマンドは比較的ステートレスですが、Gitは「コミット履歴」「ブランチの状態」「ステージング状態」といった内部状態を持つため、より複雑な状態管理が必要でした。
let gitState = {
branch: "main",
staged: [],
commits: [],
branches: ["main"]
};
例えば git add でステージングに追加し、git commit でその内容をコミット履歴に積む、git checkout -b feature でブランチを分岐させる、といった操作をこの状態オブジェクトの変更として表現しています。これにより、git log を打てば「今までの操作結果」を反映したコミット履歴が表示される、という一連の流れを再現できます。
Docker(コンテナの起動・停止状態)やTerraform(リソースの作成・適用状態)、AWS CLI(仮想的なS3バケットやEC2インスタンスの一覧)についても、同様に「そのレッスン用の状態オブジェクト」を持たせることで対応しています。
5. なぜこの方式にしたか(メリット・デメリット)
メリット
- サーバー費用がほぼかからない(静的ホスティングに近い構成で運用可能)
- 起動待ちがなく、ページを開いた瞬間からコマンドを打てる
- 任意のコマンド実行を許可しないため、セキュリティリスクが低い
デメリット
- 実際のシェルとの完全な互換性はない(あくまで学習用に必要な範囲のコマンドに限定)
- 新しいコマンド・オプションを追加するたびに、パーサーとロジックの拡張が必要
学習用途に絞るのであれば、この制約は許容範囲だと判断しました。むしろ「本物の環境を用意する」ことよりも「間違えても壊れない、繰り返し練習できる環境」を優先しています。
理解度チェック問題を9,000問超まで用意した理由
疑似ターミナルは「体験」としては強力ですが、それだけでは知識の定着度を測れません。そこで各レッスンごとに理解度チェック問題を用意し、章単位でまとめて復習できる問題集(現在9,357問)も並行して整備しています。
- レッスンを読む・実行する(インプット)
- 疑似ターミナルで実際に打つ(体験)
- 章末の問題で振り返る(アウトプット)
の3段階を揃えることで、「なんとなく分かった気になる」を防ぐ設計にしています。
対応カテゴリ(疑似ターミナルあり)
- Linux/シェルコマンド(全300レッスン)
- Gitコマンド(全59レッスン)
- ネットワーク(Cisco)コマンド(全300レッスン)
- Docker(全45レッスン)
- AWSコマンド(全41レッスン)
- Terraform(全37レッスン)
- Claude Code(全40レッスン)
インフラ・SRE志望の方や、実務でLinux/Gitに日常的に触れるエンジニアの練習環境としても活用できると思います。
さいごに
「読むだけの教材」と「実際にコマンドを打つ経験」の間には、想像以上の差があります。今回はその差を埋めるために、サーバーを持たない疑似ターミナルという方式を選び、Linux・Git・Docker・AWS CLI・Terraform・Claude Codeまで対応させました。
登録不要・完全無料で公開しているので、コマンド操作の練習環境として触ってみてもらえると嬉しいです。改善点やこんな機能が欲しいというフィードバックも歓迎です。
👉 プロ道(Prodou) - 環境構築から学べるプログラミング学習サイト(全31カテゴリ・3,000レッスン超・完全無料)