命令行界面 (CLI)、終端 (Terminal)、Shell、TTY,傻傻分不清楚?

原文發表在個人 博客 上,歡迎訂閱。;)

爲何忽然想寫這樣一篇文章呢?實際上是由於在最近計劃發佈的一篇關於 WSL (Windows Subsystem for Linux) 的博文中,我打算對終端模擬器、Shell 的選擇與配置進行一些說明。不過對於剛接觸 Linux 或者剛接觸命令行界面的同窗,可能會有些難以理解它們之間的區別(事實上我當初也是這樣)。php

雖然這個話題已經是老生常談,搜索一下應該也能找到大把的相關文章。不過可貴提到了這方面,就趁此機會把個人理解寫下來,一來看看我是否是真正理解了,二來看看我能不能把它們之間的區別講得更加簡明易懂。html

0. 太長不看 TL;DR

  • 命令行界面 (CLI) = 使用文本命令進行交互的用戶界面
  • 終端 (Terminal) = TTY = 文本輸入/輸出環境
  • 控制檯 (Console) = 一種特殊的終端
  • Shell = 命令行解釋器,執行用戶輸入的命令並返回結果

1. 什麼是命令行界面?

命令行界面,通俗來說,就是你看過的那種滿屏幕都是字符的界面。linux

命令行界面(英語:Command-line Interface,縮寫:CLI)是在圖形用戶界面獲得普及以前使用最爲普遍的用戶界面,它一般不支持鼠標,用戶經過鍵盤輸入指令,計算機接收到指令後,予以執行。

—— 摘自 Wikipediagit

相信你們對於影視做品中出現的那種,某黑客/程序員/安全專家坐在電腦前猛敲鍵盤、屏幕上放眼望去全是滾動的字符的場景不會感到陌生。這種靠一行行命令的輸入輸出進行交互的用戶界面,就叫作命令行界面。程序員

the_matrix_screenshot.jpg

▲ 電影「黑客帝國」劇照github

在圖形用戶界面 (GUI) 已經徹底普及的今天,普通用戶在平常使用電腦的過程當中幾乎不用手動輸入任何命令,大部分操做都是點點鼠標就能完成,而熟練使用命令行操做彷佛已經成爲高逼格的代名詞。shell

但事實上,如今依然有着不少的軟件開發者、系統管理員,或者是高級用戶在使用命令行界面操做計算機。其中很大一個緣由,就是效率:在熟記命令的前提下,使用命令行界面每每要比使用圖形用戶界面來得快。編程

舉個栗子,我要把當前目錄下的(包括嵌套的子目錄)全部 *.tpl 文件的後綴名修改成 *.blade.php,若是不使用命令行,該怎麼作?手動修改確定不至於,但也得去網上找找相關軟件,得要注意下載來源是否靠譜(像我這樣有點潔癖的選手還得去找綠色版),下載後還要手動指定文件路徑、重命名模板……ubuntu

而使用命令行的話(這裏以 Ubuntu 上的 Bash 爲例),只需運行這麼一句:vim

rename 's/\.tpl$/\.blade.php/' ./**/*.tpl

命令行操做的高效率等優勢,也是如今許多圖形化的計算機系統依然沒有放棄提供命令行操做方式的緣由。就連 Windows 都有自帶 cmd.exe 和 PowerShell 等命令行程序(事實上你在搜索「批量重命名」時,能夠看到不少方案都是經過「Windows 命令提示符」實現的)。

2. 終端 —— 人與機器交互的接口

終端 (Terminal),其詞彙自己的意義爲「終點站;末端;(電路)的端子,線接頭」。而在計算機領域,終端則是一種用來讓用戶輸入數據至計算機,以及顯示其計算結果的機器。

也就是說,終端只是一種用於與計算機進行交互的輸入輸出設備,其自己並不提供運算處理功能。

想要充分理解終端,咱們得回溯歷史,去看看終端的起源。

2.1 歷史上的終端

在大型機 (Mainframe) 和小型機 (Minicomputer) 的時代裏,計算機曾經很是昂貴且巨大,不像如今這樣人手一臺。這些笨重的計算機一般被安置在單獨的房間內,而操做計算機的人們坐在另外的房間裏,經過某些設備與計算機進行交互。這種設備就叫作 終端 (Terminal),也叫終端機。

ASR-33_2.jpg

▲ ASR-33 電傳打字機(圖片來源:Flickr - Marcin Wichary,CC-BY-2.0)

