第 1 章 GNU/Linux 教程

目录

1.1. 控制臺基礎
1.1.1. shell 提示符
1.1.2. X 系統下的 shell 提示符
1.1.3. root 賬戶
1.1.4. root shell 提示符
1.1.5. GUI系統管理工具
1.1.6. 虛擬控制檯
1.1.7. 怎樣退出命令行提示符
1.1.8. 怎樣關閉系統
1.1.9. 恢復一個正常的控制檯
1.1.10. 建議新手的額外軟件包
1.1.11. 額外用戶賬號
1.1.12. sudo 配置
1.1.13. 玩的時間
1.2. 類 Unix 文件系統
1.2.1. Unix 文件基礎
1.2.2. 文件系統深入解析
1.2.3. 文件系統權限
1.2.4. 控制新建檔案的許可權:umask
1.2.5. 一組使用者的許可權(組)
1.2.6. 時間戳
1.2.7. 連結
1.2.8. 命名管道(先進先出)
1.2.9. 套接字
1.2.10. 設備文件
1.2.11. 特別設備文件
1.2.12. procfs 和 sysfs
1.2.13. tmpfs
1.3. Midnight Commander (MC)
1.3.1. 自定義 MC
1.3.2. 啟動 MC
1.3.3. MC 文件管理
1.3.4. MC 命令列技巧
1.3.5. MC 內部編輯器
1.3.6. MC 內部檢視器
1.3.7. 自動啟動 MC
1.3.8. MC 中的 FTP 虛擬檔案系統
1.4. 類 Unix 工作環境基礎
1.4.1. 登入 shell
1.4.2. 定製bash
1.4.3. 特殊按鍵
1.4.4. Unix類型的鼠標操作
1.4.5. 文件內容查看
1.4.6. 文本編輯器
1.4.7. 設置默認文本編輯器
1.4.8. 定製vim
1.4.9. 記錄shell活動
1.4.10. 基本的Unix命令
1.5. 簡單 shell 命令
1.5.1. 命令執行和環境變量
1.5.2. “$LANG”變量
1.5.3. "$PATH" 變數
1.5.4. "$HOME" 變數
1.5.5. 命令列選項
1.5.6. Shell 萬用字元
1.5.7. 命令的返回值
1.5.8. 典型的順序命令和 shell 重定向
1.5.9. 命令別名
1.6. 類 Unix 的文本處理
1.6.1. Unix 文本工具
1.6.2. 正則表達式
1.6.3. 替換表達式
1.6.4. 正則表示式的全域性替換
1.6.5. 從文字檔案的表格中提取資料
1.6.6. 用於管道命令的小片段指令碼

我認爲學習一個計算機系統,就像學習一門新的外語。雖然教程和文檔是有幫助的,但你必須自己練習。爲了幫助你平滑起步,我詳細說明一些基本要點。

DebianGNULinux中最強大的設計來自Unix操作系統,一個多用戶多任務的操作系統。你必須學會利用這些特性以及Unix和GNU/Linux的相似性。

別迴避面向Unix的文檔,不要只是依賴於GNU/Linux文檔,這樣做會剝奪你瞭解許多有用的信息。

[注意] 注意

如果你在任何類Unix系統中使用過一端時間的命令行工具,你可能已經掌握了這份文檔中的內容。那請把它當做一個實戰檢驗和進修。

啓動系統之後,如果你沒有安裝X 窗口系統和顯示管理器(例如gdm3),那麼你就會看對字符登錄界面。假設你的主機名爲foo,那麼登錄提示符將如下所示。

foo login:

如果你安裝了一個 GUI 環境,例如 GNOMEKDE,那麼你能夠用 Ctrl-Alt-F1進入登錄提示符,同時你可以通過Alt-F7回到GUI環境(更多詳情請參閱下文第 1.1.6 节 “虛擬控制檯”)。

在登錄提示符下,你輸入你的用戶名,例如penguin,然後按回車鍵,接下來輸入你的密碼並再次按回車鍵。

[注意] 注意

遵循Unix傳統,Debian系統下的用戶名和密碼是大小寫敏感的。用戶名通常由小寫字母組成。第一個用戶賬號通常在安裝期間進行創建。額外的用戶賬號由root用戶用 adduser(8)創建。

系統以保存在 "/etc/motd" 中的歡迎信息(Message Of The Day)來開始,同時顯示一個命令提示符。

Debian GNU/Linux jessie/sid foo tty1
foo login: penguin
Password:
Last login: Mon Sep 23 19:36:44 JST 2013 on tty3
Linux snoopy 3.11-1-amd64 #1 SMP Debian 3.11.6-2 (2013-11-01) x86_64

The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
foo:~$

現在,你就在 shell 下。shell 解析你的命令。

如果你安裝了帶有顯示管理器的X Window System,例如通過在安裝Debian時選擇“桌面環境”所安裝GNOMEgdm3,那麼你在啓動系統後將使用圖形登陸界面。輸入你的用戶名和密碼可以登陸到非特權用戶賬號。使用tab可以在用戶名和密碼之間移動,也可以使用鼠標左擊。

要在X窗口下獲得shell提示符,你必須啓動一個x終端模擬器程序,例如gnome-terminal(1)rxvt(1)xterm(1)。在GNOME桌面環境下,你可以點擊“應用程序”→“附件”→“終端”來打開終端。

你還可以看下下面的 第 1.1.6 节 “虛擬控制檯” 章節。

在其它一些桌面系統(如 fluxbox)下面,可能沒有明顯的開始菜單入口。如果是這種情況,試下右擊桌面屏幕並希望能有彈出菜單。

root 賬戶也被稱作超級用戶或特權用戶。用這個賬戶,你能夠履行下面的系統管理任務。

  • 讀、寫和刪除系統上的任何文件,不顧它們的文件權限

  • 設置系統上任何文件的所有者和權限

  • 設置系統上任何非特權用戶的密碼

  • 免用戶密碼登錄任何用戶

