面向 DBA 的 Linux Shell 指令碼簡介

路途中的人2012發表於2017-03-17

http://www.itpub.net/showthread.php?s=&threadid=720028

面向 DBA Linux Shell 指令碼簡介

7 年前,Oracle 釋出了 Linux 上的第一個商業資料庫。從那時起,OracleRed 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$datafiledba_data_files)、臨時檔案(v$tempfiledba_temp_files)、重做日誌 (v$logfile)、存檔日誌 (v$archived_log) 和控制檔案 (v$controlfile) 的位置和其他屬性。可以透過該檢視以及透過檢視某些 init.ora 引數(db_recovery_file_destdb_recovery_file_dest_size)確定有關閃回恢復區 ($recovery_file_dest) 的資訊。還可以查詢程式 (v$process) 和記憶體(v$sgav$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.shOracle 產品生成各種日誌,您可能要監視它們。資料庫警報日誌包含對資料庫操作至關重要的訊息。當安裝或解除安裝產品以及在應用補丁時也會生成日誌檔案。以下指令碼迭代以引數形式傳遞給它的檔案。如果發現任何包含 ORA- 的行,則向指定的接收者傳送電子郵件。

cat $1 | grep ORA- > alert.err

if [ 'cat alert.err|wc -l' -gt 0 ]

then

mail -s "$0 $1 Errors" administrator@yourcompany.com < alert.err

fi

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

可以使用 ORACLE_HOMEORACLE_BASE ORACLE_SID 等環境變數找到不在 Linux 環境中固定位置的資源。如果管理 Oracle 電子商務套件 11i 應用程式例項,則可以使用許多其他環境變數來定位資源。這些變數包括 APPL_TOPTWO_TASKCONTEXT_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`" administrator@yourcompany.com

同樣,可以從 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 搜尋 SMONOracle System Monitor 後臺程式),它顯示資料庫正在執行。您要刪除引用正在執行的 grep 命令的條目。然後,使用 awk 找到列表中的第八列,其中包含 ora_smon_<oracle_sid> 形式的系統監視器程式名稱。然後,awk 的最後一個例項使用下劃線字元作為分隔符來搜尋並列印擁有此 SMON 程式的資料庫名稱。下劃線字元需要括在引號中,並在每個引號之前使用一個反斜槓將這些引號轉義(因為整個字串顯示在一組雙引號中)。

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

#!/bin/bash

output='sqlplus -s "

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/29067253/viewspace-2135555/,如需轉載,請註明出處,否則將追究法律責任。

相關文章