早期的終端通常是一種叫作 電傳打字機 (Teletype) 的設備。爲啥呢?由於 Unix 的創始人 Ken Thompson 和 Dennis Ritchie 想讓 Unix 成爲一個多用戶系統。多用戶系統就意味着要給每一個用戶配置一個終端,每一個用戶都要有一個顯示器、一個鍵盤。但當時全部的計算機設備都很是昂貴(包括顯示器),並且鍵盤和主機是集成在一塊兒的,根本沒有獨立的鍵盤。

後來他們機智地找到了同樣東西,那就是 ASR-33 電傳打字機。雖然電傳打字機本來的用途是在電報線路上收發電報,可是它既有能夠發送信號的鍵盤,又能把接收到的信號打印在紙帶上,徹底能夠做爲人機交互設備使用。

並且最重要的是,價格低廉。:P

因而,他們把不少臺 ASR-33 鏈接到計算機上,讓每一個用戶均可以在終端登陸並操做主機。就這樣,他們創造了計算機歷史上第一個真正的多用戶操做系統 Unix,而電傳打字機就成爲了第一個 Unix 終端。

想知道用電傳打字機作終端是一種怎樣的體驗?這裏有一個 很炫酷的演示視頻

2.2. 控制檯 (Console) 是什麼?

上面咱們說過,在歷史上,終端是鏈接到計算機上的一種帶輸入輸出功能的外設。可是有一個終端不同凡響,它與計算機主機是一體的,是計算機的一個組成部分。這個特殊的終端就叫作 控制檯 (Console)。

顧名思義,控制檯是用於管理主機的,只能給系統管理員使用,有着比普通終端更大的權限。一臺計算機上通常只有一個控制檯,可是能夠鏈接不少個終端。

console_and_terminal.jpg