無限權力的 root 賬戶,要求你慎重和負責任的使用。

[警告] 警告

從來不和其他人共享 root 密碼。

[注意] 注意

一個文件(包括硬件設備,如CD-ROM等,這些對Debian系統來說都只是一個文件)的權限可能會導致非root用戶無法使用或訪問它 。雖然在這種情況下,使用root帳戶是一個快速的方法,但正確的解決方法應該是對文件權限和用戶組的成員進行合適的設置(參見第 1.2.3 节 “文件系統權限”)。

如果你的桌面菜單沒有適當的權限啓動系統管理工具,你可以在X終端模擬器(例如gnome-terminal(1)rxvt(1)xterm(1))中root的shell提示符下啓動它。參見第 1.1.4 节 “root shell 提示符”第 7.8.5 节 “以 root 執行 X 客戶端”

[警告] 警告

永遠不要以根帳號鍵入 rootgdm3(1) 的提示符號下啟動 X 顯示器。

[警告] 警告

永遠不要在顯示關鍵信息的X Window下運行不受信任的遠程GUI程序,因爲它可能會監聽你的X屏幕。

在默認的Debian系統中,有6個可切換的類VT100字符控制檯,可以直接在Linux主機上啓動shell。除非你處於GUI環境下,否則你可以同時按下左Alt鍵F1F6之一的鍵在虛擬控制檯間切換。每一個字符控制檯都允許獨立登陸賬戶並提供多用戶環境。這個多用戶環境是偉大的Unix的特性,很容易上癮。

如果你處於X Window System中,你可以通過Ctrl-Alt-F1鍵前往字符控制檯1,也就是同時按下左Ctrl鍵左Alt鍵F1鍵。你可以按下Alt-F7回到X Window System,它一般運行在虛擬控制檯7。

你也可以使用命令行切換到另一個虛擬控制檯,例如切換到控制檯1。

# chvt 1

就像任何其他的現代操作系統一樣,Debian會通過內存中的緩存數據進行文件操作以提高性能,因此在電源被安全地關閉前需要適當的關機過程,通過將內存中的數據強制寫入硬盤來維持文件的完整性。如果軟件的電源控制可用,那麼關機過程中會自動關閉系統電源。(否則,你可能需要在關機過程之後按電源鍵幾秒鐘。)

在普通多用戶模式模式下,可以使用命令行關閉系統。

# shutdown -h now

在單用戶模式下,可以使用命令行關閉系統。

# poweroff -i -f

另外,如果在“/etc/inittab”中含有“ca:12345:ctrlaltdel:/sbin/shutdown -t1 -a -h now”,那麼你可以按下Ctrl-Alt-Delete(同時按下左Ctrl鍵左Alt鍵Delete)來關機。參見inittab(5)獲取更多細節。

參見第 6.9.6 节 “怎樣通過 SSH 關閉遠端系統”

不需任何桌面環境,就能執行Debian的最小安裝方式,但若能使用 mcvim 併用 apt-get(8),對初學者而言,仍是有用的。

# apt-get update
 ...
# apt-get install mc vim sudo
 ...

如果你已經安裝了這些軟件包,那麼不會有新的軟件包被安裝。


閱讀一些信息文檔,也是一個好的主意。


你可以用下面的命令安裝這些包。

# apt-get install package_name

對於典型的單用戶工作站,例如運行在筆記本電腦上的桌面Debian系統,通常簡單地配置sudo(8)來使爲非特權用戶(例如用戶penguin)只需輸入用戶密碼而非root密碼就能獲得管理員權限。

# echo "penguin  ALL=(ALL) ALL" >> /etc/sudoers

另外,可以使用下列命令使非特權用戶(例如用戶penguin)無需密碼就獲得管理員權限。

# echo "penguin  ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers

這些技巧只對你管理的單用戶工作站中那個唯一的用戶有用。

[警告] 警告

在多用戶工作站中不要建立這樣的普通用戶賬戶,因爲它會導致非常嚴重的系統安全問題。

[小心] 小心

在上述例子中,用戶penguin的密碼及賬號要有和root賬號密碼同樣多的保護。

[小心] 小心

在這種情況下,管理員權限被賦予那些有權對工作站進行系統管理任務的人。永遠不要讓你的公司行政管理部門或你的老闆進行管理(例如給予他們權限),除非他們獲得了授權並有這樣的能力。

[注意] 注意

爲了對受限的設備和文件提供訪問權限,你應該考慮使用 羣組 提供的近用限制而不是使用 root 權限,來自 sudo(8)

[注意] 注意

隨着越來越細緻周密的配置,sudo(8)可以授予一個共享系統上的其它用戶有限的管理權限而不共享root密碼。這可以幫助對有多個管理員的主機進行責任追究,你可以瞭解到是誰做什麼。另一方面,你可能不想任何人有這樣的權限。

在GNU/Linux和其他類Unix操作系統中,文件被組織到目錄中。所有的文件和目錄排放在以“/”爲根的巨大的樹裏。叫它樹是因爲如果你畫出文件系統,它看起來就像一棵樹,但是它是顛倒過來的。

These files and directories can be spread out over several devices. mount(8) serves to attach the filesystem found on some device to the big file tree. Conversely, umount(8) detaches it again. On recent Linux kernels, mount(8) with some options can bind part of a file tree somewhere else or can mount filesystem as shared, private, slave, or unbindable. Supported mount options for each filesystem are available in "/usr/share/doc/linux-doc-*/Documentation/filesystems/".

Unix系統上叫做目錄,某些其他系統上叫做文件夾。請同樣留意,在任何Unix系統上,沒有的驅動器的概念,例如“A:”。這只有一個文件系統,並且所有東西都包含在內。這相對於Windows來說是一個巨大的優點。

下面是一些 Unix 文件基礎。

[注意] 注意

