Web開発
ターミナルのフルスタック解説
The full stack of terminals explained (ahmadawais.com)
要約
この記事は、開発者が長年使用していながらも曖昧になりがちな「ターミナル」「シェル」「TTY」「コンソール」といった用語の定義と、それらの関係性を詳細に解説しています。これらの用語がどのように進化し、現代のコンピューティングにおいてそれぞれどのような役割を果たしているのかを、歴史的背景から技術的な詳細まで掘り下げて説明しています。
全文翻訳
コード 40 分読了
ターミナルのフルスタック解説:ターミナル、シェル、TTY、コンソール、POSIX、ANSIエスケープシーケンス、PTY、Raw/Canonicalモード
Ahmad Awais
ほとんどの開発者は、ターミナルが実際には何であるかを理解せずに、何年もターミナルを使用しています。彼らは使い方を知っています。定義することはできません。これは、ほとんどの人が燃焼を理解せずに車を運転するのと同じように、問題ありません。しかし、時折、区別が重要になるような形で何かが壊れ、立ち往生することがあります。「ターミナル」「シェル」「tty」「コンソール」という言葉は、互換的に使用されます。そうすべきではありませんが、それらがそうであるという事実は、興味深いことを示しています。これらの概念は実際には非常に密接に結びついているため、何世代もの開発者がそれらを分離せずにやってきました。有用な質問は、「これらの言葉の意味は何か」だけでなく、「なぜ違いを知ることがあなたの考え方を変えるのか」ということです。この記事は、人々を混乱させる語彙から、TUI(テキストユーザーインターフェース)アプリをゼロから構築するまで、フルスタックをカバーしています。vimが画面を乗っ取る際に実際に行っていること、Raw Modeが存在する理由、ANSIエスケープシーケンスとは何かを疑問に思ったことがあるなら、この記事がそれです。
かつては同じものだった
これは重要な洞察です。4つの言葉すべてが、元々は同じ物理的なオブジェクトを指していました。1960年代には、キーボードとプリンターを備えた機械でコンピューターを操作していました。その機械は、誰が話しているかによって3つの名前を持っていました。
┌─────────────────────────────────────
│ ┌───────────────────────────────
│ │ $ hello world_
│ <-- "Console" (物理デバイス)
│ │ <-- "Terminal" (ワイヤーの端)
│ │ <-- "TTY" (テレタイプライターです)
│ └───────────────────────────────
│ ┌───────────────────────────────
│ │ ┌───┐┌───┐┌───┐┌───┐┌───┐
│ │ │ Q ││ W ││ E ││ R ││ T │...
│ │ └───┘└───┘└───┘└───┘└───┘
│ └───────────────────────────────
└─────────────────────────────────────
│ │ wire
│ ┌───────┴────────
│ MAINFRAME
│ COMPUTER
└────────────────
3つの名前、1つのもの。だからそれらはぼやけるのです。ハードウェアがソフトウェアに進化するにつれて、各言葉は独自の意味に向かって漂っていきました。しかし、それらはゆっくりと漂いました。
パート1:語彙
コンソール
コンソールは、コンピューターの物理的な入出力デバイスです。元々は、機械自体に直接接続されたキーボードとディスプレイを意味していました。OSの観点からは、「システムのプライマリ標準I/Oターミナル」として扱われます。サーバーでは、あなたが歩いて行ってモニターを接続したときに目にするものです。ラップトップでは、グラフィカルデスクトップがクラッシュした場合に着地するテキスト画面です。それは最後の手段のターミナルであり、カーネルがパニックメッセージを書き込む場所です。なぜなら、すべてが壊れているときでも確実に存在するからです。
リモートアクセス(コンソールではない):
You --> laptop --> SSH --> internet --> server
│ ┌────┴────
│ server
└────┬────
コンソールアクセス(本物):
You --> keyboard ──────────────────────> monitor <──────────────────────
^ これはコンソールです。直接的。物理的。ネットワークがダウンしていても動作します。
この言葉は時間とともに緩くなりました。ブラウザの開発者ツールは「コンソール」です。macOSにはConsoleというログビューアがあります。しかし、元の意味は常に同じです。直接的、ローカル、ハードウェアインターフェースです。
ターミナル
ターミナルは、あなたが見るものです。入出力を処理します。キーストロークが入り、テキストが出てきます。それがその仕事のすべてです。iTerm2、Alacritty、Windows Terminal、またはGNOME Terminalを開くとき、あなたはターミナルエミュレータを実行しています。これは、古いハードウェアターミナルが回路で行っていたことをソフトウェアで行うプログラムです。「エミュレータ」の部分は通常省略されますが、それを覚えておく価値があります。なぜなら、それは抽象化を明確にするからです。あなたのターミナルアプリはデバイスのふりをしています。ここに人々を驚かせる部分があります。ターミナルはあなたのコマンドを理解しません。lsやgit pushの意味を全く知りません。何も解析しません。それはキーボードが接続された表示面です。
┌─ TERMINAL (あなたが見るもの) ───────────────
│
│ 所有するもの:
│ - 画面へのテキストレンダリング
│ - 色とフォント
│ - スクロールバック履歴
│ - コピー&ペースト
│ - ANSIエスケープシーケンスの解釈
│
│ 所有しないもの:
│ - コマンドの理解
│ - プログラムの実行
│ - タブ補完
│ - あなたのプロンプト
└─────────────────────────────────────────
プラットフォーム別の主要なターミナルエミュレータ:
macOS: Terminal.app, iTerm2, Ghostty, Alacritty, kitty
Linux: GNOME Terminal, Konsole
Windows: Windows Terminal, ConEmu
Web/Node: xterm
これはクリーンな分離であり、クリーンな分離は注目に値します。それらは負荷を支える傾向があります。
シェル
シェルは、ターミナル内で実行されるプログラムです。それはコマンドラインインタープリタであり、あなたが入力したテキストを取得し、どのプログラムを実行するかを決定し、それを実行し、そのプロセスのライフサイクルを管理するものです。あなたはgit statusと入力します。あなたのターミナルはそのテキストをシェルに送信します。シェルはそれを解析し、gitプログラムを見つけ、プロセスを生成し、I/Oを配線します。出力はターミナルを通してあなたの目にフィードバックされます。シェルがロジックを処理しました。ターミナルがピクセルを処理しました。
あなたは入力します: git status
│ ▼
┌─ TERMINAL ───────────────────────
│
│ キー入力をバイトに変換
│ シェルにテキストを送信
└──────────────┬───────────────────
│ "git status\n"
▼
┌─ SHELL (bash, zsh, fish) ────────
│
│ コマンドを解析
│ /usr/bin/git を検索
│ プロセスを生成
│ そのライフサイクルを管理
└──────────────┬───────────────────
│ 出力バイト
▼
┌─ TERMINAL ───────────────────────
│
│ 出力を受信
│ 画面にレンダリング
│
│ On branch main
│ nothing to commit
└──────────────────────────────────
シェルの主なジョブは次のとおりです。コマンド解析(トークン分割、リダイレクト処理)、環境変数管理、プロセス起動と制御(ジョブ制御)、およびスクリプト機能の提供です。シェルは多数あり、どれを使用するかは意味のある選択です。Bashはデフォルトであり、ほぼすべてのUnixライクシステムに存在します。ZshはmacOSのデフォルトであり、拡張性の高さで人気があります。PowerShellはWindowsで全く異なるアプローチを取ります。
重要なこと:あなたのターミナルとあなたのシェルは独立しています。どちらか一方を変更しても、もう一方に影響を与えることなく交換できます。
どのターミナルでもどのシェルでも動作します
┌──────────────┐ ┌──────────────
│ iTerm2 │─────────┐ ┌─────│ Bash │
│ Alacritty │─────────┼────┼─────│ Zsh │
│ Kitty │─────────┼────┼─────│ Fish │
│ Win Terminal│─────────┘ └─────│ PowerShell
└──────────────┘ └──────────────
それらは互いに気にしません。
CLI(コマンドラインインターフェース)
CLIはより広いカテゴリです。GUIとは対照的に、コマンドがテキストとして入力され、出力がテキストとして返されるインターフェースです。シェル、REPL、TUIアプリはすべてCLIの一種です。誰かが「コマンドライン」と言うとき、彼らは通常、ls -lやgit commit -m "msg"のような単一のコマンドを入力する実際の入力行を意味します。シェルはその文字列を解析して実行します。
TTY(テレタイプライター)
TTYは4つの用語の中で最も技術的であり、最も長く無視しても安全なものです。現代のUnixでは、TTYはカーネル内のデバイスファイルであり、ターミナルをシェルに接続します。UnixライクOSのターミナルデバイスの一般的な用語です。元々は物理的なテレタイプライターを接続するためのデバイスでしたが、現在は仮想ターミナルを含む一般的なターミナルデバイスを指します。今すぐttyと入力すると、/dev/ttys003または/dev/pts/1のようなものが表示されるはずです。それはあなたの現在のセッションのデバイスファイルです。
┌──────────────┐ ┌──────────────┐ ┌──────────────
│ │ │ │ │
│ Terminal │◄───►│ TTY device │◄───►│ Shell │
│ (iTerm2) │ │ /dev/pts/1 │ │ (bash) │
│ │ │ │ │
└──────────────┘ └──────────────┘ └──────────────
user-space kernel user-space
TTYは間に位置します。それはデータフローを処理するカーネルの中間業者です。日常的な目的では、「tty」と「terminal」は同じ意味です。違いは、システムレベルのコードを書いている場合や、シグナルに関する奇妙なデバッグを行っている場合にのみ現れます。
PTY(疑似ターミナル)
PTYは、ターミナルエミュレータによって使用される仮想ターミナルデバイスです。実際には、2つのデバイスファイルがペアとして機能します。
┌─────────────────┐ ┌──────────────────
│ PTY Manager │ │ PTY Sub