▲ 左邊的是 Console,右邊的是 Terminal(圖片來源:帶你逛西雅圖活電腦博物館

放在如今咱們可能難以理解爲何會有控制檯和終端的區分,不過就像上一節所說的,當時都是不少個用戶經過終端去訪問一臺計算機,而專門管理那些大塊頭機器的系統管理員另有其人。普通用戶用的就是普通的終端,而系統管理員用的終端比較牛逼,因此就被叫作控制檯啦(笑)。

不過隨着我的計算機的普及,控制檯 (Console) 與終端 (Terminal) 的概念已經逐漸模糊。在現代,咱們的鍵盤與顯示器既能夠認爲是控制檯,也能夠認爲是普通的終端。當你在管理系統時,它們是控制檯;當你在作通常的工做時(瀏覽網頁、編輯文檔等),它們就是終端。咱們本身既是通常用戶,也是系統管理員。

所以,如今 Console 與 Terminal 基本被看做是同義詞。

2.3 字符終端與圖形終端

終端也有不一樣的種類。

字符終端 (Character Terminal) 也叫文本終端 (Text Terminal),是隻能接收和顯示文本信息的終端。早期的終端所有是字符終端。字符終端也分爲 啞終端 (Dumb Terminal) 和所謂的 智能終端 (Intelligent Terminal),由於後者能夠理解轉義序列、定位光標和顯示位置,比較聰明,而啞終端不行。

DEC_VT100_terminal.jpg

▲ DEC VT100 終端(圖片來源:Flickr - Jason Scott,CC-BY-2.0)

DEC 公司在 1978 年製造的 VT100,因爲其設計良好而且是第一批支持 ANSI 轉義序列與光標控制的智能終端,得到了空前的成功。VT100 不只是史上最流行的字符終端,更是成爲了字符終端事實上的標準。

隨着技術的進步,圖形終端 (Graphical Terminal) 也開始出如今公衆的視野中。圖形終端不但能夠接收和顯示文本信息,也能夠顯示圖形與圖像。著名的圖形終端有 Tektronix 4010 系列。

不過如今專門的圖形終端已經極爲少見,他們基本上已經被全功能顯示器所取代。

2.3. 終端模擬器 (Terminal Emulator)

隨着計算機的進化,咱們已經見不到專門的終端硬件了,取而代之的則是鍵盤與顯示器。

可是沒有了終端,咱們要怎麼與那些傳統的、不兼容圖形接口的命令行程序(好比說 GNU 工具集裏的大部分命令)交互呢?這些程序並不能直接讀取咱們的鍵盤輸入,也沒辦法把計算結果顯示在咱們的顯示器上……(圖形界面的原理我這裏就很少說了,它們編程的時候圖形接口還在孃胎裏呢!)

這時候咱們就須要一個程序來模擬傳統終端的行爲,即 終端模擬器 (Terminal Emulator)。

嚴格來說,Terminal Emulator 的譯名應該是「終端仿真器」。

對於那些命令行 (CLI) 程序,終端模擬器會「僞裝」成一個傳統終端設備;而對於現代的圖形接口,終端模擬器會「僞裝」成一個 GUI 程序。一個終端模擬器的標準工做流程是這樣的:

  1. 捕獲你的鍵盤輸入;
  2. 將輸入發送給命令行程序(程序會認爲這是從一個真正的終端設備輸入的);
  3. 拿到命令行程序的輸出結果(STDOUT 以及 STDERR);
  4. 調用圖形接口(好比 X11),將輸出結果渲染至顯示器。

終端模擬器有不少,這裏就舉幾個經典的例子:

  • GNU/Linux:gnome-terminal、Konsole;
  • macOS:Terminal.app、iTerm2;
  • Windows:Win32 控制檯、ConEmu 等。

my-terminals.png

▲ 我正在使用的終端模擬器:Hyperwsl-terminal

在專門的終端硬件已經基本上僅存於計算機博物館的現代,人們一般圖省事兒,直接稱呼終端模擬器爲「終端」。

2.4 終端窗口 (Terminal Window) 與虛擬控制檯 (Virtual Console)

大部分終端模擬器都是在圖形用戶界面 (GUI) 中運行的,可是也有例外。

好比在 GNU/Linux 操做系統中,按下 Ctrl + Alt + F1,F2...F6 等組合鍵能夠切換出好幾個黑不溜秋的全屏終端界面,而按下 Ctrl + Alt + F7 纔是切換回圖形界面。不過不要被它們唬着了,雖然它們並不運行在圖形界面中,但其實它們也是終端模擬器的一種。

KNOPPIX_booting.png

▲ 一個正在顯示系統啓動信息的虛擬控制檯(圖片來源:hacktolive.org,GPLv2)

這些全屏的終端界面與那些運行在 GUI 下的終端模擬器的惟一區別就是它們是 由操做系統內核直接提供的。這些由內核直接提供的終端界面被叫作 虛擬控制檯 (Virtual Console),而上面提到的那些運行在圖形界面上的終端模擬器則被叫作 終端窗口 (Terminal Window)。除此以外並無什麼差異。

固然了,由於終端窗口是跑在圖形界面上的,全部若是圖形界面宕掉了那它們也就跟着完蛋了。這時候你至少還能夠切換到 Virtual Console 去救火,由於它們由內核直接提供,只要系統自己不出問題通常均可用(笑)。

3. 那麼 TTY 又是什麼?

簡單來講,tty 就是終端的統稱。

爲何呢?看了上面的 2.1 節的同窗應該知道,最先的 Unix 終端是 ASR-33 電傳打字機。而電傳打字機 (Teletype / Teletypewriter) 的英文縮寫就是 tty,即 tty 這個名稱的來源。

因爲 Unix 被設計爲一個多用戶操做系統,因此人們會在計算機上鍊接多個終端(在當時,這些終端全都是電傳打字機)。Unix 系統爲了支持這些電傳打字機,就設計了名爲 tty 的子系統(沒錯,由於當時的終端全都是 tty,因此這個系統也被命名爲了 tty,就是這麼簡單粗暴),將具體的硬件設備抽象爲操做系統內部位於 /dev/tty* 的設備文件。

爲何要把電傳打字機這個硬件設備抽象成「tty 設備」文件呢?有興趣的同窗能夠去了解一下 Unix 操做系統中 Everything is a file 的概念。

tty_device_files.png

▲ 還記得上面咱們說過的特殊的終端,也就是經過 Ctrl + Alt + F1-6 呼出的那些虛擬控制檯 (Virtual Console) 嗎?其對應的就是上圖中的 tty1tty6

隨着計算機的發展,終端設備已經再也不限制於電傳打字機,可是 tty 這個名稱仍是就這麼留了下來。長此以往,它們的概念就混淆在了一塊兒。因此在現代,tty 設備就是終端設備,終端設備就是 tty 設備,無需區分。

因爲早期計算機上的 串行端口 (Serial Port) 最大的用途就是鏈接終端設備,因此當時的 Unix 會把串口上的設備也一樣抽象爲 tty 設備(位於 /dev/ttyS*)。所以,如今人們也常常將串口設備稱呼爲 tty 設備。

在 tty 子系統中後來還衍生出了 pty、ptmx、pts 等概念,這裏就不詳細展開了。有興趣的同窗能夠參考一下這篇文章:Linux TTY/PTS 概述

4. Shell —— 提供用戶界面的程序

你們都知道,操做系統有一個叫作 內核 (Kernel) 的東西,它管理着整臺計算機的硬件,是現代操做系統中最基本的部分。可是,內核處於系統的底層,是不能讓普通用戶隨意操做的,否則一個不當心繫統就崩潰啦!

但咱們總仍是要讓用戶操做系統的,怎麼辦呢?這就須要一個專門的程序,它接受用戶輸入的命令,而後幫咱們與內核溝通,最後讓內核完成咱們的任務。這個提供用戶界面的程序被叫作 Shell (殼層)。

其實 Shell 只是提供了一個用戶操做系統的入口,咱們通常是經過 Shell 去調用其餘各類各樣的應用程序,最後來達成咱們的目的。好比說咱們想要知道一個文件的內容,咱們會在 Shell 中輸入命令 cat foo.txt,而後 Shell 會幫咱們運行 cat 這個程序, cat 再去調用內核提供的 open 等系統調用來獲取文件的內容。雖然並非 Shell 直接去與內核交互,但廣義上能夠認爲是 Shell 提供了與內核交互的用戶界面。

至於爲何叫作 Shell,看下圖就知道啦。是否是很像一層殼呢?

computer_system.jpg

Shell 一般能夠分爲兩種:命令行 Shell圖形 Shell。顧名思義,前者提供一個命令行界面 (CLI),後者提供一個圖形用戶界面 (GUI)。Windows 下的 explorer.exe 就是一個典型的圖形 Shell(沒錯,它確實是,由於它接受來自你的指令,而且會幫你與內核交互完成你的指令)。

常見或歷史上知名的命令行 Shell 有:

  • 適用於 Unix 及類 Unix 系統:

    • sh (Bourne shell),最經典的 Unix shell;
    • bash (Bourne-Again shell),目前絕大多數 Linux 發行版的默認 shell;
    • zsh (Z shell),我我的最喜歡的 shell;
    • fish (Friendly interactive shell),專一於易用性與友好用戶體驗的 shell;
  • Windows 下的 cmd.exe (命令提示符) 與 PowerShell

還有其餘各類五花八門的 Shell 程序,這裏就不一一列舉了,有興趣的本身去搜一搜吧。:P

5. Shell 與終端的分工

如今咱們知道,終端乾的活兒是從用戶這裏接收輸入(鍵盤、鼠標等輸入設備),扔給 Shell,而後把 Shell 返回的結果展現給用戶(好比經過顯示器)。而 Shell 乾的活兒是從終端那裏拿到用戶輸入的命令,解析後交給操做系統內核去執行,並把執行結果返回給終端。

不過 Shell 與終端的分工有一些容易混淆的地方,這裏以例子進行說明:

  • 終端將用戶的鍵盤輸入轉換爲控制序列(除了字符之外的按鍵,好比 左方向鍵^[[D),Shell 則解析並執行收到的控制序列(好比 ^[[D將光標向左移動);
  • 不過也有例外,好比終端在接收到 Ctrl + C 組合鍵時,不會把這個按鍵轉發給當前的程序,而是會發送一個 SIGINT 信號(默認狀況下,這會致使進程終止)。其餘相似的特殊組合鍵有 Ctrl-ZCtrl-\ 等,能夠經過 stty -a 命令查看當前終端的設置。

shell_control_sequences.png

  • Shell 發出相似「把前景色改成紅色(控制序列爲 \033[31m)」「顯示 foo」等指令;
  • 終端接收這些指令,而且照着 Shell 說的作,因而你就看到了終端上輸出了一行紅色的 foo

terminal_control_sequences.png

  • 除非被重定向,不然 Shell 永遠不會知道它所執行命令的輸出結果。咱們能夠在終端窗口中上下翻頁查看過去的輸出內容,這徹底是終端提供的 feature,與 Shell 沒有半毛錢關係;
  • 命令提示符 (Prompt) 是一個徹底的 Shell 概念,與終端無關;
  • 行編輯、輸入歷史與自動補全等功能是由 Shell 提供的(好比 fish 這個 Shell 就有着很好用的歷史命令與命令自動補全功能)。不過終端也能本身實現這些功能,好比說 XShell 這個終端模擬器就能夠在本地寫完一行命令,而後整條發送給遠程服務器中的 Shell(在鏈接情況不佳時頗有用,否則打個字都要卡半天);
  • 終端中的複製粘貼功能(Shift + Insert 或者鼠標右鍵等)基本上都是由終端提供的。舉個例子,Windows 默認的終端對於複製粘貼的支持很屎,而換一個終端(例如 ConEmu)後就能夠很好地支持複製粘貼。不過 Shell 以及其餘命令行程序也能夠提供本身的複製粘貼機制(例如 vim)。

6. 總結

計算機史這玩意,有趣是挺有趣的,就是查起資料來太費腦子。

爲了避免誤人子弟,在這篇博文寫做的過程當中我也查閱了各類各樣的文檔和史料,力求內容的準確性。不過能力所限,若是文章中仍有出現謬誤,歡迎在下方評論區批評指正。

7. 參考連接

相關文章
相關標籤/搜索