雖然你可以在文件名中使用任意的字幕或者符號, 但是在實際情況下這樣做是一個壞主意. 最好避免使用一些在命令行裏面含有特殊意義的字符, 比如空格, 製表符, 換行符, 和其它的特殊字符: { } ( ) [ ] ' ` " \ / >< | ; ! #&^ * % @ $. 如果你想有一個區分度良好的命名, 比較好的選擇是利用 時期, 連字符和下劃線. 你也可以每個單詞的首字母大寫, 這叫大駝峯命名法, 比如這樣 "LikeThis". 經驗豐富的Linux用戶會趨向於在文件名中不使用空格.

[注意] 注意

這個 "root" 可能既表示 "超級用戶root" 又表示 " 根目錄"(/root) . 應該根據上下文確定它的用法.

[注意] 注意

單詞path不僅表示包含全限定文件名, 也可能表示命令搜索的路徑. 通常路徑真實的意思是需要通過上下文來明確.

關於文件層次的最佳詳細實踐在文件系統層次標準("/usr/share/doc/debian-policy/fhs/fhs-2.3.txt.gz" 和 hier (7)). 你應該記住以下的一些標準作爲開始學習的步驟.


按照UNIX系統的傳統,Debian GNU / Linux 的檔案系統是在物理資料儲存裝置諸如磁碟或其他儲存裝置上,與硬體裝置的互動,如控制檯和遠端串列埠終端都是以統一的方式呈現在 “/ dev /” 下面。

Each file, directory, named pipe (a way two programs can share data), or physical device on a Debian GNU/Linux system has a data structure called an inode which describes its associated attributes such as the user who owns it (owner), the group that it belongs to, the time last accessed, etc. The idea of representing just about everything in the filesystem was a Unix innovation, and modern Linux kernels have developed this idea ever further. Now, even information about processes running in the computer can be found in the filesystem.

這個對物理實體和內部進程的統一和抽象是非常強大的,因爲這允許我們用同樣的命令對許多完全不同的設備進行同樣的操作。甚至可以通過向鏈接到運行進程的特殊文件寫入數據來改變內核的運行方式。

[提示] 提示

如果你需要識別文件樹和物理實體之間的對應關係,不帶參數運行mount(8)

類Unix系統的文件系統權限被定義給三類受影響的用戶。

  • 擁有這個文件的用戶u

  • 這個文件所屬的其他用戶(g

  • 所有其餘的用戶(o),同樣稱爲“世界”和“所有人”

對文件來說,每個對應權限允許下列動作。

  • 可讀r)權限允許所有者檢查文件的內容。

  • 可寫w)權限允許所有者修改文件內容。

  • 可執行x)權限允許所有者把文件當做一個命令運行。

對於目錄來說,每個對應權限允許下列動作。

  • 可讀r)權限允許所有者列出目錄內的內容。

  • 可寫w)權限允許所有者添加或刪除目錄裏面的文件。

  • 可執行x)權限允許所有者訪問目錄裏的文件。

在這裏,一個目錄的可執行權限意味着不僅允許讀目錄裏的文件,還允許顯示他們的屬性,例如大小和修改時間。

ls(1)用於顯示文件和目錄的權限信息(更多)。當運行時帶有“-l”選項,它將按給定順序顯示下列信息。

  • 文件類型(第一個字母)

  • 文件的訪問權限(9個字符,三個字符組成一組按照用戶、組、其他的順序表示)

  • 鏈接到文件的硬鏈接數

  • 文件所有者的用戶

  • 這個文件所屬的

  • 以字符(字節)爲單位的文件大小

  • 文件的日期和時間(mtime)

  • 文件的名字


chown(1)用於 root 賬戶修改文件的所有者。chgrp(1)用於文件的所有者或 root 賬戶修改文件所屬的組。chmod(1)用於文件的所有者或root賬戶修改文件和文件夾的訪問權限。操作一個foo文件的基本語法如下 。

# chown <newowner> foo
# chgrp <newgroup> foo
# chmod  [ugoa][+-=][rwxXst][,...] foo

例如,你可以按照下面使一個目錄樹被用戶foo所有,並共享給組bar

# cd /some/location/
# chown -R foo:bar .
# chmod -R ug+rwX,o=rX .

