高級 Linux 命令精通指南(1)

 在 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

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

<!-- Tips Box start -->

適用於 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 命令獲得值以進行進一步處理。

<!-- Tips Box start -->

適用於 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),這表明版本不僅僅經過重新編譯,實際上這些版本通過其他庫進行了更改(也許是這樣)。文件大小的不同還指示了某些問題的可能原因。

<!-- Tips Box end -->

文件類型

查看文件時,如何知道它的文件類型?命令 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 文件是一個二進制文件;因此文件顯示爲數據文件。

<!-- Tips Box start -->

適用於 Oracle 用戶的技巧

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

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

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

<!-- Tips Box end -->

比較文件

如何判斷兩個文件(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

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

<!-- Tips Box start -->

適用於 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)不會有太大的差別,但如果差別很大,那麼我就需要知道差別的原因。

<!-- Tips Box end -->

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 對於比較二進制文件可能並不可靠。

<!-- Tips Box start -->

適用於 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 也可以證明這兩個程序存在差別。

<!-- Tips Box end -->

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 已被修改。

<!-- Tips Box start -->

適用於 Oracle 用戶的技巧

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

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

<!-- Tips Box end -->

結論

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


Arup Nanda ([email protected]) 擔任 Oracle DBA 已 12 餘載,處理過各方面的數據庫管理問題,從性能優化到安全性和災難恢復,無所不及。他與人合著了 PL/SQL for DBAs (O'Reilly Media, 2005),並曾在 2003 年榮獲 Oracle Magazine 的 DBA 稱號,現在爲 Oracle ACE。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章