1. 程式人生 > >高階 Linux 命令精通指南 第1部分

高階 Linux 命令精通指南 第1部分

感謝原創Arup Nanda

在 Sheryl Calish 撰寫的“Linux 檔案命令精通指南”這篇出色的文章中,您學習到了一些對於 Linux 新手尤為重要的常用 Linux 命令。既然您現在已經掌握了基礎知識,下面我們將介紹一些更為複雜但卻非常有用的命令。

在這個共分 4 個部分的文章系列中,您將學習各種常用命令的一些並不被人們所熟知的使用技巧,以及可以使這些命令更為有用的用法變化形式。在學習本文章系列過程中,您將先後瞭解一些難於掌握的命令。

注意,根據您所使用的 Linux 的特定版本或編譯的特定核心,這些命令可能會存在差別,但即便如此,這種差別也很小。

輕鬆更改所有者、組和許可權

在 Sheryl 的文章中,您學習瞭如何使用 chown 和 chgrp 命令來更改檔案的所有權和組。假設有如下幾個檔案:

# ls -l
total 8
-rw-r--r--    1 ananda   users          70 Aug  4 04:02 file1
-rwxr-xr-x    1 oracle   dba           132 Aug  4 04:02 file2
-rwxr-xr-x    1 oracle   dba           132 Aug  4 04:02 file3
-rwxr-xr-x    1 oracle   dba           132 Aug  4 04:02 file4
-rwxr-xr-x    1 oracle   dba           132 Aug  4 04:02 file5
-rwxr-xr-x    1 oracle   dba           132 Aug  4 04:02 file6

並且您需要更改所有檔案的許可權以便與 file1 的許可權匹配。當然,您可以執行 chmod 644 * 來進行此更改,但如果您要編寫一個指令碼來執行該操作,而事先卻並不知道這些許可權,那該怎麼辦?或者,您可能要基於許多不同的檔案進行多個許可權更改,但卻發現逐個使用這些檔案的許可權並進行相應的修改並不可行。

一種更好的方法是使許可權類似於另一個檔案的許可權。以下命令使 file2 的許可權與 file1 相同:

chmod --reference file1 file2 

現在,如果您檢視以下示例:

# ls -l file[12]
total 8
-rw-r--r--    1 ananda   users          70 Aug  4 04:02 file1
-rw-r--r--    1 oracle   dba           132 Aug  4 04:02 file2

file2 的許可權完全按照 file1 中的許可權進行了更改。您不必先獲取 file1 的許可權。

您還可以將同一技巧用於檔案中的組成員關係。要使 file2 的組與 file1 相同,可以執行以下命令:

# chgrp --reference file1 file2
# ls -l file[12]
-rw-r--r--    1 ananda   users          70 Aug  4 04:02 file1
-rw-r--r--    1 oracle   users         132 Aug  4 04:02 file2

當然,適用於更改組的方法也同樣適用於所有者。下面演示瞭如何將同一技巧用於所有權更改。如果許可權如下所示:

# ls -l file[12] 
-rw-r--r--    1 ananda   users          70 Aug  4 04:02 file1
-rw-r--r--    1 oracle   dba           132 Aug  4 04:02 file2

則可以按以下方式更改所有權:

# chown --reference file1 file2
# ls -l file[12] 
-rw-r--r--    1 ananda   users          70 Aug  4 04:02 file1
-rw-r--r--    1 ananda   users         132 Aug  4 04:02 file2

注意,組和所有者已經更改。

適用於 Oracle 使用者的技巧

您可以使用該技巧根據某個參考可執行檔案更改目錄中 Oracle 可執行檔案的所有權和許可權。該技巧對於移植非常有用,在移植期間您可以(並且可能應該)以不同的使用者身份安裝檔案,並在以後將這些檔案轉移至常規的 Oracle 軟體所有者。

有關檔案的詳細說明

ls 命令及其許多引數提供了一些非常有用的檔案資訊。另一個不太為人所熟知的命令 stat 提供了一些更為有用的資訊。

下面演示瞭如何對可執行檔案“oracle”(位於 $ORACLE_HOME/bin 目錄下)使用此命令。