有三個更加特殊的權限位。

  • Set_User_ID位(sS替換用戶的x

  • Set_Group_ID位(sS替換組的x

  • 粘置位(tT替代其他用戶的x

如果“ls -l”對這些位的輸出是大寫字母,則表示這些輸出下面的執行位未設定

給一個可執行文件設置Set-User-ID位將允許一個用戶以他自己的ID運行這個可執行文件(例如root)。類似的,給一個可執行文件設置了Set-Group-ID位將允許一個用戶以文件的組ID運行該文件。(例如root組)。由於這些設置可能引起安全風險,使能它們的時候需要格外留意。

在一個目錄上設置“Set-Group-ID”將打開類 BSD 的文件創建計劃,所有在目錄裏面創建的文件將屬於目錄所屬的

給一個目錄設定“粘滯位”將保護該目錄內的檔案不被其所有者之外的一個使用者刪除。為了保護一個在像“/tmp”這樣所有人可寫或同組可寫的目錄下檔案內容的安全,不僅要去除可寫許可權,還要給其所在目錄設定粘滯位。否則,該檔案可以被任意對其所在目錄有寫許可權的使用者刪除並建立一個同名的新檔案。

這裏有少量有趣的文件權限例子。

$ ls -l /etc/passwd /etc/shadow /dev/ppp /usr/sbin/exim4
crw------T 1 root root   108, 0 Oct 16 20:57 /dev/ppp
-rw-r--r-- 1 root root     2761 Aug 30 10:38 /etc/passwd
-rw-r----- 1 root shadow   1695 Aug 30 10:38 /etc/shadow
-rwsr-xr-x 1 root root   973824 Sep 23 20:04 /usr/sbin/exim4
$ ls -ld /tmp /var/tmp /usr/local /var/mail /usr/src
drwxrwxrwt 14 root root  20480 Oct 16 21:25 /tmp
drwxrwsr-x 10 root staff  4096 Sep 29 22:50 /usr/local
drwxr-xr-x 10 root root   4096 Oct 11 00:28 /usr/src
drwxrwsr-x  2 root mail   4096 Oct 15 21:40 /var/mail
drwxrwxrwt  3 root root   4096 Oct 16 21:20 /var/tmp

chmod(1)有另一種數值模式來描述檔案許可權。這種數字模式使用3到4位八進位制(底為8)數。


這聽起來很複雜實際上相當簡單。如果你把“ls -l”命令輸出的前幾列(2-10),看成以二進位制(底為2)表示檔案的許可權(“-”看成0,“rwx”看成1),你應該可以理解用數字模式值的最後3位數字對檔案許可權的八進位制表示。

嘗試下列例子

$ touch foo bar
$ chmod u=rw,go=r foo
$ chmod 644 bar
$ ls -l foo bar
-rw-r--r-- 1 penguin penguin 0 Oct 16 21:39 bar
-rw-r--r-- 1 penguin penguin 0 Oct 16 21:35 foo
[提示] 提示

如果你需要在 shell 指令碼中訪問“ls -l”顯示的資訊,你需要使用相關命令,如test(1)stat(1)readlink(1)。shell 內建命令,如“[”或“test”,可能也會用到。

為了使組許可權應用到一個特定使用者,這個使用者需要通過使用 “sudo vigr” 編輯 /etc/group 以及使用 “sudo vigr -s” 編輯 /etc/gshadow 成為該組的成員。你需要登出之後重新登入(或執行 “exec newgrp”)以啟用新的組配置。

[注意] 注意

或者,你可以通過新增一行 “auth optional pam_group.so”到 “/etc/pam.d/common-auth” 以及配置 “/etc/security/group.conf” ,使得在身份驗證過程動態新增使用者到組。(參見第 4 章 認證。)

在 Debian 系統中,硬體裝置是另一種檔案。如果你從一個使用者賬戶訪問某些裝置出現問題,例如CD-ROM和USB記憶棒,你需要使這個使用者成為相關組的成員。

一些著名的由系統提供的組允許其成員不需要 root 許可權訪問某些特定的檔案和裝置。


[提示] 提示

你需要屬於 dialout 組使得可以重配置調變解調器,撥號到任意地方,等等。但如果root 使用者在 “/etc/ppp/peers/” 為受信任點建立了預定義配置檔案的話,你只需要屬於dip 組,就可以通過使用pppd(8)pon(1),以及poff(1)命令 建立撥號 IP 連結到這些受信任的點。

某些著名的由系統提供的組允許它們的成員不帶 root 許可權執行特定的命令。


由系統提供的使用者和組的完整列表,參見由 base-passwd包提供的“/usr/share/doc/base-passwd/users-and-groups.html”中,當前版本的“使用者和組”。

使用者和組系統的管理命令,參見passwd(5)group(5)shadow(5)newgrp(1)vipw(8)vigr(8),以及pam_group(8)

有兩種方法把一個檔案 “foo” 連結到一個不同的檔名 “bar”。

請參閱下面的示例,rm 命令結果中連結數的變化和細微的差別。

$ umask 002
$ echo "Original Content" > 1 foo
$ ls -li foo
1449840 -rw-rw-r-- 1 penguin penguin 17 Oct 16 21:42 foo
$ ln foo bar     # hard link
$ ln -s foo baz  # symlink
$ ls -li foo bar baz
1449840 -rw-rw-r-- 2 penguin penguin 17 Oct 16 21:42 bar
1450180 lrwxrwxrwx 1 penguin penguin  3 Oct 16 21:47 baz -> 2 foo
1449840 -rw-rw-r-- 2 penguin penguin 17 Oct 16 21:42 foo
$ rm foo
$ echo "New Content" > 3 foo
$ ls -li foo bar baz
1449840 -rw-rw-r-- 1 penguin penguin 17 Oct 16 21:42 bar
1450180 lrwxrwxrwx 1 penguin penguin  3 Oct 16 21:47 baz -> 4 foo
1450183 -rw-rw-r-- 1 penguin penguin 12 Oct 16 21:48 foo
$ cat bar
Original Content
$ cat baz
New Content

硬連結可以在同一個檔案系統內建立,並共用同一個inode號,如ls(1)帶 “-i”選項顯示的。

符號連結總是名義上具有“rwxrwxrwx”的檔案訪問許可權,如上面例子所示,實際的有效訪問許可權由它所指向的檔案確定。

[小心] 小心

除非你有非常好的理由,否則不要建立一個複雜的符號連結或硬連結通常是個好主意。符號連結的邏輯組合可能導致檔案系統噩夢般的無限迴圈。

[注意] 注意

通常使用符號連結比使用硬連結更合適,除非你有一個好理由使用硬連結。

.”目錄連結到它所在的目錄,因此任何新建目錄的連結數從2開始。“..”目錄連結到父目錄,因此目錄的連結數隨著新的子目錄的建立而增加。

如果你剛從Windows遷移到Linux,你很快將清楚 Unix 的檔名連結相較於Windows最相近的“快捷方式”是多麼精心設計的。由於它是在檔案系統中實現的,應用無法看到連結檔案跟原始檔案之間的區別。在硬連結這種情況,這真的是毫無差別。

命名管道是一個像管道一樣的檔案。你把內容放進了檔案,它從另一端出來。因此,它被稱為FIFO,即先進先出:你從管道這端先放進去的東西會從另一端先出來。

如果對一個命名管道進行寫入操作,寫入的過程不會被終止,直到寫入的資訊從管道中被讀取出來。讀取過程將會持續到沒有資訊可以讀取為止。管道的大小始終是零,它不儲存資料,它只是連線兩個過程,像shell提供的 " 1| 2" 語法功能一樣。然而,一旦管道有了名稱,這兩個程序就可以不必在同一個命令列,甚至由同一個使用者執行。管道是 UNIX 的一個非常有影響力的創新。

嘗試下列例子

$ cd; mkfifo mypipe
$ echo "hello" >mypipe & # put into background
[1] 8022
$ ls -l mypipe
prw-rw-r-- 1 penguin penguin 0 Oct 16 21:49 mypipe
$ cat mypipe
hello
[1]+  Done                    echo "hello" >mypipe
$ ls mypipe
mypipe
$ rm mypipe

設備文件包括系統的物理設備和虛擬設備,如硬盤、顯卡、顯示屏、鍵盤。虛擬設備的一個例子是控制檯,用“/dev/console”來描述。

設備文件有兩種類型。

  • 字符設備

    • 每次訪問一個字符

    • 一個字符等於一個字節

    • 如鍵盤、串口…

  • 塊設備

    • 通過更大的單元–塊,進行訪問

    • 一個塊>一個字節

    • 如硬盤等…

你可以讀寫塊設備文件,儘管該文件可能包含二進制數據,讀取後顯示出無法理解的亂碼。向文件寫入數據,有時可以幫助定位硬件連接故障。比如,你可以將文本文件導入打印機設備“/dev/lp0”,或者將調製解調命令發送到合適的串口“/dev/ttyS0”。但是,除非這些操作都小心完成,否則可能會導致一場大災難。所以要特別小心。

[注意] 注意

常規訪問打印機,使用lp(1)

設備的節點數可以通過執行ls(1)得到,如下所示。

$ ls -l /dev/sda /dev/sr0 /dev/ttyS0 /dev/zero
brw-rw---T  1 root disk     8,  0 Oct 16 20:57 /dev/sda
brw-rw---T+ 1 root cdrom   11,  0 Oct 16 21:53 /dev/sr0
crw-rw---T  1 root dialout  4, 64 Oct 16 20:57 /dev/ttyS0
crw-rw-rw-  1 root root     1,  5 Oct 16 20:57 /dev/zero
  • "/dev/sda"的主設備號是8,次設備號是0。它可以被disk羣組的用戶讀寫。

  • "/dev/sr0"的主設備號是11,次設備號是0。它可以被cdrom羣組的用戶讀寫。

  • "/dev/ttyS0"的主設備號是4,次設備號是64。它可以被dailout羣組的用戶讀寫。

  • "/dev/zero"的主設備號是1,次設備號是5。它可以被任意用戶讀寫。

在現代Linux系統中,處在"/dev"之下的文件系統會自動被udev()機制填充。

procfssysfs兩個僞文件系統,分別加載於"/proc"和"/sys"之上,將內核中的數據結構暴露給用戶空間。或者說,這些條目是虛擬的,他們打開了深入瞭解操作系統運行的方便之門。

目錄"/proc"爲每個正在運行的進程提供了一個子目錄,目錄的名字就是進程標識符(PID)。需要讀取進程信息的系統工具,如ps(),可以從這個目錄結構獲得信息。

"/proc/sys"之下的目錄,包含了可以更改某些內核運行參數的接口。(你也可以使用專門的sysctl()命令修改,或者使用其預加載/配置文件"/etc/sysctl.conf"。)

當人們看到這個特別大的文件"/proc/kcore"時,常常會驚慌失措。這個文件於你的的電腦內存大小相差不多。它被用來調試內核。它是一個虛擬文件,指向系統內存,所以不必擔心它的大小。

"/sys"以下的目錄包含了內核輸出的數據結構,它們的屬性,以及它們之間的鏈接。它同時也包含了改變某些內核運行時參數的接口。

參考"proc.txt(.gz)","sysfs.txt(.gz)",以及其他相關的Linux內核文檔("/usr/share/doc/linux-doc-*/Documentation/filesystems/*"),這些文件由linux-doc-*軟件包提供。

tmpfs是一個臨時文件系統,它的文件都保存在虛擬內存中。必要時,位於內存頁緩存的tmpfs數據可能被交換到硬盤中的交換分區

系統啓動早期階段,"/run"目錄掛載爲tmpfs。這樣即使"/"掛載爲只讀,它也是可以被寫入的。它爲過渡態文件提供了新的存儲空間,同時也替代了Filesystem Hierarchy Standar2.3版中說明的目錄位置:

  • "/var/run" → "/run"

  • "/var/lock" → "/run/lock"

  • "/dev/shm" → "/run/shm"

參考"tmpfs.txt(.gz)", 文件位於Linux內核文檔("/usr/share/doc/linux-doc-*/Documentation/filesystems/*")目錄之下,由軟件包linux-doc-*提供。

Midnight Commander (MC) 是一個Linux終端或其它終端環境下的 GNU 版 "瑞士軍刀" 。它為新手們提供了一個選單式樣的終端使用體驗,這更易於學習運用標準的 Unix 命令。

你可能需要按照下面的命令來安裝標題為 " mc " 的Midnight Commander 包.

$ sudo apt-get install mc

使用 mc(1) 命令那個來瀏覽 Debian 系統。這是最好的學習方式。請使用游標鍵和回車鍵來翻看一些感興趣的內容。

  • "/etc" 及其子目錄

  • " /var/log " 及其子目錄

  • " /usr/share/doc " 及其子目錄

  • " /sbin " 和 " /bin "

雖然 MC 差不多可以讓你做任何事情,但學會從 shell 提示下使用命令列工具也是非常重要的,可以讓你變得熟悉類 Unix 工作環境。

在使用類 Unix 系統過程中, 各種類似於VimEmacs的工具,你應該精通其中的一個。

我認為習慣於使用 Vim 命令是一個明智的選擇,因為Linux/Unix系統裡一般都附帶了 Vi 編輯器。 (實際上最初的vi 以及後來的 nvi 這類工具程式很常見。因為在 Vim 裡提供了F1幫助鍵,在同類工具中它的功能更強大,所以我選擇 Vim 而不是其它新出的一些工具。)

假設你不是用 Emacs 就是用XEmacs 作為你的編輯器,其實還有更好的選擇,尤其是在程式設計的時候。 Emacs 還有很多其他的特點,包括新手導讀,目錄編輯器,郵件客戶端等等。當編寫指令碼或程式的時候,它能自動識別當前工作模式所對應的格式,讓使用更加便利。一些人甚至堅持認為Linux系統裡最需要配備的就是 Emacs。花十分鐘來學習 Emacs 可以為後面的工作剩下更多時間。在此強烈推薦學習使用 Emacs 時候直接使用 GNU Emacs 參考手冊。

在實踐應用中所有這些程式都會有一個教程,輸入 "vim" 和F1鍵就可以啟動Vim。建議你最好閱讀一下前面的35行。移動游標到 "|tutor|" 並按 Ctrl-] 就可以看到線上培訓教程。

[注意] 注意

好的編輯器,像 Vim 和 Emacs,可以處理 UTF-8 及其它不常用編碼格式的文字。有個建議就是在 X 環境下使用UTF-8編碼,並安裝要求的程式和字型。編輯器裡可以選擇獨立於 X 環境的編碼格式。關於多位元組文字可以查閱參考文件。

讓我們來學習基本的Unix命令。在這裏,我指的是一般意義上的“UNIX”。任何UNIX克隆系統通常都會提供等價的命令。Debian系統也不例外。如果有一些命令不像你想的那樣起作用,請不要擔心。如果shell中使用了別名,其對應的命令輸出會不同。這些例子並不意味着要以這個順序來執行。

嘗試使用非特權用戶賬號來使用下列的命令。

表 1.16. 基本的Unix命令列表

命令 說明
pwd 顯示當前/工作目錄的名稱
whoami 顯示當前的用戶名
id 顯示當前用戶的身份(名稱、uid、gid和相關組)
file <foo> 顯示“<foo>”文件的文件類型
type -p <commandname> 顯示“<commandname>”命令的文件所處位置
which <commandname> 同上
type <commandname> 顯示“<commandname>”命令的相關信息
apropos <key-word> 查找與“<key-word>”有關的命令
man -k <key-word> 同上
whatis <commandname> 用一行解釋 “<commandname>” 命令
man -a <commandname> 顯示“<commandname>”命令的解釋(Unix風格)
info <commandname> 顯示“<commandname>”命令相當長的解釋(GNU風格)
ls 顯示目錄內容(不包含以 . 點號開頭的文件和目錄)
ls -a 顯示目錄內容(包含所有文件和目錄)
ls -A 顯示目錄內容(包含幾乎所有文件和目錄,除了“..”和“.”)
ls -la 顯示所有的目錄內容,幷包含詳細的信息
ls -lai 顯示所有的目錄內容,幷包含inode和詳細的信息
ls -d 顯示當前目錄下的所有目錄
tree 使用樹狀圖顯示目錄內容
lsof <foo> 列出處於開啟狀態的檔案 "<foo>"
lsof -p <pid> 列出被某程序開啟的檔案: "<pid>"
mkdir <foo> 在當前目錄中建立新目錄“<foo>
rmdir <foo> 刪除當前目錄中的“<foo>”目錄
cd <foo> 切換到當前目錄下或變量“$CDPATH”中的“<foo>”目錄
cd / 切換到根目錄
cd 切換到當前用戶的家目錄
cd /<foo> 切換到絕對路徑爲“/<foo>”的目錄
cd .. 切換到上一級目錄
cd ~<foo> 切換到用戶“<foo>”的家目錄
cd - 切換到之前的目錄
</etc/motd pager 使用默認的分頁顯示程序來顯示“/etc/motd”的內容
touch <junkfile> 建立一個空文件“<junkfile>
cp <foo> <bar> 將一個現有文件“<foo>”複製到一個新文件“<bar>
rm <junkfile> 刪除文件“<junkfile>
mv <foo> <bar> 將一個現有文件“<foo>”重命名成“<bar>”(“<bar>”必須不存在)
mv <foo> <bar> 將一個現有文件“<foo>”移動到新的位置“<bar>/<foo>”(必須存在“<bar>”目錄)
mv <foo> <bar>/<baz> 移動一個現有文件“<foo>”到新位置並重命名爲“<bar>/<baz>”(必須存在“bar”目錄,且不存在“bar>/<baz>”目錄)
chmod 600 <foo> 使其他人無法讀寫現有文件“<foo>”(並且所有人都無法執行該文件)
chmod 644 <foo> 使其他人對現有文件“<foo>”可讀但不可寫(並且所有人都無法執行該文件)
chmod 755 <foo> 使其他人對“<foo>”可讀而不可寫(並且所有人都能執行該文件)
find . -name <pattern> 使用 shell “<pattern>” 查找匹配的文件名(速度較慢)
locate -d . <pattern> 使用 shell “<pattern>” 查找匹配的文件名(速度較快,使用定期生成的數據庫)
grep -e "<pattern>" *.html 在當前目錄下以“.html”結尾的所有文件中,查找匹配“<pattern>”的文件並顯示
top 全屏顯示進程信息,輸入“q”退出
ps aux | pager 顯示所有正在運行的進程的信息(BSD風格)
ps -ef | pager 顯示所有正在運行的進程的信息(Unix system-V風格)
ps aux | grep -e "[e]xim4*" 顯示所有正在運行“exim”和“exim4”的進程
ps axf | pager 顯示所有正在運行的進程的信息(ASCII風格)
kill <1234> 殺死ID爲“<1234>”的進程
gzip <foo> 使用 Lempel-Ziv 編碼(LZ77)將“<foo>”壓縮爲“<foo>.gz
gunzip <foo>.gz 將“<foo>.gz”解壓爲“<foo>
bzip2 <foo> 使用 Burrows-Wheeter 塊排序壓縮算法和 Huffman 編碼將“<foo>”壓縮爲“<foo>.bz2”(壓縮效果比gzip更好)
bunzip2 <foo>.bz2 將“<foo>.bz2”解壓爲“<foo>
xz <foo> 使用 Lempel-Ziv-Markov 鏈算法將“<foo>”壓縮爲“<foo>.xz”(壓縮效果比bzip2更好)
unxz <foo>.xz 將“<foo>.xz”解壓爲“<foo>
tar -xvf <foo>.tar 從“<foo>.tar”檔案中提取文件
tar -xvzf <foo>.tar.gz 從被gzip壓縮過的“<foo>.tar.gz”檔案中提取文件
tar -xvjf <foo>.tar.bz2 從“<foo>.tar.bz2”檔案中提取文件
tar -xvJf <foo>.tar.xz 從“<foo>.tar.xz”檔案中提取文件
tar -cvf <foo>.tar <bar>/ 將目錄“<bar>/”中的內容打包到“<foo>.tar”檔案中
tar -cvzf <foo>.tar.gz <bar>/ 將目錄“<bar>/”中的內容打包到被壓縮的“<foo>.tar.gz”檔案中
tar -cvjf <foo>.tar.bz2 <bar>/ 將目錄“<bar>/”中的內容打包到“<foo>.tar.bz2”檔案中
tar -cvJf <foo>.tar.xz <bar>/ 將目錄”<bar>/“中的內容打包到”<foo>.tar.xz“檔案中
zcat README.gz | pager 使用默認的分頁顯示程序來顯示“README.gz”壓縮包中的內容
zcat README.gz > foo 將“README.gz”解壓後的內容輸出到文件“foo”中
zcat README.gz >> foo 將“README.gz”解壓後的內容添加到文件“foo”的末尾(如果文件不存在,則會先建立該文件)

[注意] 注意

Unix有一個慣例,以“.”開頭的文件將被隱藏。它們一般爲包含了配置信息和用戶首選項的文件。

[注意] 注意

對於cd命令,參見builtins(7)

[注意] 注意

基本的 Debian 系統的默認分頁顯示程序是more(1),它無法往回滾動。通過命令“apt-get install less"安裝less軟件包後,less(1)會成爲默認的分頁顯示程序,它可以通過方向鍵往回滾動。

[注意] 注意

"[" 和"]" 在正則表示式 "ps aux | grep -e "[e]xim4*"" 命令中,可以避免grep在結果中排除它自己, 正則表示式中的 "4*" 意思是空或字元"4" ,這樣可以讓 grep 既找到 "exim" 也找到 "exim4"。 雖然 "*" 可以用於命令名稱匹配和正則表示式中,但是它們的含義是不一樣的。欲詳細瞭解正則表示式可以參考 grep(1)

作爲訓練,請使用上述的命令來遍歷目錄並探究系統。如果你有任何有關控制臺命令的問題,請務必閱讀手冊。

嘗試下列例子

$ man man
$ man bash
$ man builtins
$ man grep
$ man ls

手冊的風格可能讓人有點難以習慣,因爲它們都相當簡潔,尤其是比較老舊、非常傳統的那些手冊。但是,一旦你習慣了它,你來欣賞它們的簡潔。

請注意,許多類Unix命令(包含來自 GNU 和 BSD 的)都可以顯示簡短的幫助信息,你可以使用下列的其中一種方式來查看它(有時不帶任何參數也可以)。

$ <commandname> --help
$ <commandname> -h

現在,你對如何使用 Debian 系統已經有一些感覺了。讓我們更深入瞭解 Debian 系統的命令執行機制。在這裏,我將爲新手做一般的講解。精確的解釋參見bash(1)

一般的命令由有序的組件構成。

  1. 設置變量值(可選)

  2. 命令名

  3. 參數(可選)

  4. 重定向(可選:> , >> , < , << 等等)

  5. 控制操作(可選:&&|| , <換行符> , ; , & , ( , )

一些環境變量的值會改變部分Unix命令的行爲。

環境變量的默認值由PAM系統初始化,其中一些會被某些應用程序重新設定。

  • 顯示管理器(例如gdm3)會重新設定環境變量。

  • Shell指令碼啟動的時候會重置 "~/.bash_profile" 和 "~/.bashrc" 中的環境變數。

$LANG” 變數的完整的語言環境值由3部分組成:“xx_YY.ZZZZ”。


對於語言代碼和國家代碼,參加“info gettext”中的相關描述。

對於現代 Debian 系統中的編碼,你應該總是設定爲UTF-8,除非你有足夠的理由和背景知識並且特別想使用過時的編碼。

對於語言環境配置的細節,參見 第 8.4 节 “語言環境”

[注意] 注意

LANG=en_US”即不是“LANG=C”也不是“LANG=en_US.UTF-8”。它是“LANG=en_US.ISO-8859-1”(參見第 8.4.1 节 “編碼的基礎知識”)。


使用 shell 命令行按順序執行下列典型的命令。

$ date
Sun Jun  3 10:27:39 JST 2007
$ LANG=fr_FR.UTF-8 date
dimanche 3 juin 2007, 10:27:33 (UTC+0900)

這裏,date(1)程序執行時使用了與環境變量“$LANG”不同的值。

大多數的命令在執行時並沒有預先定義環境變量。對於上面的例子,你也可以選擇如下的方式。

$ LANG=fr_FR.UTF-8
$ date
dimanche 3 juin 2007, 10:27:33 (UTC+0900)

正如你所看到的,命令的輸出受環境變數的影響,上面產生的是法語輸出。如果你想這個環境變數能在子程序中被繼承的話(例如執行 shell 指令碼時),你需要使用下面的命令匯出(export)它。

$ export LANG
[注意] 注意

在使用常規的控制檯終端的時候,環境變數 "$LANG" 通常會被桌面環境變數通過 exported 方式重置。如果要測試 export 帶來的影響,這個可能不是一個很好的例子。

[提示] 提示

提交一個BUG報告的時候,如果使用的是非英語的環境,在 "LANG=en_US.UTF-8" 環境下對命令進行執行和檢查會更好一些。

可以通過命令 locale(5)locale(7) 來檢視 "$LANG" 及相關的環境變數。

[注意] 注意

建議最好用變數 "$LANG" 來配置系統環境變數,只有在逼不得已的情況下才用 $LC_*" 開頭的變數。

讓我們試著記住下面 Shell 命令裡部分命令列所使用的命令習語。


Debian 系統是一個多任務的操作系統。後臺任務讓用戶能夠在一個 shell 中執行多個程序。後臺進程的管理涉及 shell 的內建命令:jobsfgbgkill。請閱讀 bash(1) 中的章節:“SIGNALS”、“JOB CONTROL” 和 “builtins(1)”。

嘗試下列例子

$ </etc/motd pager
$ pager </etc/motd
$ pager /etc/motd
$ cat /etc/motd | pager

儘管4個 shell 重定向的例子都會顯示相同的結果,但最後一個例子毫無意義地運行了額外的 cat 命令浪費了資源。

shell 允許你使用 exec 通過任意一個文件描述符來打開文件。

$ echo Hello >foo
$ exec 3<foo 4>bar  # open files
$ cat <&3 >&4       # redirect stdin to 3, stdout to 4
$ exec 3<&- 4>&-    # close files
$ cat bar
Hello

預定義的文件描述符0-2。


在類 Unix 的工作環境中,文本處理是通過使用管道組成的標準文本處理工具鏈完成的。這是另一個重要的 Unix 創新。

這裏有一些在類 Unix 系統中經常使用到的標準文本處理工具。

如果你不確定這些命令究竟做了什麼,請使用“man command” 來自己把它搞清楚吧。

[注意] 注意

排序的順序和表示式的範圍取決於語言環境 。如果你想要獲得一個命令的傳統行為,可以在命令之前使用 “LANG=C” 讓 C 語言環境代替 UTF-8(參見 第 1.5.2 节 ““$LANG”變量”第 8.4 节 “語言環境”)。

[注意] 注意

Perl 正則表達式( perlre(1) )、Perl 兼容正則表達式(PCRE)Pythonre 模塊提供的正則表達式與一般的 ERE 相比多了許多通用的擴展。

正則表示式被使用在許多文字處理工具中。它們類似 shell 的萬用字元,但更加複雜和強大。

正則表示式描述要匹配的模式,它是由文字字元和元字元構成的。

元字符僅僅是帶有特殊含義的字符。它們有兩種主要的形式,BREERE ,使用哪種取決於上述的文本工具。


常見的 emacs 表示為基本的 BRE 但擴充為 "+" 與 "?" 做為 metacharacters 當成 ERE。因此,不需要以 "\" 在正規的表示 emacs 表示中做為逸出字元。

grep(1) 可以使用正則表達式來進行文本搜索。

嘗試下列例子

$ egrep 'GNU.*LICENSE|Yoyodyne' /usr/share/common-licenses/GPL
GNU GENERAL PUBLIC LICENSE
GNU GENERAL PUBLIC LICENSE
Yoyodyne, Inc., hereby disclaims all copyright interest in the program

下面有一個文字檔案 “DPL” ,裡面含有 2004 年以前 Debian 專案的領導者名字和起始日期,並以空格分隔。

Ian     Murdock   August  1993
Bruce   Perens    April   1996
Ian     Jackson   January 1998
Wichert Akkerman  January 1999
Ben     Collins   April   2001
Bdale   Garbee    April   2002
Martin  Michlmayr March   2003
[提示] 提示

參見 “Debian 簡史” 獲取最新的 Debian 領導階層歷史

Awk 經常被用來從這種型別的檔案中提取資料。

嘗試下列例子

$ awk '{ print $3 }' <DPL                   # month started
August
April
January
January
April
April
March
$ awk '($1=="Ian") { print }' <DPL          # DPL called Ian
Ian     Murdock   August  1993
Ian     Jackson   January 1998
$ awk '($2=="Perens") { print $3,$4 }' <DPL # When Perens started
April 1996

Shell (例如 Bash )也可以用來分析這種檔案。

嘗試下列例子

$ while read first last month year; do
    echo $month
  done <DPL
... 第一個 AWK 例子的一些輸出

內建命令 read 使用 “$IFS” (內部域分隔符)中的字元來將行分隔成多個單詞。

如果你將 “$IFS” 改變為 “:” ,你可以很好地使用 shell 來分析 “/etc/passwd”。

$ oldIFS="$IFS"   # save old value
$ IFS=':'
$ while read user password uid gid rest_of_line; do
    if [ "$user" = "bozo" ]; then
      echo "$user's ID is $uid"
    fi
  done < /etc/passwd
bozo's ID is 1000
$ IFS="$oldIFS"   # restore old value

(如果要用 Awk 做到相同的事,使用 “FS=':'” 來設定域分隔符。)

IFS 也被 shell 用來分割引數擴充套件、命令替換和算術擴充套件的結果。這不會出現在雙引號或單引號中。 IFS 的預設值為 <空格>、<tab> 和<換行符>。

請謹慎使用 shell 的 IFS 技巧。當 shell 將指令碼的一部分解釋為對它的輸入時,會發生一些奇怪的事。

$ IFS=":,"                        # use ":" and "," as IFS
$ echo IFS=$IFS,   IFS="$IFS"     # echo is a Bash builtin
IFS=  , IFS=:,
$ date -R                         # just a command output
Sat, 23 Aug 2003 08:30:15 +0200
$ echo $(date -R)                 # sub shell --> input to main shell
Sat  23 Aug 2003 08 30 36 +0200
$ unset IFS                       # reset IFS to the default
$ echo $(date -R)
Sat, 23 Aug 2003 08:30:50 +0200

下面的指令碼作為管道的一部分,可以做一些細緻的事情。


使用 find(1)xargs(1),單行 shell 指令碼能夠在多個檔案上迴圈使用,可以執行相當複雜的任務。參見 第 10.1.5 节 “查詢檔案的語法”第 9.3.9 节 “使用檔案迴圈來重複一個命令”.

當使用 shell 互動模式變得太麻煩的時候,請考慮寫一個 shell 指令碼(參見 第 12.1 节 “Shell 腳本”).