面向 DBA 的 Linux Shell 腳本簡介

面向 DBA 的 Linux Shell 腳本簡介
作者:Casimir Saternos

學習一些在 Linux 上安裝、運行和維護 Oracle 數據庫所需的基本 bash shell 腳本。

本文相關下載:
示例腳本
Oracle 數據庫 10g

2005 年 11 月發表

大約 7 年前,Oracle 發佈了 Linux 上的第一個商業數據庫。從那時起,Oracle、Red Hat 和 Novell/SUSE 就不斷地合作更改 Linux 內核,從而提高數據庫和應用程序的性能。正因爲這樣,用於 Linux 的 Oracle 數據庫 10g 才包含了與操作系統緊密相關的許多增強功能。DBA 比以往任何時候更需要了解和使用此平臺來在其監視下對系統進行最佳管理。

以往,系統管理員與 DBA 之間在職責方面存在差別。但實際上,這種差別通常並不明顯。許多 IT 部門僱傭一些可解決數據庫級以及操作系統級問題的員工。當然,Oracle 數據庫本身使用操作系統資源,並能與其環境緊密交互。

此外,許多系統管理員和 DBA 發現將其工作相關的任務自動化很有必要或比較方便。軟件安裝、系統資源監視以及系統管理涉及一些重複和容易出錯的任務,而自動過程可以比手動過程更好地完成這些任務。

將這些任務自動化的方法之一是 shell 腳本。Shell 腳本自 Linux 系統安裝之初就起着重要作用。啓動和關閉系統時就會調用各種腳本。Oracle 和其他第三方供應商的實用程序也是通過 shell 腳本可調用的。由於這些腳本可以快速開發,因此歷來就用它們構建應用程序原型。系統管理員已利用通過 shell 腳本實現的功能提供針對其監視的系統的特定要求和特徵定製的解決方案了。

在本文中,我將介紹“bash”shell 腳本可以實現的、與在 Linux 平臺上安裝、運行和維護 Oracle 數據庫相關的功能。注意,本文適用於 Linux 腳本初學者或對 Linux 相對陌生的 DBA;對大多數經驗豐富的 Linux 系統管理員則不適用。

Shell 腳本是什麼?

shell 腳本是一個包含命令序列的文本文件。當運行文件(或腳本)時,將執行該文件中包含的命令。術語 shell 僅指與 Linux 內核通信所使用的特定命令行用戶界面。目前有多個不同的 shell,其中包括 C shell (csh)、Korn shell (ksh)、Bourne shell (sh) 和 Bourne-Again shell (bash)。shell 本身就是一個從文件或終端讀取命令、解釋這些命令並通常執行其他命令的命令。Bourne-Again shell 合併了上述其他 shell 的特性,本文就使用該腳本進行演示。

腳本文件中的第一行可用於指定使用哪個 shell 來運行該腳本。以下是所有腳本示例中包含的第一行的含義:

#!/bin/bash
       
爲什麼使用 Shell 腳本?

由於 shell 腳本與 DBA 的工作相關,因此您可能不會馬上看到 shell 腳本的價值,這跟您的工作經歷有關。如果您以前從未使用過 UNIX 或類似 UNIX 的系統,那麼可能會對大量含義晦澀的命令感到一愁莫展。此外,除了作爲關係數據庫外,Oracle 10g 還提供了一個用於處理數據庫數據的強健平臺以及幾個用於在數據庫外部與操作系統交互的方法。