# cd $ORACLE_HOME/bin
# stat oracle
  File: `oracle'
  Size: 93300148        Blocks:182424     IO Block:4096   Regular File
Device: 343h/835d       Inode: 12009652    Links: 1    
Access: (6751/-rwsr-s--x)  Uid:(  500/  oracle)   Gid:(  500/     dba)
Access: 2006-08-04 04:30:52.000000000 -0400
Modify: 2005-11-02 11:49:47.000000000 -0500
Change: 2005-11-02 11:55:24.000000000 -0500

注意使用該命令獲得的資訊:除了通常的檔案大小(也可以使用 ls -l 命令獲得)以外,您還獲得了該檔案佔用的塊數。通常的 Linux 塊大小為 512 位元組,因此一個大小為 93,300,148 位元組的檔案將佔用 (93300148/512=) 182226.85 個塊。由於塊都是完整佔用,因此該檔案使用了一些整數個數的塊。無需猜測就可以獲得確切的塊數。

您還可以從以上輸出中獲得檔案所有權的 GID 和 UID,以及許可權的八進位制表示形式 (6751)。如果要將檔案恢復到它現在具有的相同許可權,可以使用 chmod 6751 oracle,而不是顯式拼寫這些許可權。

以上輸出最有用的部分是檔案訪問時間戳資訊。該輸出顯示,該檔案被訪問的時間是 2006-08-04 04:30:52(顯示在“Access:”的旁邊),即 2006 年 8 月 4 日上午 4:30:52。這是某個人開始使用資料庫的時間。該檔案的修改時間是 2005-11-02 11:49:47(顯示在“Modify:”的旁邊)。最後,“Change:”旁邊的時間戳顯示檔案狀態更改的時間。

stat 命令的修改符 -f 顯示了有關檔案系統(而非檔案)的資訊:

# stat -f oracle
  File: "oracle"
    ID: 0        Namelen:255     Type:ext2/ext3
Blocks: Total: 24033242   Free: 15419301   Available: 14198462   Size: 4096
Inodes: Total: 12222464   Free: 12093976  

另一個選項 -t 顯示了完全相同的資訊,只不過是在一行中顯示的:

# stat -t oracle 
oracle 93300148 182424 8de9 500 500 343 12009652 1 0 0 1154682061 
1130950187 1130950524 4096

這對 shell 指令碼非常有用,在 shell 指令碼中可以使用一個簡單的 cut 命令獲得值以進行進一步處理。

適用於 Oracle 使用者的技巧

重新連結 Oracle(通常在安裝補丁過程中執行)時,將在建立新的可執行檔案之前將現有可執行檔案的名稱更改為其他名稱。例如,可以使用以下命令重新連結所有實用程式

relink utilities

該命令對 sqlplus 可執行檔案進行重新編譯,此外還執行其他操作。它將現有的可執行檔案 sqlplus 命名為 sqlplusO。如果重新編譯由於某種原因失敗,則 relink 程序會將 sqlplusO 重新命名為 sqlplus,並撤銷更改。同樣,如果在應用補丁後發現功能問題,則可以通過手動重新命名檔案來快速撤銷補丁。

下面演示瞭如何對這些檔案使用 stat:

# stat sqlplus*
  File: 'sqlplus'
  Size: 9865            Blocks:26         IO Block:4096   Regular File
Device: 343h/835d       Inode:9126079     Links: 1    
Access: (0751/-rwxr-x--x)  Uid:(  500/  oracle)   Gid:(  500/     dba)
Access: 2006-08-04 05:15:18.000000000 -0400
Modify: 2006-08-04 05:15:18.000000000 -0400
Change: 2006-08-04 05:15:18.000000000 -0400
 
  File: 'sqlplusO'
  Size: 8851            Blocks:24         IO Block:4096   Regular File
Device: 343h/835d       Inode:9125991     Links: 1    
Access: (0751/-rwxr-x--x)  Uid:(  500/  oracle)   Gid:(  500/     dba)
Access: 2006-08-04 05:13:57.000000000 -0400
Modify: 2005-11-02 11:50:46.000000000 -0500
Change: 2005-11-02 11:55:24.000000000 -0500

輸出顯示 sqlplusO 的修改時間是 2005 年 11 月 11 日,而 sqlplus 的修改時間是 2006 年 8 月 4 日,該時間也是 sqlplusO 的狀態更改時間。該輸出表明,sqlplus 的原始版本從 2005 年 11 月 11 到 2006 年 8 月 4 日這段時間內一直正常執行。如果要診斷某些功能問題,則該資訊將是一個非常不錯的起點。除了檔案更改以外,如果您知道許可權的更改時間,則可以將它與發覺的任何功能問題聯絡起來。

另一個重要的輸出是檔案大小,不同的檔案存在不同的大小(sqlplus 的大小為 9865 位元組,而 sqlplusO 的大小為 8851),這表明版本不僅僅經過重新編譯,實際上這些版本通過其他庫進行了更改(也許是這樣)。檔案大小的不同還指示了某些問題的可能原因。

檔案型別

檢視檔案時,如何知道它的檔案型別?命令 file 可以顯示檔案型別。例如:

# file alert_DBA102.log
alert_DBA102.log:ASCII text

檔案 alert_DBA102.log 是一個 ASCII 文字檔案。來看看更多示例:

# file initTESTAUX.ora.Z
initTESTAUX.ora.Z:compress'd data 16 bits

該示例指示檔案是壓縮檔案,但如何知道檔案的壓縮型別?方法之一是將該檔案解壓縮並再次執行它;但這實際上是幾乎不可能的。一種更簡便的方法是使用引數 -z

# file -z initTESTAUX.ora.Z
initTESTAUX.ora.Z:ASCII text (compress'd data 16 bits)

另一種方法是顯示符號連結:

# file spfile+ASM.ora.ORIGINAL   
spfile+ASM.ora.ORIGINAL:symbolic link to 
/u02/app/oracle/admin/DBA102/pfile/spfile+ASM.ora.ORIGINAL

儘管該方法很有用,但所指向的檔案的型別是什麼?可以使用選項 -l,而不必再次執行檔案:

# file -L spfile+ASM.ora.ORIGINAL
spfile+ASM.ora.ORIGINAL:data

該示例清楚地表明該檔案是資料檔案。注意,與 init.ora 不同的是,spfile 檔案是一個二進位制檔案;因此檔案顯示為資料檔案。

適用於 Oracle 使用者的技巧

假設您要在使用者轉儲目標目錄中搜索某個跟蹤檔案,但不知道該檔案是否位於其他目錄並只以一個符號連結形式存在,或某個人是否壓縮了該檔案(甚至對其進行了重新命名)。有一點您是知道的:該檔案肯定是一個 ascii 檔案。下面演示瞭如何執行操作:

file -Lz * | grep ASCII | cut -d":"-f1 | xargs ls -ltr

該命令將檢查 ASCII 檔案(即使它們經過了壓縮)並按時間順序將其列出。

比較檔案

如何判斷兩個檔案(file1 和 file2)是否相同?方法有多種,每種方法都有其自身的優點。

diff最簡單的命令是 diff,用於顯示兩個檔案之間的差別。以下是這兩個檔案的內容:

# cat file1
In file1 only
In file1 and file2
# cat file2
In file1 and file2
In file2 only

使用 diff 命令能夠了解這兩個檔案之間的差別,如下所示:

# diff file1 file2
1d0
< In file1 only
2a2
> In file2 only
#

在以上輸出中,第一列中的“<”表示該行位於上面最先提到的檔案(即 file1)中。第一列中的“>”表示該行位於第二個檔案 (file2) 中。輸出第一行中的字元 1d0 顯示為了作用於檔案 file1(以使其與 file2 相同)而在 sed 中必須執行的操作。

另一個選項 -y 顯示了相同的輸出,只不過輸出是並排顯示的:

# diff -y file1 file2 -W 120
In file1 only                             <
In file1 and file2                                In file1 and file2
                                          >    In file2 only

-W 選項是可選的;它僅指示該命令使用寬度為 120 個字元的螢幕輸出,這對於包含長行的檔案很有用。

如果只希望瞭解檔案是否不同,而不必知道如何不同,則可以使用 -q 選項。

# diff -q file3 file4
# diff -q file3 file2
Files file3 and file2 differ

由於檔案 file3 和 file4 相同,因此沒有輸出;在另一個示例中,將報告檔案存在差別。

如果要編寫 shell 指令碼,則採用以下方式生成可以分析的輸出可能比較有用。-u 選項可以執行該操作:

# diff -u file1 file2        
--- file1       2006-08-04 08:29:37.000000000 -0400
+++ file2       2006-08-04 08:29:42.000000000 -0400
@@ -1,2 +1,2 @@
-In file1 only
In file1 and file2
+In file2 only

以上輸出顯示了這兩個檔案的內容,但並未顯示重複內容,第一列中的 + 號和 - 號指示檔案中的行。第一列中的任何字元均未指示這兩個檔案中同時存在的內容。

該命令可以識別空格。如果要忽略空格,請使用 -b 選項。使用 -B 選項忽略空白行。最後,使用 -i 忽略大小寫。

diff 命令還可以應用於目錄。命令

diff dir1 dir2

顯示檔案檔案存在於任一目錄中;無論檔案是存在於這兩個目錄中的一個,還是同時存在於這兩個目錄中。如果它找到同名的子目錄,則不會繼續檢視任何單個檔案是否存在差別。示例如下:

# diff DBA102 PROPRD     
Common subdirectories:DBA102/adump and PROPRD/adump
Only in DBA102:afiedt.buf
Only in PROPRD:archive
Only in PROPRD:BACKUP
Only in PROPRD:BACKUP1
Only in PROPRD:BACKUP2
Only in PROPRD:BACKUP3
Only in PROPRD:BACKUP4
Only in PROPRD:BACKUP5
Only in PROPRD:BACKUP6
Only in PROPRD:BACKUP7
Only in PROPRD:BACKUP8
Only in PROPRD:BACKUP9
Common subdirectories:DBA102/bdump and PROPRD/bdump
Common subdirectories:DBA102/cdump and PROPRD/cdump
Only in PROPRD:CreateDBCatalog.log
Only in PROPRD:CreateDBCatalog.sql
Only in PROPRD:CreateDBFiles.log
Only in PROPRD:CreateDBFiles.sql
Only in PROPRD:CreateDB.log
Only in PROPRD:CreateDB.sql
Only in DBA102:dpdump
Only in PROPRD:emRepository.sql
Only in PROPRD:init.ora
Only in PROPRD:JServer.sql
Only in PROPRD:日誌
Only in DBA102:oradata
Only in DBA102:pfile
Only in PROPRD:postDBCreation.sql
Only in PROPRD:RMANTEST.sh
Only in PROPRD:RMANTEST.sql
Common subdirectories:DBA102/scripts and PROPRD/scripts
Only in PROPRD:sqlPlusHelp.log
Common subdirectories:DBA102/udump and PROPRD/udump

注意,普通的子目錄只按這種方式報告,而不進行比較。如果要進一步深究,並比較這些子目錄中的檔案,則應使用以下命令:

diff -r dir1 dir2

該命令將採用遞迴方式進入每個子目錄,以比較檔案並報告同名檔案之間的差別。

適用於 Oracle 使用者的技巧

diff 的一種常見用法是區分不同的 init.ora 檔案。作為一種最佳實踐,我在更改之前通常對檔案進行復制並重命名(例如,將 initDBA102.ora 複製並重命名為 initDBA102.080306.ora 以表示 2006 年 8 月 3 日)。檔案所有版本之間的一個簡單的 diff 就可以快速指出哪些內容發生更改以及更改時間。

這是一個非常強大的用於管理 Oracle 根目錄的命令。作為最佳實踐,我在應用補丁時從不更新 Oracle 根目錄。例如,假設當前的 Oracle 版本為 10.2.0.1。ORACLE_HOME 可能為 /u01/app/oracle/product/10.2/db1。當需要將它更新為 10.2.0.2 時,我不會對此 Oracle 根目錄打補丁。相反,我將在 /u01/app/oracle/product/10.2/db2 上啟動一個全新的安裝,然後對該根目錄打補丁。準備就緒後,我使用以下命令:

# sqlplus / as sysdba
SQL> shutdown immediate
SQL> exit
# export ORACLE_HOME=/u01/app/oracle/product/10.2/db2
# export PATH=$ORACLE_HOME/bin:$PATH
# sqlplus / as sysdba
SQL> @$ORACLE_HOME/rdbms/admin/catalog

...

等等。

該方法的目的是不破壞原始的 Oracle 根目錄,因此我可以在出現問題時輕鬆地進行恢復。這還意味著資料庫關閉並再次啟動,而且瞬間即可完成。如果我將補丁直接安裝到 Oracle 根目錄上,則必須長時間(補丁應用的整個持續時間)關閉資料庫。此外,如果補丁應用由於某種原因出現故障,則不必清理 Oracle 根目錄。

既然有多個 Oracle 根目錄,那如何檢視哪些內容發生了更改?方法其實很簡單,我可以使用以下命令:

diff -r /u01/app/oracle/product/10.2/db1 /u01/app/oracle/product/10.2/db2 | 
grep -v Common

該命令顯示了兩個 Oracle 根目錄之間的差別,以及同名檔案之間的差別。某些重要的檔案(如 tnsnames.ora、listener.ora 以及 sqlnet.ora)不會有太大的差別,但如果差別很大,那麼我就需要知道差別的原因。

cmp.命令 cmp 類似於 diff

# cmp file1 file2   
file1 file2 differ:byte 10, line 1

只要遇到差別就會返回輸出。可以使用此輸出標識檔案在何處可能存在差別。與 diff 一樣,cmp 有很多選項,其中最重要的選項是 -s 選項,它只返回一個程式碼:

  • 如果檔案相同,則返回 0
  • 如果檔案不同,則返回 1
  • 如果無法進行比較,則返回某個非零數字

示例如下:

# cmp -s file3 file4
# echo $?
0

特殊變數 $? 指示返回程式碼來自上次執行的命令。在本示例中,該變數為 0,表示檔案 file1 和 file2 相同。

# cmp -s file1 file2
# echo $?
1

表示 file1 和 file2 不同。

cmp 的這個屬性對於 shell 指令碼非常有用,因為在 shell 指令碼中您只希望檢查兩個檔案是否存在差別,而不必檢查差別是什麼。該命令的另一個重要用途是比較二進位制檔案,而 diff 對於比較二進位制檔案可能並不可靠。

適用於 Oracle 使用者的技巧

回顧一下上一個提示,當您重新連結 Oracle 可執行檔案時,舊版本在被覆蓋之前將一直保留。因此,在重新連結時,可執行檔案 sqlplus 重新命名為“sqlplusO”,並且新編譯的 sqlplus 置於 $ORACLE_HOME/bin 中。那麼,如何確保剛剛建立的 sqlplus 存在差別?只需使用以下命令:

# cmp sqlplus sqlplusO
sqlplus sqlplusO differ:byte 657, line 7

如果檢查大小:

# ls -l sqlplus*
-rwxr-x--x    1 oracle   dba          8851 Aug  4 05:15 sqlplus
-rwxr-x--x    1 oracle   dba          8851 Nov  2  2005 sqlplusO

即使這兩個示例中的大小完全相同,cmp 也可以證明這兩個程式存在差別。

comm.命令 comm 與其他命令相似,只是輸出分三列顯示,並且列之間由製表符分隔。示例如下:

# comm file1 file2
In file1 and file2
In file1 only
In file1 and file2
In file2 only

本部分中的命令摘要


命令 用途

chmod

使用 - -reference 引數更改檔案許可權

chown

使用 - -reference 引數更改檔案所有者

chgrp

使用 - -reference 引數更改檔案的組

stat

查詢檔案的擴充套件屬性,如檔案的上次訪問時間

file

查詢檔案型別,如 ASCII、資料等

diff

檢視兩個檔案之間的差別

cmp

比較兩個檔案

comm

瞭解兩個檔案的相同內容,並分三列顯示輸出

md5sum

計算檔案的 MD5 雜湊值(用於確定檔案是否已更改)

如果您想要檢視某個檔案的內容(另一個檔案中不存在這些內容),而不僅僅是差別(SQL 語言中 MINUS 實用程式的排序),則該命令將很有用。-1 選項將不顯示在第一個檔案中找到的內容:

# comm -1 file1 file2
In file1 and file2
In file2 only

md5sum.該命令將生成檔案的 32 位 MD5 雜湊值:

# md5sum file1
ef929460b3731851259137194fe5ac47  file1

可以將兩個具有相同校驗和的檔案視為相同。而該命令的用途並不僅僅限於比較檔案。它還可以提供一種機制來確保檔案的完整性。

假設您有兩個需要保護的重要檔案,file1 和 file2。可以使用 --check 選項檢查並確保檔案未更改。首先,為這些重要檔案建立校驗和檔案,然後對其進行安全儲存:

# md5sum file1 file2 > f1f2 

以後,當您要驗證這些檔案是否仍保持不變時,可執行如下操作:

# md5sum --check f1f2      
file1:OK
file2:OK

這清楚地表明檔案未被修改。現在,更改一個檔案並檢查 MD5:

# cp file2 file1
# md5sum --check f1f2
file1:FAILED
file2:OK
md5sum:WARNING:1 of 2 computed checksums did NOT match

輸出清楚地表明 file1 已被修改。

適用於 Oracle 使用者的技巧

md5sum 是一個非常強大的用於安全性實施的命令。您所管理的某些配置檔案(如 listener.ora、tnsnames.ora 和 init.ora)對於成功的 Oracle 基礎架構非常重要,任何修改都可能會導致停機。這些通常是更改控制過程的一部分。不要相信別人所說的這些檔案並未更改,使用 MD5 校驗和執行該命令。建立一個校驗和檔案,並在每次執行計劃的更改時重新建立該檔案。作為合規性的一部分,使用 md5sum 命令檢查該檔案。如果某個人無意中更新了這些重要檔案中的一個,您就會立即捕獲更改。

同樣,您還可以為 $ORACLE_HOME/bin 中的所有可執行檔案建立 MD5 校驗和,並不斷比較它們以捕獲未授權的修改。

結論

到目前為止,您只學習了對於高效執行作業比較有用的 Linux 命令的一部分。在下一部分中,我將介紹一些更復雜但卻很有用的命令,如 stracewhereisreniceskill 等。