正如我們之前所討論到的,shell 在 shell 會話中維護著大量的信息,這些信息稱為 (shell) 環境。 存儲在 shell 環境中的數據被程序用來確定配置屬性。然而大多數程序用配置文件來存儲程序設置, 某些程序也會查找存儲在 shell 環境中的數值來調整他們的行為。知道了這些,我們就可以用 shell 環境 來自定制 shell 經歷。
在這一章,我們將用到以下命令:
> * printenv - 打印部分或所有的環境變量
> * set - 設置 shell 選項
> * export — 導出環境變量,讓隨后執行的程序知道。
> * alias - 創建命令別名
## 什么存儲在環境變量中?
shell 在環境中存儲了兩種基本類型的數據,雖然對于 bash 來說,很大程度上這些類型是不可 辨別的。它們是環境變量和 shell 變量。Shell 變量是由 bash 存放的少量數據,而剩下的基本上 都是環境變量。除了變量,shell 也存儲了一些可編程的數據,命名為別名和 shell 函數。我們 已經在第六章討論了別名,而 shell 函數(涉及到 shell 腳本)將會在第五部分敘述。
## 檢查環境變量
我們既可以用 bash 的內部命令 set,或者是 printenv 程序來查看什么存儲在環境當中。set 命令可以 顯示 shell 和環境變量兩者,而 printenv 只是顯示環境變量。因為環境變量內容列表相當長,所以最好 把每個命令的輸出結果管道到 less 命令:
~~~
[me@linuxbox ~]$ printenv | less
~~~
執行以上命令之后,我們應該能得到類似以下內容:
~~~
KDE_MULTIHEAD=false
SSH_AGENT_PID=6666
HOSTNAME=linuxbox
GPG_AGENT_INFO=/tmp/gpg-PdOt7g/S.gpg-agent:6689:1
SHELL=/bin/bash
TERM=xterm
XDG_MENU_PREFIX=kde-
HISTSIZE=1000
XDG_SESSION_COOKIE=6d7b05c65846c3eaf3101b0046bd2b00-1208521990.996705
-1177056199
GTK2_RC_FILES=/etc/gtk-2.0/gtkrc:/home/me/.gtkrc-2.0:/home/me/.kde/sh
are/config/gtkrc-2.0
GTK_RC_FILES=/etc/gtk/gtkrc:/home/me/.gtkrc:/home/me/.kde/share/confi
g/gtkrc
GS_LIB=/home/me/.fonts
WINDOWID=29360136
QTDIR=/usr/lib/qt-3.3
QTINC=/usr/lib/qt-3.3/include
KDE_FULL_SESSION=true
USER=me
LS_COLORS=no=00:fi=00:di=00;34:ln=00;36:pi=40;33:so=00;35:bd=40;33;01
:cd=40;33;01:or=01;05;37;41:mi=01;05;37;41:ex=00;32:\*.cmd=00;32:\*.exe:
~~~
我們所看到的是環境變量及其數值的列表。例如,我們看到一個叫做 USER 的變量,這個變量值是 “me”。printenv 命令也能夠列出特定變量的數值:
~~~
[me@linuxbox ~]$ printenv USER
me
~~~
當使用沒有帶選項和參數的 set 命令時,shell 和環境變量二者都會顯示,同時也會顯示定義的 shell 函數。不同于 printenv 命令,set 命令的輸出結果很禮貌地按照字母順序排列:
~~~
[me@linuxbox ~]$ set | less
~~~
也可以通過 echo 命令來查看一個變量的內容,像這樣:
~~~
[me@linuxbox ~]$ echo $HOME
/home/me
~~~
如果 shell 環境中的一個成員既不可用 set 命令也不可用 printenv 命令顯示,則這個變量是別名。 輸入不帶參數的 alias 命令來查看它們:
~~~
[me@linuxbox ~]$ alias
alias l.='ls -d .* --color=tty'
alias ll='ls -l --color=tty'
alias ls='ls --color=tty'
alias vi='vim'
alias which='alias | /usr/bin/which --tty-only --read-alias --show-dot --show-tilde'
~~~
## 一些有趣的變量
shell 環境中包含相當多的變量,雖然你的 shell 環境可能不同于這里展示的,但是你可能會看到 以下變量在你的 shell 環境中:
表12-1: 環境變量
| 變量 | 內容 |
|-------|--------|
| DISPLAY | 如果你正在運行圖形界面環境,那么這個變量就是你顯示器的名字。通常,它是 ":0", 意思是由 X 產生的第一個顯示器。 |
| EDITOR | 文本編輯器的名字。 |
| SHELL | shell 程序的名字。 |
| HOME | 用戶家目錄。 |
| LANG | 定義了字符集以及語言編碼方式。 |
| OLD_PWD | 先前的工作目錄。 |
| PAGER | 頁輸出程序的名字。這經常設置為/usr/bin/less。 |
| PATH | 由冒號分開的目錄列表,當你輸入可執行程序名后,會搜索這個目錄列表。 |
| PS1 | Prompt String 1\. 這個定義了你的 shell 提示符的內容。隨后我們可以看到,這個變量 內容可以全面地定制。 |
| PWD | 當前工作目錄。 |
| TERM | 終端類型名。類 Unix 的系統支持許多終端協議;這個變量設置你的終端仿真器所用的協議。 |
| TZ | 指定你所在的時區。大多數類 Unix 的系統按照協調時間時 (UTC) 來維護計算機內部的時鐘 ,然后應用一個由這個變量指定的偏差來顯示本地時間。 |
| USER | 你的用戶名 |
如果缺失了一些變量,不要擔心,這些變量會因發行版本的不同而不同。
## 如何建立 shell 環境?
當我們登錄系統后,啟動 bash 程序,并且會讀取一系列稱為啟動文件的配置腳本, 這些文件定義了默認的可供所有用戶共享的 shell 環境。然后是讀取更多位于我們自己家目錄中 的啟動文件,這些啟動文件定義了用戶個人的 shell 環境。精確的啟動順序依賴于要運行的 shell 會話 類型。有兩種 shell 會話類型:一個是登錄 shell 會話,另一個是非登錄 shell 會話。
登錄 shell 會話會提示用戶輸入用戶名和密碼;例如,我們啟動一個虛擬控制臺會話。當我們在 GUI 模式下 運行終端會話時,非登錄 shell 會話會出現。
登錄 shell 會讀取一個或多個啟動文件,正如表12-2所示:
表12-2: 登錄 shell 會話的啟動文件
| 文件 | 內容 |
|-------|---------|
| /etc/profile | 應用于所有用戶的全局配置腳本。 |
| ~/.bash_profile | 用戶私人的啟動文件。可以用來擴展或重寫全局配置腳本中的設置。 |
| ~/.bash_login | 如果文件 ~/.bash_profile 沒有找到,bash 會嘗試讀取這個腳本。 |
| ~/.profile | 如果文件 ~/.bash_profile 或文件 ~/.bash_login 都沒有找到,bash 會試圖讀取這個文件。 這是基于 Debian 發行版的默認設置,比方說 Ubuntu。 |
非登錄 shell 會話會讀取以下啟動文件:
表12-3: 非登錄 shell 會話的啟動文件
| 文件 | 內容 |
|-------|---------|
| /etc/bash.bashrc | 應用于所有用戶的全局配置文件。 |
| ~/.bashrc | 用戶私有的啟動文件。可以用來擴展或重寫全局配置腳本中的設置。 |
除了讀取以上啟動文件之外,非登錄 shell 會話也會繼承它們父進程的環境設置,通常是一個登錄 shell。
瀏覽一下你的系統,看一看系統中有哪些啟動文件。記住-因為上面列出的大多數文件名都以圓點開頭 (意味著它們是隱藏文件),你需要使用帶”-a”選項的 ls 命令。
在普通用戶看來,文件 ~/.bashrc 可能是最重要的啟動文件,因為它幾乎總是被讀取。非登錄 shell 默認 會讀取它,并且大多數登錄 shell 的啟動文件會以能讀取 ~/.bashrc 文件的方式來書寫。
## 一個啟動文件的內容
如果我們看一下典型的 .bash_profile 文件(來自于 CentOS 4 系統),它看起來像這樣:
~~~
# .bash_profile
# Get the aliases and functions
if [ -f ~/.bashrc ]; then
. ~/.bashrc
fi
# User specific environment and startup programs
PATH=$PATH:$HOME/bin
export PATH
~~~
以”#”開頭的行是注釋,shell 不會讀取它們。它們在那里是為了方便人們閱讀。第一件有趣的事情 發生在第四行,伴隨著以下代碼:
~~~
if [ -f ~/.bashrc ]; then
. ~/.bashrc
fi
~~~
這叫做一個 if 復合命令,我們將會在第五部分詳細地介紹它,現在我們對它翻譯一下:
~~~
If the file ~/.bashrc exists, then
read the ~/.bashrc file.
~~~
我們可以看到這一小段代碼就是一個登錄 shell 得到 .bashrc 文件內容的方式。在我們啟動文件中, 下一件有趣的事與 PATH 變量有關系。
曾經是否感到迷惑 shell 是怎樣知道到哪里找到我們在命令行中輸入的命令的?例如,當我們輸入 ls 后, shell 不會查找整個計算機系統,來找到 /bin/ls(ls 命令的絕對路徑名),而是,它查找一個目錄列表, 這些目錄包含在 PATH 變量中。
PATH 變量經常(但不總是,依賴于發行版)在 /etc/profile 啟動文件中設置,通過這些代碼:
~~~
PATH=$PATH:$HOME/bin
~~~
修改 PATH 變量,添加目錄 $HOME/bin 到目錄列表的末尾。這是一個參數展開的實例, 參數展開我們在第八章中提到過。為了說明這是怎樣工作的,試試下面的例子:
~~~
[me@linuxbox ~]$ foo="This is some"
[me@linuxbox ~]$ echo $foo
This is some
[me@linuxbox ~]$ foo="$foo text."
[me@linuxbox ~]$ echo $foo
This is some text.
~~~
使用這種技巧,我們可以把文本附加到一個變量值的末尾。通過添加字符串 $HOME/bin 到 PATH 變量值 的末尾,則目錄 $HOME/bin 就添加到了命令搜索目錄列表中。這意味著當我們想要在自己的家目錄下, 創建一個目錄來存儲我們自己的私人程序時,shell 已經給我們準備好了。我們所要做的事就是 把創建的目錄叫做 bin,趕快行動吧。
注意:很多發行版默認地提供了這個 PATH 設置。一些基于 Debian 的發行版,例如 Ubuntu,在登錄 的時候,會檢測目錄 ~/bin 是否存在,若找到目錄則把它動態地加到 PATH 變量中。
最后,有下面一行代碼:
~~~
export PATH
~~~
這個 export 命令告訴 shell 讓這個 shell 的子進程可以使用 PATH 變量的內容。
## 修改 shell 環境
既然我們知道了啟動文件所在的位置和它們所包含的內容,我們就可以修改它們來定制自己的 shell 環境。
## 我們應該修改哪個文件?
按照通常的規則,添加目錄到你的 PATH 變量或者是定義額外的環境變量,要把這些更改放置到 .bash_profile 文件中(或者其替代文件中,根據不同的發行版。例如,Ubuntu 使用 .profile 文件)。 對于其它的更改,要放到 .bashrc 文件中。除非你是系統管理員,需要為系統中的所有用戶修改 默認設置,那么則限定你只能對自己家目錄下的文件進行修改。當然,有可能會更改 /etc 目錄中的 文件,比如說 profile 文件,而且在許多情況下,修改這些文件也是明智的,但是現在,我們要 安全起見。
## 文本編輯器
為了編輯(例如,修改)shell 的啟動文件,還有系統中大多數其它配置文件,我們使用一個叫做文本 編輯器的程序。文件編輯器是一個,在某些方面,類似于文字處理器的程序,比如說隨著鼠標的移動, 它允許你在屏幕上編輯文字。只有一點,文本編輯器不同于文字處理器,就是它只能支持純文本,并且 經常包含為便于寫程序而設計的特性。文本編輯器是軟件開發人員用來寫代碼,和系統管理原員用來管理 系統配置文件的重要工具。
Linux 系統有許多不同類型的文本編輯器可用;你的系統中可能已經安裝了幾個。為什么會有這么 多種呢?可能因為程序員喜歡編寫它們,又因為程序員們會頻繁地使用它們,所以程序員編寫編輯器讓 它們按照程序員自己的愿望工作。
文本編輯器分為兩種基本類型:圖形化的和基于文本的編輯器。GNOME 和 KDE 兩者都包含一些流行的 圖形編輯器。GNOME 自帶了一個叫做 gedit 的編輯器,這個編輯器通常在 GNOME 菜單中稱為”文本編輯器”。 KDE 通常自帶了三種編輯器,分別是(按照復雜度遞增的順序排列)kedit,kwrite,kate。
有許多基于文本的編輯器。你將會遇到一些流行的編輯器,它們是 nano,vi,和 emacs。這個 nano 編輯器 是一個簡單的,容易使用的編輯器,它是 pico 編輯器的替代物,pico 編輯器由 PINE 郵件套件提供。vi 編輯器 (在大多數 Linux 系統中被 vim 替代,vim 是 “Vi IMproved”的簡寫)是類 Unix 操作系統的傳統編輯器。 vim 是我們下一章節的討論對象。emacs 編輯器最初由 Richard Stallman 寫成。emacs 是一個龐大的,多用途的, 可做任何事情的編程環境。雖然 emacs 很容易獲取,但是大多數 Linux 系統很少默認安裝它。
## 使用文本編輯器
所有的文本編輯器都可以通過在命令行中輸入編輯器的名字,加上你所想要編輯的文件來喚醒。如果所 輸入的文件名不存在,編輯器則會假定你想要創建一個新文件。下面是一個使用 gedit 的例子:
~~~
[me@linuxbox ~]$ gedit some_file
~~~
這條命令將會啟動 gedit 文本編輯器,同時加載名為 “some_file” 的文件,如果這個文件存在的話。
所有的圖形文本編輯器都相當不言自明的,所以我們在這里不會介紹它們。反之,我們將集中精力在 我們第一個基于文本的文本編輯器,nano。讓我們啟動 nano,并且編輯文件 .bashrc。但是在我們這樣 做之前,先練習一些”安全計算”。當我們編輯一個重要的配置文件時,首先創建一個這個文件的備份 總是一個不錯的主意。這樣能避免我們在編輯文件時弄亂文件。創建文件 .bashrc 的備份文件,這樣做:
~~~
[me@linuxbox ~]$ cp .bashrc .bashrc.bak
~~~
備份文件的名字無關緊要,只要選擇一個容易理解的文件名。擴展名 “.bak”,”.sav”, “.old”,和 “.orig” 都是用來指示備份文件的流行方法。哦,記住 cp 命令會默默地重寫存在的文件。
現在我們有了一個備份文件,我們啟動 nano 編輯器吧:
~~~
[me@linuxbox ~]$ nano .bashrc
~~~
一旦 nano 編輯器啟動后,我們將會得到一個像下面一樣的屏幕:
~~~
GNU nano 2.0.3
....
~~~
注意:如果你的系統中沒有安裝 nano 編輯器,你可以用一個圖形化的編輯器代替。
這個屏幕由上面的標頭,中間正在編輯的文件文本和下面的命令菜單組成。因為設計 nano 是為了 代替由電子郵件客戶端提供的編輯器的,所以它相當缺乏編輯特性。在任一款編輯器中,你應該 學習的第一個命令是怎樣退出程序。以 nano 為例,你輸入 Ctrl-x 來退出 nano。在屏幕底層的菜單中 說明了這個命令。”^X” 表示法意思是 Ctrl-x。這是控制字符的常見表示法,許多程序都使用它。
第二個我們需要知道的命令是怎樣保存我們的勞動成果。對于 nano 來說是 Ctrl-o。盡然我們 已經獲得了這些知識,接下來我們準備做些編輯工作。使用下箭頭按鍵和 / 或下翻頁按鍵,移動 鼠標到文件的最后一行,然后添加以下幾行到文件 .bashrc 中:
~~~
umask 0002
export HISTCONTROL=ignoredups
export HISTSIZE=1000
alias l.='ls -d .* --color=auto'
alias ll='ls -l --color=auto'
~~~
注意:你的發行版可能已經包含其中的一些行,但是復制沒有任何傷害。
下表是所添加行的意義:
表12-4:
| 文本行 | 含義 |
|-------|---------|
| umask 0002 | 設置掩碼來解決共享目錄的問題。 |
| export HISTCONTROL=ignoredups | 使得 shell 的歷史記錄功能忽略一個命令,如果相同的命令已被記錄。 |
| export HISTSIZE=1000 | 增加命令歷史的大小,從默認的 500 行擴大到 1000 行。 |
| alias l.='ls -d .* --color=auto' | 創建一個新命令,叫做'l.',這個命令會顯示所有以點開頭的目錄項。 |
| alias ll='ls -l --color=auto' | 創建一個叫做'll'的命令,這個命令會顯示長格式目錄列表。 |
正如我們所看到的,我們的許多附加物意思直覺上并不是明顯的,所以添加注釋到我們的文件 .bashrc 中是 一個好主意,可以幫助人們理解。使用編輯器,更改我們的附加物,讓它們看起來像這樣:
~~~
# Change umask to make directory sharing easier
umask 0002
# Ignore duplicates in command history and increase
# history size to 1000 lines
export HISTCONTROL=ignoredups
export HISTSIZE=1000
# Add some helpful aliases
alias l.='ls -d .* --color=auto'
alias ll='ls -l --color=auto'
~~~
啊,看起來好多了! 當我們完成修改后,輸入 Ctrl-o 來保存我們修改的 .bashrc 文件,輸入 Ctrl-x 退出 nano。
> 為什么注釋很重要?
>
> 不管什么時候你修改配置文件時,給你所做的更改加上注釋都是一個好主意。的確,明天你會 記得你修改了的內容,但是六個月之后會怎樣呢?幫自己一個忙,加上一些注釋吧。當你意識 到這一點后,對你所做的修改做個日志是個不錯的主意。
>
> Shell 腳本和 bash 啟動文件都使用 “#” 符號來開始注釋。其它配置文件可能使用其它的符號。 大多數配置文件都有注釋。把它們作為指南。
>
> 你會經常看到配置文件中的一些行被注釋掉,以此防止它們被受影響的程序使用。這樣做 是為了給讀者在可能的配置選項方面一些建議,或者給出正確的配置語法實例。例如,Ubuntu 8.04 中的 .bashrc 文件包含這些行:
>
> ~~~
> # some more ls aliases
> #alias ll='ls -l'
> #alias la='ls -A'
> #alias l='ls -CF'
>
> ~~~
>
> 最后三行是有效的被注釋掉的別名定義。如果你刪除這三行開頭的 “#” 符號,此技術程稱為 uncommenting (不注釋),這樣你就會激活這些別名。相反地,如果你在一行的開頭加上 “#” 符號, 你可以注銷掉這一行,但會保留它所包含的信息。
## 激活我們的修改
我們對于文件 .bashrc 的修改不會生效,直到我們關閉終端會話,再重新啟動一個新的會話, 因為 .bashrc 文件只是在剛開始啟動終端會話時讀取。然而,我們可以強迫 bash 重新讀取修改過的 .bashrc 文件,使用下面的命令:
~~~
[me@linuxbox ~]$ source .bashrc
~~~
運行上面命令之后,我們就應該能夠看到所做修改的效果了。試試其中一個新的別名:
~~~
[me@linuxbox ~]$ ll
~~~
## 總結
在這一章中,我們學到了用文本編輯器來編輯配置文件的必要技巧。隨著繼續學習,當我們 讀到命令的手冊頁時,記錄下命令所支持的環境變量。可能會有一個或兩個寶貝。在隨后的章節 里面,我們將會學習 shell 函數,一個很強大的特性,你可以把它包含在 bash 啟動文件里面,以此 來添加你自定制的命令寶庫。
## 拓展閱讀
bash 手冊頁的 INVOCATION 部分非常詳細地討論了 bash 啟動文件。
- 第一章:引言
- 第二章:什么是shell
- 第三章:文件系統中跳轉
- 第四章:研究操作系統
- 第五章:操作文件和目錄
- 第六章:使用命令
- 第七章:重定向
- 第八章:從shell眼中看世界
- 第九章:鍵盤高級操作技巧
- 第十章:權限
- 第十一章:進程
- 第十二章:shell環境
- 第十三章:VI簡介
- 第十四章:自定制shell提示符
- 第十五章:軟件包管理
- 第十六章:存儲媒介
- 第十七章:網絡系統
- 第十八章:查找文件
- 第十九章:歸檔和備份
- 第二十章:正則表達式
- 第二十一章:文本處理
- 第二十二章:格式化輸出
- 第二十三章:打印
- 第二十四章:編譯程序
- 第二十五章:編寫第一個shell腳本
- 第二十六章:啟動一個項目
- 第二十七章:自頂向下設計
- 第二十八章:流程控制 if分支結構
- 第二十九章:讀取鍵盤輸入
- 第三十章:流程控制 while/until 循環
- 第三十一章:疑難排解
- 第三十二章:流程控制 case分支
- 第三十三章:位置參數
- 第三十四章:流程控制 for循環
- 第三十五章:字符串和數字
- 第三十六章:數組
- 第三十七章:奇珍異寶