但您會發現幾個探究 shell 腳本領域的原因,其中包括:

  • 必須支持已經存在的腳本。

  • 需要在安裝 Oracle 軟件前自動設置系統。例如,您可以編寫一個腳本來檢查 OS 的初始狀態並報告安裝軟件前必須滿足的任何前提條件。該腳本還可以創建相關的 OS 用戶和組併爲用戶設置環境變量。

  • 可以使用正在運行的 Oracle 數據庫來執行手動或計劃的任務。但在數據庫 運行時需要運行某些任務。可以使用腳本停止或啓動數據庫(以及偵聽器或相關的數據庫進程)。無法從數據庫內部啓動此類動作。

  • 您需要一種監視數據庫狀態(例如,是否正在運行並可進行進程查詢)的機制。這樣的腳本還可以監視非特定於 Oracle 的其他進程和資源,從而提供系統當前運行情況的更詳細信息。

  • 需要將備份自動化。Oracle Recovery Manager (RMAN) 是一個用於開發可以在任何平臺上運行的備份腳本的實用程序。可以從 shell 腳本中調用 Oracle Recovery Manager 並使用它執行各種備份和恢復活動。

  • 您可能有一個並非特定於某個數據庫的要求。您可能在一臺計算機上安裝了多個數據庫。建議您不要使用單個數據庫滿足此要求,因爲那樣會引發潛在的安全性問題。在這些情況下,shell 腳本提供了一種既可以滿足此要求又不會將進程與單個數據庫關聯的方法。

什麼情況下 使用 Shell 腳本

Oracle 數據庫包含了超出 RDBMS 傳統定義的功能。與軟件的任何其他部分一樣,它使用操作系統提供的資源,但它所“看到”並“更改”其環境的程度遠遠超過了其他軟件。SQL 和 Oracle 的固定視圖從數據庫內部提供了系統視圖,而 shell 腳本從數據庫外部提供了系統視圖。Shell 腳本並不是適用於所有問題的解決方案。

必須意識到,操作系統的許多方面可以從數據庫內部進行監視和修改。可以使用 Oracle 的固定視圖(帶 v$ 前綴的視圖)確定計算機的主機名 (v$instance) 或數據庫正在其中運行的平臺的名稱 (v$database)。還可以通過這種方式確定與數據庫相關的文件的位置和其他屬性。可以直接從數據庫中查詢數據文件(v$datafile、dba_data_files)、臨時文件(v$tempfile、dba_temp_files)、重做日誌 (v$logfile)、存檔日誌 (v$archived_log) 和控制文件 (v$controlfile) 的位置和其他屬性。可以通過該視圖以及通過查看某些 init.ora 參數(db_recovery_file_dest、db_recovery_file_dest_size)確定有關閃回恢復區 ($recovery_file_dest) 的信息。還可以查詢進程 (v$process) 和內存(v$sga、v$sgastat 等)的狀態。有各種內置的 PL/SQL 程序包,並能夠創建允許對底層 OS 進行其他訪問的 Java 和 C 數據庫對象。

如果您正在考慮爲一個需要大量數據庫訪問的任務編寫腳本,則腳本可能並不是最佳選擇。本文的稍後部分將介紹如何使用 SQL*Plus 訪問數據庫,但在很多情況下,使用其他語言可以更好地解決此問題。

下表歸納了可以從數據庫中訪問的信息:

服務器/操作系統信息

服務器標識

典型查詢

附註

實例運行在的主機的名稱

select host_name
from v$instance;

也可以通過從 bash 運行以下命令來獲得該信息:

 

hostname

uname –n

操作系統平臺

select platform_name from v$database –-(10g)

 

如果運行 uname –s,則將返回類似信息

 

文件信息

Oracle 文件位置

典型查詢

附註

控制文件

select name
from v$controlfile;

數據庫控制文件的位置。init.ora 的參數 control_files 也包含該信息。

數據文件

select file_name
from Dba_data_files;

數據庫數據文件的位置

臨時文件

select file_name
from Dba_temp_files;

數據庫臨時文件的位置

日誌文件

select member
from v$logfile;

重做日誌的位置

歸檔日誌

select name
from v$archived_log

歸檔重做日誌的位置。init.ora 的參數 log_archive_dest_n 也包含該信息。如果數據庫不在 Archivelog 模式下,則該查詢將不返回結果。

閃回恢復區

select name
from v$recovery_file_dest

Oracle 10g 安裝用作閃回恢復區的目錄。init.ora 參數 db_recovery_file_dest 也包含該信息。

由參數指示的文件系統上的其他訪問點

select *
from v$parameter

where value like '%/%'

value like '%/%';

根據 Oracle 數據庫安裝和版本的不同,該查詢的結果可能迥然不同。可能返回的參數有:

spfile
standby_archive_dest
utl_file_dir
background_dump_dest user_dump_dest
core_dump_dest
audit_file_dest
dg_broker_config_file1
dg_broker_config_file2

用編程的方式訪問文件系統

select directory_path from dba_directories

可以使用 Oracle UTL_FILE_DIR 參數和 DIRECTORY 數據庫對象訪問標準數據庫功能以外的文件。

 

進程信息

處理器/進程

典型查詢

附註

會話進程

select p.spid, s.username, s.program

from v$process p, v$session s

where p.addr=s.paddr order by 2, 3, 1

可以將 spid 與 ps –ef 結果相關聯,以將數據庫中的可用信息與給定進程的操作系統信息進行比較。

與並行相關的進程

select slave_name, status
from v$PQ_SLAVE

Oracle 數據庫的很多方面(如加載、查詢、對象創建、恢復和複製)都可以利用並行來加快可以分割的活動。參數 parallel_threads_per_cpu 設置實例的默認並行度。

 

內存信息

內存

典型查詢

附註

程序全局區

select * from V$PGASTAT

參數 pga_aggregate_target 用於爲所有專用服務器連接配置內存。

可以使用 vmstat 和 top 等 Linux 實用程序監視內存使用情況。

系統全局區

select * from v$sga

 

 

SGA_MAX_SIZE 和 SGA_TARGET 參數用於配置 Oracle 數據庫 10g 的動態內存分配特性。還可以使用其他參數爲特殊用途手動分配內存。

同時,還有各種 Linux 實用程序可用於監視內存分配。

BASH 腳本

腳本要麼作爲自動進程的一部分被調用(無需人爲干預),要麼以交互方式運行(用戶根據提示執行操作)。只要您擁有文件的執行權限,便可以從命令行鍵入該文件的名稱來運行它。如果您沒有文件的執行權限,但擁有其讀取權限,則可以通過在腳本的前面加上 sh 來運行該腳本。

如果腳本設計爲在無用戶輸入的情況下運行,則可以使用多種可選方法調用它。可以在後臺運行腳本,即使在斷開連接的情況下,您仍可以通過輸入以下形式的命令來運行:

nohup /path_to_dir/myscript_here.sh &

這對於需要很長時間才能完成的腳本很有用。 at 命令可用於在將來執行腳本,而 cron 可用於計劃要重複執行的腳本。

 

以下示例介紹了提供視圖輸出(使用 echo)、循環、條件邏輯以及變量賦值等重要方面。

 

print_args.sh。參數是位於命令名右側並傳遞到腳本中的詞。要訪問第一個參數,使用 $1 變量。 $0 變量包含腳本本身的名稱。 $# 變量包含腳本中的參數個數。一種迭代所傳遞的所有參數的便捷方法是使用 while 循環和 shift 命令。該命令使您可以迭代參數列表中的所有參數(而非保持無限循環)。

