正如我們之前所討論到的,shell 在 shell 會話中維護著大量的信息,這些信息稱為 (shell) 環(huán)境。 存儲在 shell 環(huán)境中的數(shù)據(jù)被程序用來確定配置屬性。然而大多數(shù)程序用配置文件來存儲程序設置, 某些程序也會查找存儲在 shell 環(huán)境中的數(shù)值來調(diào)整他們的行為。知道了這些,我們就可以用 shell 環(huán)境 來自定制 shell 經(jīng)歷。
在這一章,我們將用到以下命令:
printenv - 打印部分或所有的環(huán)境變量
set - 設置 shell 選項
export — 導出環(huán)境變量,讓隨后執(zhí)行的程序知道。
shell 在環(huán)境中存儲了兩種基本類型的數(shù)據(jù),雖然對于 bash 來說,很大程度上這些類型是不可 辨別的。它們是環(huán)境變量和 shell 變量。Shell 變量是由 bash 存放的少量數(shù)據(jù),而剩下的基本上 都是環(huán)境變量。除了變量,shell 也存儲了一些可編程的數(shù)據(jù),命名為別名和 shell 函數(shù)。我們 已經(jīng)在第六章討論了別名,而 shell 函數(shù)(涉及到 shell 腳本)將會在第五部分敘述。
我們既可以用 bash 的內(nèi)部命令 set,或者是 printenv 程序來查看什么存儲在環(huán)境當中。set 命令可以 顯示 shell 和環(huán)境變量兩者,而 printenv 只是顯示環(huán)境變量。因為環(huán)境變量內(nèi)容列表相當長,所以最好 把每個命令的輸出結(jié)果管道到 less 命令:
[me@linuxbox ~]$ printenv | less
執(zhí)行以上命令之后,我們應該能得到類似以下內(nèi)容:
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:
我們所看到的是環(huán)境變量及其數(shù)值的列表。例如,我們看到一個叫做 USER 的變量,這個變量值是 "me"。printenv 命令也能夠列出特定變量的數(shù)值:
[me@linuxbox ~]$ printenv USER
me
當使用沒有帶選項和參數(shù)的 set 命令時,shell 和環(huán)境變量二者都會顯示,同時也會顯示定義的 shell 函數(shù)。不同于 printenv 命令,set 命令的輸出結(jié)果很禮貌地按照字母順序排列:
[me@linuxbox ~]$ set | less
也可以通過 echo 命令來查看一個變量的內(nèi)容,像這樣:
[me@linuxbox ~]$ echo $HOME
/home/me
如果 shell 環(huán)境中的一個成員既不可用 set 命令也不可用 printenv 命令顯示,則這個變量是別名。 輸入不帶參數(shù)的 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 環(huán)境中包含相當多的變量,雖然你的 shell 環(huán)境可能不同于這里展示的,但是你可能會看到 以下變量在你的 shell 環(huán)境中:
變量 | 內(nèi)容 |
---|---|
DISPLAY | 如果你正在運行圖形界面環(huán)境,那么這個變量就是你顯示器的名字。通常,它是 ":0", 意思是由 X 產(chǎn)生的第一個顯示器。 |
EDITOR | 文本編輯器的名字。 |
SHELL | shell 程序的名字。 |
HOME | 用戶家目錄。 |
LANG | 定義了字符集以及語言編碼方式。 |
OLD_PWD | 先前的工作目錄。 |
PAGER | 頁輸出程序的名字。這經(jīng)常設置為/usr/bin/less。 |
PATH | 由冒號分開的目錄列表,當你輸入可執(zhí)行程序名后,會搜索這個目錄列表。 |
PS1 | Prompt String 1. 這個定義了你的 shell 提示符的內(nèi)容。隨后我們可以看到,這個變量 內(nèi)容可以全面地定制。 |
PWD | 當前工作目錄。 |
TERM | 終端類型名。類 Unix 的系統(tǒng)支持許多終端協(xié)議;這個變量設置你的終端仿真器所用的協(xié)議。 |
TZ | 指定你所在的時區(qū)。大多數(shù)類 Unix 的系統(tǒng)按照協(xié)調(diào)時間時 (UTC) 來維護計算機內(nèi)部的時鐘 ,然后應用一個由這個變量指定的偏差來顯示本地時間。 |
USER | 你的用戶名 |
如果缺失了一些變量,不要擔心,這些變量會因發(fā)行版本的不同而不同。
當我們登錄系統(tǒng)后,啟動 bash 程序,并且會讀取一系列稱為啟動文件的配置腳本, 這些文件定義了默認的可供所有用戶共享的 shell 環(huán)境。然后是讀取更多位于我們自己家目錄中 的啟動文件,這些啟動文件定義了用戶個人的 shell 環(huán)境。精確的啟動順序依賴于要運行的 shell 會話 類型。有兩種 shell 會話類型:一個是登錄 shell 會話,另一個是非登錄 shell 會話。
登錄 shell 會話會提示用戶輸入用戶名和密碼;例如,我們啟動一個虛擬控制臺會話。當我們在 GUI 模式下 運行終端會話時,非登錄 shell 會話會出現(xiàn)。
登錄 shell 會讀取一個或多個啟動文件,正如表12-2所示:
文件 | 內(nèi)容 |
---|---|
/etc/profile | 應用于所有用戶的全局配置腳本。 |
~/.bash_profile | 用戶私人的啟動文件。可以用來擴展或重寫全局配置腳本中的設置。 |
~/.bash_login | 如果文件 ~/.bash_profile 沒有找到,bash 會嘗試讀取這個腳本。 |
~/.profile | 如果文件 ~/.bash_profile 或文件 ~/.bash_login 都沒有找到,bash 會試圖讀取這個文件。 這是基于 Debian 發(fā)行版的默認設置,比方說 Ubuntu。 |
非登錄 shell 會話會讀取以下啟動文件:
文件 | 內(nèi)容 |
---|---|
/etc/bash.bashrc | 應用于所有用戶的全局配置文件。 |
~/.bashrc | 用戶私有的啟動文件??梢杂脕頂U展或重寫全局配置腳本中的設置。 |
除了讀取以上啟動文件之外,非登錄 shell 會話也會繼承它們父進程的環(huán)境設置,通常是一個登錄 shell。
瀏覽一下你的系統(tǒng),看一看系統(tǒng)中有哪些啟動文件。記住-因為上面列出的大多數(shù)文件名都以圓點開頭 (意味著它們是隱藏文件),你需要使用帶"-a"選項的 ls 命令。
在普通用戶看來,文件 ~/.bashrc 可能是最重要的啟動文件,因為它幾乎總是被讀取。非登錄 shell 默認 會讀取它,并且大多數(shù)登錄 shell 的啟動文件會以能讀取 ~/.bashrc 文件的方式來書寫。
如果我們看一下典型的 .bash_profile 文件(來自于 CentOS 4 系統(tǒng)),它看起來像這樣:
# .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 不會讀取它們。它們在那里是為了方便人們閱讀。第一件有趣的事情 發(fā)生在第四行,伴隨著以下代碼:
if [ -f ~/.bashrc ]; then
. ~/.bashrc
fi
這叫做一個 if 復合命令,我們將會在第五部分詳細地介紹它,現(xiàn)在我們對它翻譯一下:
If the file ~/.bashrc exists, then
read the ~/.bashrc file.
我們可以看到這一小段代碼就是一個登錄 shell 得到 .bashrc 文件內(nèi)容的方式。在我們啟動文件中, 下一件有趣的事與 PATH 變量有關系。
曾經(jīng)是否感到迷惑 shell 是怎樣知道到哪里找到我們在命令行中輸入的命令的?例如,當我們輸入 ls 后, shell 不會查找整個計算機系統(tǒng),來找到 /bin/ls(ls 命令的絕對路徑名),而是,它查找一個目錄列表, 這些目錄包含在 PATH 變量中。
PATH 變量經(jīng)常(但不總是,依賴于發(fā)行版)在 /etc/profile 啟動文件中設置,通過這些代碼:
PATH=$PATH:$HOME/bin
修改 PATH 變量,添加目錄 $HOME/bin 到目錄列表的末尾。這是一個參數(shù)展開的實例, 參數(shù)展開我們在第八章中提到過。為了說明這是怎樣工作的,試試下面的例子:
[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 就添加到了命令搜索目錄列表中。這意味著當我們想要在自己的家目錄下, 創(chuàng)建一個目錄來存儲我們自己的私人程序時,shell 已經(jīng)給我們準備好了。我們所要做的事就是 把創(chuàng)建的目錄叫做 bin,趕快行動吧。
注意:很多發(fā)行版默認地提供了這個 PATH 設置。一些基于 Debian 的發(fā)行版,例如 Ubuntu,在登錄 的時候,會檢測目錄 ~/bin 是否存在,若找到目錄則把它動態(tài)地加到 PATH 變量中。
最后,有下面一行代碼:
export PATH
這個 export 命令告訴 shell 讓這個 shell 的子進程可以使用 PATH 變量的內(nèi)容。
既然我們知道了啟動文件所在的位置和它們所包含的內(nèi)容,我們就可以修改它們來定制自己的 shell 環(huán)境。
按照通常的規(guī)則,添加目錄到你的 PATH 變量或者是定義額外的環(huán)境變量,要把這些更改放置到 .bash_profile 文件中(或者其替代文件中,根據(jù)不同的發(fā)行版。例如,Ubuntu 使用 .profile 文件)。 對于其它的更改,要放到 .bashrc 文件中。除非你是系統(tǒng)管理員,需要為系統(tǒng)中的所有用戶修改 默認設置,那么則限定你只能對自己家目錄下的文件進行修改。當然,有可能會更改 /etc 目錄中的 文件,比如說 profile 文件,而且在許多情況下,修改這些文件也是明智的,但是現(xiàn)在,我們要 安全起見。
為了編輯(例如,修改)shell 的啟動文件,還有系統(tǒng)中大多數(shù)其它配置文件,我們使用一個叫做文本 編輯器的程序。文件編輯器是一個,在某些方面,類似于文字處理器的程序,比如說隨著鼠標的移動, 它允許你在屏幕上編輯文字。只有一點,文本編輯器不同于文字處理器,就是它只能支持純文本,并且 經(jīng)常包含為便于寫程序而設計的特性。文本編輯器是軟件開發(fā)人員用來寫代碼,和系統(tǒng)管理原員用來管理 系統(tǒng)配置文件的重要工具。
Linux 系統(tǒng)有許多不同類型的文本編輯器可用;你的系統(tǒng)中可能已經(jīng)安裝了幾個。為什么會有這么 多種呢?可能因為程序員喜歡編寫它們,又因為程序員們會頻繁地使用它們,所以程序員編寫編輯器讓 它們按照程序員自己的愿望工作。
文本編輯器分為兩種基本類型:圖形化的和基于文本的編輯器。GNOME 和 KDE 兩者都包含一些流行的 圖形編輯器。GNOME 自帶了一個叫做 gedit 的編輯器,這個編輯器通常在 GNOME 菜單中稱為"文本編輯器"。 KDE 通常自帶了三種編輯器,分別是(按照復雜度遞增的順序排列)kedit,kwrite,kate。
有許多基于文本的編輯器。你將會遇到一些流行的編輯器,它們是 nano,vi,和 emacs。這個 nano 編輯器 是一個簡單的,容易使用的編輯器,它是 pico 編輯器的替代物,pico 編輯器由 PINE 郵件套件提供。vi 編輯器 (在大多數(shù) Linux 系統(tǒng)中被 vim 替代,vim 是 "Vi IMproved"的簡寫)是類 Unix 操作系統(tǒng)的傳統(tǒng)編輯器。 vim 是我們下一章節(jié)的討論對象。emacs 編輯器最初由 Richard Stallman 寫成。emacs 是一個龐大的,多用途的, 可做任何事情的編程環(huán)境。雖然 emacs 很容易獲取,但是大多數(shù) Linux 系統(tǒng)很少默認安裝它。
所有的文本編輯器都可以通過在命令行中輸入編輯器的名字,加上你所想要編輯的文件來喚醒。如果所 輸入的文件名不存在,編輯器則會假定你想要創(chuàng)建一個新文件。下面是一個使用 gedit 的例子:
[me@linuxbox ~]$ gedit some_file
這條命令將會啟動 gedit 文本編輯器,同時加載名為 "some_file" 的文件,如果這個文件存在的話。
所有的圖形文本編輯器都相當不言自明的,所以我們在這里不會介紹它們。反之,我們將集中精力在 我們第一個基于文本的文本編輯器,nano。讓我們啟動 nano,并且編輯文件 .bashrc。但是在我們這樣 做之前,先練習一些"安全計算"。當我們編輯一個重要的配置文件時,首先創(chuàng)建一個這個文件的備份 總是一個不錯的主意。這樣能避免我們在編輯文件時弄亂文件。創(chuàng)建文件 .bashrc 的備份文件,這樣做:
[me@linuxbox ~]$ cp .bashrc .bashrc.bak
備份文件的名字無關緊要,只要選擇一個容易理解的文件名。擴展名 ".bak",".sav", ".old",和 ".orig" 都是用來指示備份文件的流行方法。哦,記住 cp 命令會默默地重寫存在的文件。
現(xiàn)在我們有了一個備份文件,我們啟動 nano 編輯器吧:
[me@linuxbox ~]$ nano .bashrc
一旦 nano 編輯器啟動后,我們將會得到一個像下面一樣的屏幕:
GNU nano 2.0.3
....
注意:如果你的系統(tǒng)中沒有安裝 nano 編輯器,你可以用一個圖形化的編輯器代替。
這個屏幕由上面的標頭,中間正在編輯的文件文本和下面的命令菜單組成。因為設計 nano 是為了 代替由電子郵件客戶端提供的編輯器的,所以它相當缺乏編輯特性。在任一款編輯器中,你應該 學習的第一個命令是怎樣退出程序。以 nano 為例,你輸入 Ctrl-x 來退出 nano。在屏幕底層的菜單中 說明了這個命令。"^X" 表示法意思是 Ctrl-x。這是控制字符的常見表示法,許多程序都使用它。
第二個我們需要知道的命令是怎樣保存我們的勞動成果。對于 nano 來說是 Ctrl-o。盡然我們 已經(jīng)獲得了這些知識,接下來我們準備做些編輯工作。使用下箭頭按鍵和 / 或下翻頁按鍵,移動 鼠標到文件的最后一行,然后添加以下幾行到文件 .bashrc 中:
umask 0002
export HISTCONTROL=ignoredups
export HISTSIZE=1000
alias l.='ls -d .* --color=auto'
alias ll='ls -l --color=auto'
注意:你的發(fā)行版可能已經(jīng)包含其中的一些行,但是復制沒有任何傷害。
下表是所添加行的意義:
文本行 | 含義 |
---|---|
umask 0002 | 設置掩碼來解決共享目錄的問題。 |
export HISTCONTROL=ignoredups | 使得 shell 的歷史記錄功能忽略一個命令,如果相同的命令已被記錄。 |
export HISTSIZE=1000 | 增加命令歷史的大小,從默認的 500 行擴大到 1000 行。 |
alias l.='ls -d .* --color=auto' | 創(chuàng)建一個新命令,叫做'l.',這個命令會顯示所有以點開頭的目錄項。 |
alias ll='ls -l --color=auto' | 創(chuàng)建一個叫做'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。
為什么注釋很重要?
不管什么時候你修改配置文件時,給你所做的更改加上注釋都是一個好主意。的確,明天你會 記得你修改了的內(nèi)容,但是六個月之后會怎樣呢?幫自己一個忙,加上一些注釋吧。當你意識 到這一點后,對你所做的修改做個日志是個不錯的主意。
Shell 腳本和 bash 啟動文件都使用 "#" 符號來開始注釋。其它配置文件可能使用其它的符號。 大多數(shù)配置文件都有注釋。把它們作為指南。
你會經(jīng)??吹脚渲梦募械囊恍┬斜蛔⑨尩簦源朔乐顾鼈儽皇苡绊懙某绦蚴褂?。這樣做 是為了給讀者在可能的配置選項方面一些建議,或者給出正確的配置語法實例。例如,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
在這一章中,我們學到了用文本編輯器來編輯配置文件的必要技巧。隨著繼續(xù)學習,當我們 讀到命令的手冊頁時,記錄下命令所支持的環(huán)境變量。可能會有一個或兩個寶貝。在隨后的章節(jié) 里面,我們將會學習 shell 函數(shù),一個很強大的特性,你可以把它包含在 bash 啟動文件里面,以此 來添加你自定制的命令寶庫。
bash 手冊頁的 INVOCATION 部分非常詳細地討論了 bash 啟動文件。