您好,登錄后才能下訂單哦!
Pixel, Byte, and Comma的軟件開發者Martin Streicher 在本文中為我們揭示了UNIX高手的秘密。Martin Streicher 是一位 Ruby on Rails 的自由開發人員和 Linux Magazine 的前任主編。Martin 畢業于 Purdue University 并獲得計算機科學學位,從 1986 年起他一直從事 UNIX 類系統的編程工作。他喜歡收集藝術品和玩具。
保存環境變量
大多數 UNIX 用戶在 .bashrc(針對 Bash shell)和 .zshrc(針對 Z shell)等 shell 啟動文件中塞滿大量用戶設置,以便一次又一次地重建鐘愛的 shell 環境。啟動文件能夠創建別名、設置 shell 選項、創建函數、以及設置環境變量。關鍵的環境變量包括 HOME(指向您的主目錄)、PATH(列舉從中搜索應用程序的目錄)和 MANPATH(列舉從中搜索手冊頁的目錄)。要查看您的 shell 中設置了哪些環境變量,鍵入 printenv 命令。查閱 shell 手冊頁,獲取可用環境變量的完整列表。
與 shell 一樣,可以通過環境變量定制其他許多 UNIX 應用程序。例如,Java 子系統要求定義 JAVA_HOME 來指向 Java 運行時的根。同樣,Amazon Web Services (AWS) 實用程序套件強制使用 AWS_CREDENTIAL_FILE 來指向一個包含有效私匙憑證的文件。單獨的應用程序也提供環境變量,關鍵是如何發現這些變量。幸運的是,這種工作不需要非法***;相反,只需查詢手邊的實用工具手冊頁,查找標題為 “Environment Variables” 的章節即可。
例如,分頁實用程序 less 定義了幾個有用的環境變量:
◆環境變量 LESS 存儲一些命令行選項,以在您每次調用該分頁程序時減少鍵入量。例如,如果您需要閱讀大量日志文件,可將以下語句添加到一個 shell 啟動文件中:
export LESS='--RAW-CONTROL-CHARACTERS --squeeze-lines --ignore-case'
上述選項將分別解譯控制字符(通常是語法著色),將多個空行壓縮為一行,并忽略字符串匹配中的大小寫。如果您使用代碼,可嘗試以下選項:
export LESS='--LINE-NUMBERS --quit-if-one-screen --quit-on-intr'
◆名為 LESSKEY 的環境設置指向一個密匙綁定文件。可以使用密匙綁定來定制 less 的行為,比如,匹配另一個頁面或編輯器的行為。
◆與 shell 一樣,less 能保留多個調用之間的歷史。設置 LESSHISTFILE 和 LESSHISTSIZE 分別指向一個持久命令文件和設置要記錄的命令的最大條數。
GNU Compiler Collection (GCC) 是另一個典型的環境變量應用示例。GCC 定義各種環境變量來定制其操作。LIBRARY_PATH,顧名思義,是一個目錄列表,用于搜索要鏈接到的庫;COMPILER_PATH 的工作方式與 shell 的 PATH 非常相似,但是由 GCC 在內部使用,用于查找編譯過程中使用的子程序。
如果您針對單個平臺寫代碼并構建二進制文件,您可能永遠也不會用到這些環境變量,但是,如果您跨平臺交叉編譯相同的代碼,那么這些變量對于訪問每個平臺的不同的頭部和庫至關重要。您可以將這些變量設置為不同的值集合,一個集合針對一種機器,而另一個集合針對另一種風格的系統。
事實上,您可以從 GCC 獲得一個暗示:可以為每個應用程序維護多個環境變量集合,根據手邊的工作從一個集合切換到另一個集合。一種方法是在每個項目目錄中保存一個環境初始化文件并根據需要source 它。例如,許多 Ruby 開發人員使用這種方法來在不同的 Ruby 版本間切換,根據需要更改環境變量 PATH、GEM_HOME 和 GEM_PATH,從一個版本跳到另一個版本。
“點綴” 環境
與環境變量非常相似的是,許多 Linux和 UNIX 應用程序都提供一個點 文件 — 文件名以圓點開始的小文件 — 來進行定制。與環境變量不同的是:環境變量采集少量標記和相對較少的信息量,而點文件可能更廣泛、更復雜,擁有自己獨特的語法規則、甚至自己的編程語言。點文件是保存選項和設置的理想位置,因為(根據 UNIX 傳統)以一個圓點開始的文件名不會出現在標準的目錄清單中。(使用 ls -a 來查看這些所謂的隱藏文件。)點文件是純文本文件,只是文件名比較特別而已。
點文件通常位于您的主目錄內,但有些實用程序也在當前工作目錄中查找點文件。如果一個應用程序支持多個點文件,則該程序通常應用于優先規則,來表明一個文件比另一個文件優先。通常,“本地” 點文件 — 位于當前工作目錄 — 優先級最高,然后是主目錄中的點文件,最后是一個系統范圍配置文件。這些文件可以全部存在,也可以存在一個,或者都不存在,這取決于應用程序將這些文件視為互斥的還是遞增的。在第一種情況下,優先鏈中第一個點文件的優先權是不容置疑的。在后一種情況下,配置可以級聯或融解到最終結果中。
less 的密匙綁定文件是一個簡單點文件示例,位于 $HOME/.lesskey 中。文件中的每一行都是一對(一個按鍵和一條命令),如下所示:
\r forw-line
\n forw-line
e forw-line
j forw-line
^E forw-line
^N forw-line
k back-line
y back-line
^Y back-line
fetchmail 是比較復雜的點文件示例。這個實用程序在本地從多個遠程源提取電子郵件并傳送消息。這個實用程序的操作只通過 $HOME/.fetchmailrc 控制。(參見手冊頁了解它的眾多選項。)cron、git、vi,以及其他許多命令都能識別點文件。同樣,請閱讀這個應用程序的手冊頁,了解可以在點文件中配置的內容。有些點文件內容豐富,足以占用一個單獨的手冊頁,比如 crontab。
噓……關于 SSH 的秘密
Secure Shell (SSH) 是一個功能強大的子系統,用于安全地登錄到遠程系統、復制文件并穿越防火墻。由于 SSH 是一個子系統,它提供大量選項來定制和簡化其操作。事實上,SSH 提供名為 $HOME/.ssh 的整個 “點目錄” 來包含其所有數據。(您的 .ssh 目錄必須是模式 600,以阻止他人訪問。非 600 模式將干擾正常的操作。)特別是,文件 $HOME/.ssh/config 可以定義大量快捷方式,包括機器名稱的別名、每主機訪問控制等。
下面是位于 $HOME/.ssh/config 中的一個典型代碼塊,用于定制一個特定主機的 SSH:
Host worker
HostName worker.example.com
IdentityFile ~/.ssh/id_rsa_worker
User joeuser
~/.ssh/config 中的每個塊配置一個或多個主機。不同的塊使用一個空行分隔。這個塊使用 4 個選項:Host、HostName、IdentityFile 和 User。Host 為 HostName 指定的機器創建一個昵稱。昵稱允許您鍵入 ssh worker,而不是 ssh worker.example.com。另外,IdentityFile 和 User 選項指定如何登錄到 worker。前者指向此主機使用的一個私匙,后者提供登錄 ID。這樣,這個代碼塊就等同于以下命令:
ssh -i ~/.ssh/id_rsa_worker
ControlMaster 是一個鮮為人知的強大選項。如果設置,同一個主機的多個 SSH 會話將共享單個連接。一旦第一個連接建立,后續連接就不再需要憑證,從而消除了每次連接同一機器都需要鍵入密碼的麻煩。ControlMaster 非常方便,您可能愿意為每臺機器啟用它。啟用方法非常簡單,只需使用主機通配符 *:
Host *
ControlMaster auto
ControlPath ~/.ssh/master-%r@%h:%p
如您所料,標記了 Host * 的塊將應用到每個主機,甚至是那些在配置文件中沒有明確指定的主機。ControlMaster auto 嘗試使用一個現有連接,并在沒有發現共享連接時創建一個新連接。ControlPath 指向一個文件,以便持久化一個控制套接字以供共享。%r 用遠程登錄用戶名替換,%h 用目標主機名替換,%p 代替連接使用的端口。(您還可以使用 %l,它使用本地主機名替換。)上述規范使用類似于下面的文件名創建控制套接字:
:22
當到遠程主機的所有連接都被切斷時,每個控制套接字都就會被移除。如果您想隨時了解連接到了哪些主機,只需鍵入 ls ~/.ssh 并查看控制套接字的主機名部分(%h)。
SSH 配置文件非常大,它也有自己的手冊頁。鍵入 man ssh_config 查看所有可能的選項。這里有一個巧妙的 SSH 技巧:可以通過 SSH 從本地系統進入遠程系統。要用到的命令行如下所示:
$ ssh example.com -L 5000:localhost:3306
這條命令的意思是:通過 example.com 進行連接,并在本地機器上的端口 5000 和名為 “localhost” 的機器上的端口 3306(MySQL 服務器端口)之間建立一條通道。由于 localhost 在 example.com 上解釋(因為通道已建立),因此 localhost 就是 example.com。由于出站通道 — 以前稱為本地轉發(local forward)— 已建立,本地客戶端能夠連接到端口 5000,并與 example.com 上運行的 MySQL 服務器通信。
通道創建的常規形式如下:
$ ssh proxyhost
localport:targethost:targetport
其中,proxyhost 是可以通過 SSH 訪問的機器,并且擁有一個到 targethost 的網絡連接(不通過 SSH)。localport 是您的本地系統上的一個非特權端口(1024 以上的任一未用端口),targetport 是您要連接到的服務的端口。
前面的命令從您的機器發送出去,到達外部世界。 也可以使用 SSH 發送進來,或者從外部世界連接到您的本地系統。入站通道的常規形式如下:
$ ssh user@proxyhost -R proxyport:targethosttargetport
建立一條入站通道 — 以前稱為遠程轉發 — 時,proxyhost 和 targethost 的角色將被反轉:目標是您的本地機器,代理是遠程機器。user 是您在代理上的登錄名。以下命令提供了一個具體示例:
$ ssh -R 8080:localhost:80
這條命令的意思是:用戶 Joe 連接到 example.com,并將遠程端口連接到本地端口 80。這條命令向 example.com 上的用戶提供一個通道,以連接到 Joe 的機器上。遠程用戶能夠連接到 8080,以便連接 Joe 機器上的 Web 服務器。
除了分別用于本地和遠程轉發的 -L 和 -R 之外,SSH 還提供 -D 參數來在遠程機器上創建一個 HTTP 代理。請參見 SSH 手冊頁了解正確語法。
使用歷史記錄重寫
如果您經常在 shell 提示符中花費大量時間,保存 shell 歷史記錄可以節約時間和輸入。但是如果歷史記錄不能被修改,就會導致一些麻煩:記錄重復的命令,且多個 shell 實例可能會干擾各自的歷史記錄。這兩個問題很容易解決,只需在您的 .bashrc 中添加兩行:
export HISTCONTROL=ignoreboth
shopt -s histappend
第一行將移除您的 shell 歷史記錄中連續的重復命令。如果您想移除所有零散的副本,可將ignoreboth 更改為 erasedups。第二行在 shell 退出時將 shell 的歷史記錄附加到您的記錄文件。默認情況下,Bash 記錄文件命名為 ~/~/.bash_history (不錯,這是一個點文件)。可以通過設置 HISTFILE(不錯,這是一個環境變量)來更改它的位置。如果您想將一個 shell 的最近 10,000 命令保存在一個包含 100,000 條目的記錄文件中,將 export HISTSIZE=10000 HISTFILESIZE=100000 添加到您的 shell 啟動文件中。要查看一個 shell 的歷史記錄,在任意提示處鍵入 history 即可。
如果不能調用,那么保存的命令歷史記錄就用處不大。而這正是 shell !(或 bang)操作符的作用所在:
* !! (“bang bang”) 完整地重復最后一條命令。
* !:0 是前一條命令的名稱。
* !^ 是前一條命令的第一個參數。!:2、!:3 … !$ 等命令是前一條命令的第二、第三……以及最后一個參數。
* !* 是最后一條命令的所有參數,命令名除外。
* !n 重復歷史中編號為 n 的命令。
* !handle 重復以 handle 中的字符開始的最后一條命令。例如,!ca 將重復以字符 ca 開始的最后一條命令,如 cat README。
* !?handle 重復包含 handle 中的字符組成的字符串的最后一條命令。例如,!?READ 還會匹配 cat README。
* ^original^substitution 使用 substitution 替換 original 的第一個 實例。例如,如果前一條命令是 cat README,,命令 ^README^license.txt 將生成一條新命令 cat license.txt。
* !:gs/original/substitution 將使用 substitution 替換 original 的所有 實例(!:gs 表示 “全局替換[global substitution]”)。
* !-2 是倒數第二條命令,!-3 是倒數第三條命令,以此類推。
您甚至可以合并歷史表達式來生成 !-2:0 -R !^ !-3:2 這樣的 “魔湯”,該命令將擴展為倒數第二條命令的名稱,加上 -R,再加上前一條命令的第一個參數,以及倒數第三條命令的第二個參數。要使這樣的神秘命令更具可讀性,可以在鍵入時擴展歷史參考。在任意提示符鍵入命令 bind Space:magic-space ,或者將其添加到一個啟動文件,從而將空格鍵綁定到函數 magic-space,該函數將擴展內聯歷史替換。
與擴展名無關的自動解壓
鑒于 Internet 上有如此眾多的代碼,您可能每天都會下載數十個文件。可能會出現這樣的情況:所有那些文件都使用不同的方式打包 — 有的是 ZIP 文件,有的是 RAR 文件,還有很多是 tarball 文件,盡管每個包都使用不同的實用程序壓縮。記住如何解壓縮和擴展每種包格式將會使人精疲力盡。那么,為何不在單個命令中完成所有那些任務呢?下面這個函數在許多樣例點文件中廣泛可用:
ex () {
if [ -f $1 ] ; then
case $1 in
*.tar.bz2) tar xjf $1 ;;
*.tar.gz) tar xzf $1 ;;
*.bz2) bunzip2 $1 ;;
*.rar) rar x $1 ;;
*.gz) gunzip $1 ;;
*.tar) tar xf $1 ;;
*.tbz2) tar xjf $1 ;;
*.tgz) tar xzf $1 ;;
*.zip) unzip $1 ;;
*.Z) uncompress $1 ;;
*.7z) 7z x $1 ;;
*) echo "'$1' cannot be extracted via extract()" ;;
esac
else
echo "'$1' is not a valid file"
fi
}
這個函數 ex 擴展了 11 種文件格式;如果要處理其他包類型,該函數還可以擴展。一旦定義 — 例如,在一個 shell 啟動文件中 — 就可以簡單地鍵入 ex somefile,其中 somefile 以以下一種已命名擴展結束:
$ ls
source
$ tar czf source.tgz source
$ ls -1
source
source.tgz
$ rm -rf source
$ ex source.tgz
$ ls -1
source
source.tgz
順便說一下,如果您將今天下載的文件放錯了位置,可以運行 find 來查找它:
$ find ~ -type f -mtime 0
命令 -type f 查找純文本文件,-mtime 0 查找自當天午夜以來創建的文件。
更多秘密
需要揭開的專家秘密還有很多。在 Web 上搜索 “shell auto-complete”,進一步了解自動完成特性,該特性用于在您鍵入一條命令時提供上下文敏感的擴展。另外,搜索 “shell prompts” 以了解如何定制您的 shell 提示:可以將其設置為彩色,可以設置您的當前工作目錄或 Git 分支,還可以顯示歷史數目 — 如果經常調用歷史,這是一個方便的參考信息。要查看工作示例,可在 Github 中搜索 “dot files”。許多專家都將他們的 shell 配置張貼在 Github 上。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。