while [ $# -ne 0  ]
do
echo $1
shift
done

如果腳本將文件名作爲參數(或提示用戶輸入文件名)並在後面讀取該文件,則建議您檢查其訪問性和可讀性。例如,涉及選擇備份控制文件的恢復腳本可能提示用戶選擇將在腳本後面部分中用於恢復文件的備份控制文件。

if [ !-r $1 ]; then # not exists and is readable
                echo "File $1 does not exist or is not readable."
                exit;
fi      

字符序列

   
if [ !-r $1 ];

是實際執行測試的部分。如果方括號之間的內容結果爲 true,則將執行位於 if 和 fi 之間的命令。實際測試顯示在方括號之間。驚歎號用於對所執行的測試取反。-r 選項檢查文件是否可讀。在這個特定示例中所要測試的是傳遞給腳本的第一個參數。通過使用另一測試 (-d ),可以檢查給定條目是否是目錄(參見 is_a_directory.sh)。

 

do_continue.sh。該示例是一個可用於讀取各種目的的用戶輸入的簡單、典型的命令序列。在運行可能在某些無法從腳本內部確定的條件下導致數據丟失或其他不好結果的進程前,建議您增加一個提示,詢問用戶是否確實希望腳本執行接下來的命令。以下示例詢問用戶是否要繼續,從命令行讀取一個名爲 doContinue 的變量並對求解用戶的輸入。如果用戶輸入的不是“y”,則告知該用戶腳本“將退出”且不執行 if 代碼塊 ( fi) 後的其他腳本。

doContinue=n
echo -n "Do you really want to continue?(y/n) " 
read doContinue

if [ "$doContinue" != "y" ]; then
echo "Quitting..."
exit
fi

只有擁有相應權限和環境的用戶才能運行給定腳本。在腳本中檢查試圖運行腳本的用戶很有用。如果將命令括在單引號 (‘) 字符中,則將該命令的結果返回給腳本。以下示例在腳本中使用 whoami 檢索當前登錄的用戶,並稍後使用 date 命令顯示日期。

       
echo "You are logged in as 'whoami'";

if [ ‘whoami‘ != "oracle" ]; then
echo "Must be logged on as oracle to run this script."
exit
fi

echo "Running script at ‘date‘"

爲與 Oracle 數據庫交互而編寫的腳本有時需要輸入數據庫口令等機密信息。stty –echo 命令關閉屏幕響應,這樣爲隨後的讀取命令輸入的信息就不會顯示在屏幕上了。在讀取機密信息並將其存儲在變量(以下示例中的 pw)中後可以使用 stty echo 重新打開顯示。

       
stty -echo    
        echo -n "Enter the database system password:  "
        read pw
stty echo
Oracle 腳本

 

某些文件位於給定 Oracle 安裝的固定位置。可以通過查看 /etc/oraInst.loc 文件獲得 Oracle 清單。/etc/oratab 文件標識服務器上安裝的數據庫(和其他 Oracle 程序)。

get_inv_location.sh。該腳本不如前面的示例直觀。通過將該腳本劃分爲幾組命令,您將更好的理解該腳本的構成。

要確定清單位置,您將把 cat 命令(顯示文件的內容)的結果輸送到 grep(一個打印匹配給定模式的行的實用程序)。您將搜索包含文字 inventory_loc 的行。

cat /etc/oraInst.loc | grep inventory_loc

如果因有多個安裝而導致存在多個清單位置,則需要排除用 # 註釋掉的行。–v 選項排除 包含給定模式的行。

       
cat /etc/oraInst.loc |grep -v "#"|grep inventory_loc

 

該命令的結果將如下所示:

inventory_loc=/u01/oraInventory

可以使用 > 重定向命令將標準輸出重定向到一個文件。如果該文件不存在,則創建該文件。如果該文件已存在,則將其覆蓋。

 

 

       
cat /etc/oraInst.loc|grep -v "#"|grep inventory_loc > tmp

一旦獲得表明信息庫位置的記錄後,您就要刪除該記錄等號前的部分。這次,您將 cat 命令的結果輸送到 awk(一種通常用於拆分可變長度字段的模式掃描和處理語言),這實際上是將字符串標記化。–F 選項指示 awk 將等號用作分隔符。然後,打印該字符串的第二個標記 ($2),它代表等號右側的所有內容。其結果是我們要找的清單位置 (/u01/oraInventory)。

cat tmp | awk -F= '{print $2}'

由於沒有必要保留臨時文件 (tmp),因此可以將它刪除。

 

 

rm tmp

list_oracle_homes.sh。如果要確定給定數據庫的 ORACLE_HOME,則有多個可選方法。可以數據庫用戶的身份登錄,並對 $ORACLE_HOME 變量執行 echo。還可以搜索 /etc/oratab 文件並選擇與給定實例關聯的名稱。該文件中的數據庫條目的形式如下

   
$ORACLE_SID:$ORACLE_HOME:<N|Y>:

以下單行代碼輸出條目(ORACLE_SID 爲 TESTDB)的 ORACLE_HOME:

cat /etc/oratab | awk -F:'{if ($1=="TESTDB") print $2 }'

 

但如果如果您需要對 /etc/orainst 文件中列出的每個 ORACLE_HOME 執行操作該怎麼辦?可以使用以下代碼段迭代這樣的列表。

dblist='cat /etc/oratab | grep -v "#" | awk -F:'{print $2 }''

for ohome in $dblist ; do
echo $ohome
done

dblist 變量被用作數組。所有 ORACLE_HOME 路徑均由該變量保存。for 循環用於迭代該列表,並將每個條目賦給變量 ohome,然後將其發送到標準輸出。

 

search_log.sh。Oracle 產品生成各種日誌,您可能要監視它們。數據庫警報日誌包含對數據庫操作至關重要的消息。當安裝或卸載產品以及在應用補丁時也會生成日誌文件。以下腳本迭代以參數形式傳遞給它的文件。如果發現任何包含 ORA- 的行,則向指定的接收者發送電子郵件。

   
cat $1 | grep ORA- > alert.err

if [ 'cat alert.err|wc -l' -gt 0 ]
then
mail -s "$0 $1 Errors" [email protected] < alert.err
fi      

執行的具體測試是統計文件 alert.err(在您重定向到 alert.err 時寫入)中存在的單詞數。如果單詞數 (wc) 大於 (-gt) 零,則執行 if 代碼塊。這該示例中,您使用 mail(也可以使用 send mail)發送郵件。郵件標題包含所執行的腳本 ($0)、搜索的日誌名稱 ($1),郵件正文是與初始搜索 (ORA-) 匹配的行。

 

可以使用 ORACLE_HOME、ORACLE_BASE 和 ORACLE_SID 等環境變量找到不在 Linux 環境中固定位置的資源。如果管理 Oracle 電子商務套件 11i 應用程序實例,則可以使用許多其他環境變量來定位資源。這些變量包括 APPL_TOP、TWO_TASK、CONTEXT_NAME 以及 CONTEXT_FILE 等。要查看您環境中的完整列表,執行以下命令並查看生成的文件 (myenv.txt):

env > myenv.txt

可以將這些環境變量的各種組合用作所搜索文件的位置。例如,可以將警報日誌位置指定爲

   
$ORACLE_BASE/admin/$ORACLE_SID/bdump/alert_$ORACLE_SID.log

 

根據該腳本中引入的原則,可以編寫一個更大的腳本並計劃定期執行,該腳本將搜索警報日誌(或其他所關注的文件)的內容並在發生任何錯誤時發送電子郵件。然後,可以將日誌內容移動到其他文件,這樣就只將最新的錯誤消息通過電子郵件發送。

Oracle Recovery Manager 腳本。Oracle Recovery Manager (RMAN) 是一個可用於管理數據庫備份和恢復的實用程序。由於編寫的所有備份腳本都可以由 RMAN 運行,即減少了平臺特定的代碼數量,因此它明顯簡化了多個平臺的管理。RMAN 可由底層操作系統調用並接受傳遞來的腳本。例如,冷 (cold.sh) 備份可能由以下腳本組成:

   
#!/bin/bash
rman target / <<EOF
shutdown immediate;
startup mount;
backup spfile;
backup database;
alter database open;
delete noprompt obsolete;
quit;
EOF     

第 1 行表明您將使用 bash shell。第 2 行調用 Oracle Recovery Manager 並指定 OS 用戶登錄目標數據庫(在環境變量 $ORACLE_SID 中指定)。該行後面的 <<EOF 表示將把隨後的命令傳遞到 RMAN 中去處理。最後一行上的 EOF 表示您已經到了要傳遞到 RMAN 中的命令序列的結尾。然後,使用 RMAN 關閉數據庫、啓動並安裝數據庫並繼續備份服務器參數文件和數據庫的內容。然後打開數據庫。隨後刪除比保留策略中指定的備份舊的任何備份。參見 RMAN 文檔,構建與您的情況相關的備份。

晚間備份通常按計劃自動運行。可以使用以下命令調用以上腳本並將標準輸出的內容發送到電子郵件地址:

sh cold.sh | mail -s"Backup `date`" [email protected]

 

同樣,可以從 shell 腳本內部運行其他 Oracle 實用程序。可以使用 tnsping 實用程序查看給定 Oracle 連接標識符能否連接監聽器。可以運行該實用程序來檢查連接問題:

tnsping ptch04 |grep TNS- 

數據庫導出和導入(傳統的和數據泵)比較適合於編寫重複進程腳本。

 

 

數據庫安裝。數據庫設置中涉及的許多步驟都可以實現自動化。在 Linux 上安裝 Oracle 10g 之前,需要運行各種測試來驗證所需的最小程序包版本以及內核參數的設置。可以使用帶 –q 選項的 rpm 命令查詢程序包的版本。

   
rpm -q compat-libstdc++

 

可以通過查看 /proc“虛擬”或“僞”文件系統確定系統的各個方面。但它不包含實際的文件,而是包含可以查看的運行時系統信息(就好像位於文件中一樣)。例如,/proc/meminfo 包含系統的內存信息,而 grep MemTotal /proc/meminfo 顯示系統的內存總量。通過使用 awk(與前面的操作相同),可以分割內存數 (KB),具體方法如下:

grep MemTotal /proc/meminfo | awk '{print $2}'

可以在進行相應的比較和響應(甚至更新系統本身)的腳本上下文中使用這樣的命令。示例腳本 10gchecks_kernel.sh 和 10gchecks.sh 只顯示基於 Oracle 文檔的當前和建議的版本和設置。

 

數據庫監視。可以使用 ps 命令報告進程狀態並檢查數據庫、監聽器、腳本或任何其他相關進程是否正在運行。如果要列出服務器上當前運行的所有數據庫,可以運行以下命令:

   
echo "'ps -ef | grep smon|grep -v grep|awk '{print $8}'| awk -F \"_\" 
'{print$3}'`"

儘管該命令可以正常運行,但一下子理解起來有點困難。第一個命令 ps(使用 -ef 選項獲得所有進程的完整列表)查找在服務器上運行的所有進程。第二個命令 grep 搜索 SMON(Oracle System Monitor 後臺進程),它顯示數據庫正在運行。您要刪除引用正在運行的 grep 命令的條目。然後,使用 awk 找到列表中的第八列,其中包含 ora_smon_<oracle_sid> 形式的系統監視器進程名稱。然後,awk 的最後一個實例使用下劃線字符作爲分隔符來搜索並打印擁有此 SMON 進程的數據庫名稱。下劃線字符需要括在引號中,並在每個引號之前使用一個反斜槓將這些引號轉義(因爲整個字符串顯示在一組雙引號中)。

 

exec_sql.sh。正如前面指出的,如果用戶擁有 sqlplus 的訪問權限,便可以從 shell 腳本中查詢數據庫。以下示例返回當前在數據庫中保持會話狀態的計算機列表(由空格分隔):

   
#!/bin/bash

output='sqlplus -s "/ as sysdba" <<EOF
set heading off feedback off verify off
select distinct machine from v\\$session;
exit
EOF
'

echo $output    

因爲您將命令輸入到其他程序中,所以該腳本類似於前一個 RMAN 腳本。以 sysdba 的身份與數據庫建立一個經驗證的本地 OS 連接。爲防止返回不必要的消息,該腳本關閉 SQL*Plus 的 heading、feedback 和 verify 選項。執行查詢並退出 SQL*Plus。

 

注意視圖名稱中 $ 之前的雙反斜槓。它們是字符串中所需的轉義序列:第一個反斜槓轉義第二個反斜槓,後者轉義 $。儘管並不好看,但卻很實用。

 

正如前面指出的,如果要編寫需要廣泛數據庫訪問權限的代碼,那麼 shell 腳本並不是最佳選擇。用 PL/SQL、Perl(使用類似於 shell 腳本中使用的語法)、Python、Java 或隨便其他什麼語言重寫腳本可能會更好。

 

 

結論

Shell 腳本是快速自動化重複和易出錯管理任務的有效工具。本文提供的示例介紹了可能會出現的可能性,但還遠遠算不上全面。每個系統都有不同的特徵和缺陷以及獨特的配置。管理員將開發獨特的解決方案來滿足特定系統的需要。

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