Lsof命令使用
1、lsof 簡介
Lsof是遵從Unix哲學的典範,它只做一件事情,並且做的相當完美。以列出某個進程打開的所有文件信息。打開的文件可能是普通的文件,目錄,NFS文件,塊文件,字符文件,共享庫,常規管道,符號鏈接,Socket流,網絡Socket,UNIX域Socket,以及其它。
在UNIX環境中,文件無處不在,這便產生了一句格言:“任何事物都是文件”。通過文件不僅僅可以訪問常規數據,通常還可以訪問網絡連接和硬件。在有些情況下,當您使用ls 請求目錄清單時,將出現相應的條目。在其他情況下,如傳輸控制協議 (TCP) 和用戶數據報協議 (UDP) 套接字,不存在相應的目錄清單。但是在後臺爲該應用程序分配了一個文件描述符,無論這個文件的本質如何,該文件描述符爲應用程序與基礎操作系統之間的交互提供了通用接口。
因爲應用程序打開文件的描述符列表提供了大量關於這個應用程序本身的信息,所以能夠查看這個列表將是很有幫助的。完成這項任務的實用程序稱爲lsof,它對應於“list open files”(列出打開的文件)。幾乎在每個 UNIX 版本中都有這個實用程序,但奇怪的是,大多數供應商並沒有將其包含在操作系統的初始安裝中。要獲取更多關於lsof 的信息,請參見參考資料部分。
參考資料:
http://www.ibm.com/developerworks/cn/aix/library/au-lsof.html#listing2
2、lsof 語法
安裝lsof:
許多Unix系統都內置了lsof,如果你的系統沒有安裝,你可以從這裏直接下載源代碼。
BSD系統有一個類似的工具可以做同樣的事情,叫做fstat。
lsof
需要訪問核心內存和各種文件,所以必須以 root 用戶的身份運行它才能夠充分地發揮其功能。
[oracle@xml-ora1 ~]$ lsof -h
lsof 4.78
latest revision:ftp://lsof.itap.purdue.edu/pub/tools/unix/lsof/
latest FAQ:ftp://lsof.itap.purdue.edu/pub/tools/unix/lsof/FAQ
latest man page:ftp://lsof.itap.purdue.edu/pub/tools/unix/lsof/lsof_man
usage: [-?abhlnNoOPRstUvVX] [+|-c c] [+|-d s][+D D] [+|-f]
[-F[f]] [-g [s]] [-i [i]] [+|-L [l]] [+m [m]] [+|-M] [-o [o]]
[-ps] [+|-r [t]] [-S [t]] [-T [t]] [-u s] [+|-w] [-x [fl]] [-Z [Z]] [--] [names]
Defaults in parentheses; comma-separatedset (s) items; dash-separated ranges.
-?|-h list help -a AND selections (OR) -b avoid kernel blocks
-cc cmd c, /c/[bix] +c w COMMAND width (9)
+ds dir s files -d s select by FD set +D D dir D tree *SLOW?*
-i select IPv[46]files -l list UID numbers
-nno host names -N select NFSfiles -o list file offset
-Oavoid overhead *RISK -P no portnames -R list paRent PID
-slist file size -t terselisting -T disable TCP/TPI info
-Uselect Unix socket -v list versioninfo -V verbose search
+|-w Warnings (+) -X skip TCP&UDP files -Z Z context [Z]
--end option scan
+f|-f +filesystem or -filenames
-F[f] select fields; -F? for help
+|-L [l] list (+) suppress (-) link counts < l (0 = all; default = 0)
+m [m]use|create mount supplement
+|-M portMap registration(-) -o o o 0t offset digits (8)
-ps exclude(^)|select PIDs -S [t] t second stat timeout (15)
-Tqs TCP/TPI Q,St (s) info
-g[s] exclude(^)|select and print process group IDs
-ii select by IPv[46] address:[46][proto][@host|addr][:svc_list|port_list]
+|-r [t] repeat every t seconds (15); + until no files, - forever
-us exclude(^)|select login|UID set s
-x[fl] cross over +d|+D File systems or symbolic Links
names select named files or fileson named file systems
Anyone can list all files; /dev warningsdisabled; kernel ID check disabled.
常用參數解釋:
lsof filename 顯示打開指定文件的所有進程
lsof -a 表示兩個參數都必須滿足時才顯示結果
lsof -c string 顯示COMMAND列中包含指定字符的進程所有打開的文件
lsof -u username 顯示所屬user進程打開的文件,逗號分隔指定多個用戶
lsof -g gid 顯示歸屬gid的進程情況
lsof +d /DIR/ 顯示目錄下被進程打開的文件
lsof +D /DIR/ 同上,但是會搜索目錄下的所有目錄,時間相對較長
lsof -d FD 顯示指定文件描述符的進程
lsof -n 不將IP轉換爲hostname,缺省是不加上-n參數
lsof -L, 作用: 列出打開文件的連接數
lsof -i 用以顯示符合條件的進程情況
lsof -i[46][protocol][@hostname|hostaddr][:service|port]
46 –> IPv4 or IPv6
protocol –> TCP or UDP
hostname –> Internet host name
hostaddr –> IPv4地址
service –> /etc/service中的 servicename (可以不只一個)
port –> 端口號 (可以不只一個)
組合用法:
[oracle@xml-ora1~]$ lsof -u oracle -cmysql
由用戶oracle打開的進程的文件,或者由mysql進程打開的文件。注意這裏是或者
[oracle@xml-ora1 ~]$ lsof -a -u oracle -c mysql
由用戶oracle打開的進程的文件同時又是有進程mysql打開的文件。這裏是並且的關係。
[oracle@xml-ora1 ~]$ lsof | head
COMMAND PID USER FD TYPE DEVICE SIZE NODE NAME
Init 1 root cwd unknown /proc/1/cwd (readlink: Permission denied)
Init 1 root rtd unknown /proc/1/root (readlink: Permissiondenied)
Java 337 oracle txt REG 8,3 50794 1046664 /usr/local/jdk1.6.0_31/bin/java
Java 3337 oracle mem REG 8,3 139416 2485804 /lib64/ld-2.5.so
oracle 28448 oracle 0u CHR 1,3 3776 /dev/null
oracle 20991 oracle 12uWREG 8,8 56962 105186 /u01/app/oradata/system01.dbf
注意:普通用戶可以使用/usr/sbin/lsof命令,但是訪問某些UNIX/LINUX內核文件的時候出現系統限制權限(readlink: Permission denied)提示。
lsof輸出各列信息的意義如下:
COMMAND:進程的名稱
PID:進程標識符
USER:進程所有者
FD:文件描述符,應用程序通過文件描述符識別該文件。如cwd、txt等
TYPE:文件類型,如DIR、REG等
DEVICE:指定磁盤的名稱
SIZE:文件的大小,單位byte
NODE:索引節點(文件在磁盤上的標識)
NAME:打開文件的確切名稱
FD 文件描述符:
cwd 值表示應用程序的當前工作目錄,這是該應用程序啓動的目錄,除非它本身對這個目錄進行更改。
txt 類型的文件是程序代碼,如應用程序二進制文件本身或共享庫,如上列表中顯示的/usr/local/jdk1.6.0_31/bin/java程序。
12uW 其中數值12表示應用程序的文件描述符,這是打開該文件時返回的一個整數。如上的最後一行文件/u01/app/oradata/system01.dbf,其文件描述符爲 12。u 表示該文件被打開並處於讀取/寫入模式,而不是隻讀(r
)或只寫 (w) 模式。同時還有大寫 的W 表示該應用程序具有對整個文件的寫鎖。該文件描述符用於確保每次只能打開一個應用程序實例。
初始打開每個應用程序時,都具有三個文件描述符,從 0 到 2,分別表示標準輸入、輸出和錯誤流。所以大多數應用程序所打開的文件的 FD 都是從 3 開始。
Type文件類型:
文件和目錄分別稱爲 REG 和 DIR。
CHR 和 BLK,分別表示字符和塊設備。
UNIX、FIFO 和 IPv4,分別表示 UNIX 域套接字、先進先出(FIFO) 隊列和網際協議 (IP) 套接字。
3、Lsof與 /proc 目錄
儘管與使用 lsof 沒有什麼直接的關係,但對/proc 目錄進行簡要的介紹是有必要的。/proc 是一個目錄,其中包含了反映內核和進程樹的各種文件。這些文件和目錄並不存在於磁盤中,因此當您對這些文件進行讀取和寫入時,實際上是在從操作系統本身獲取相關信息。大多數與lsof 相關的信息都存儲於以進程的 PID 命名的目錄中,所以 /proc/1234 中包含的是 PID 爲 1234 的進程的信息。
在 /proc 目錄的每個進程目錄中存在着各種文件,它們可以使得應用程序簡單地瞭解進程的內存空間、文件描述符列表、指向磁盤上的文件的符號鏈接和其他系統信息。lsof 實用程序使用該信息和其他關於內核內部狀態的信息來產生其輸出。稍後將看到把lsof 的輸出與 /proc 目錄中的信息聯繫起來。
[root@xml-ora1 ~]# cat /proc/25348/
attr/ coredump_filter environ io maps mountstats oom_score smaps status
auxv cpuset exe limits mem numa_maps root/ stat task/
cmdline cwd/ fd/ loginuid mounts oom_adj schedstat statm wchan
[root@xml-ora1 ~]# cat /proc/25348/fd/
0 10 12 14 16 18 2 21 23 25 27 29 30 32 34 36 38 4 41 43 45 5 7 9
1 11 13 15 17 19 20 22 24 26 28 3 31 33 35 37 39 40 42 44 46 6 8
4、查找應用程序打開的文件
lsof 常見的用法是查找應用程序打開的文件的名稱和數目。您可能想嘗試找出某個特定應用程序將日誌數據記錄到何處,或者正在跟蹤某個問題。
例如,UNIX 限制了進程能夠打開文件的數目。通常這個數值很大,所以不會產生問題,並且在需要時,應用程序可以請求更大的值(直到某個上限)。如果您懷疑應用程序耗盡了文件描述符,那麼可以使用lsof 統計打開的文件數目,以進行驗證。
要指定單個進程,可以使用 -p 參數,後面加上該進程的PID。因爲這樣做不僅會返回該應用程序所打開的文件,還會返回共享庫和代碼,所以通常需要對輸出進行篩選。要完成此任務,可以使用-d 標誌根據FD 列進行篩選,使用-a 標誌表示兩個參數都必須滿足 (AND)。如果沒有-a 標誌,缺省的情況是顯示匹配任何一個參數 (OR) 的文件。顯示了sendmail 進程打開的文件,並使用 txt 對這些文件進行篩選。
查看oracle監聽進程:
[root@xml-ora1 ~]# ps -ef | grep lsnr | grep -v grep
oracle 6462 1 0Aug01 ? 00:00:04/u01/app/oracle/product/10.2/db_1/bin/tnslsnr LISTENER –inherit
帶有 PID 篩選器並進行 txt 文件描述符篩選的 lsof 輸出
[root@xml-ora1 ~]# lsof -a -p 6462 -d ^txt
COMMAND PID USER FD TYPE DEVICE SIZE NODE NAME
tnslsnr 6462oracle cwd DIR 8,6 4096 195841 /home/oracle
tnslsnr 6462oracle rtd DIR 8,3 4096 2 /
tnslsnr 6462oracle mem REG 8,3 139416 2485804 /lib64/ld-2.5.so
tnslsnr 6462oracle mem REG 8,3 114352 2485695 /lib64/libnsl-2.5.so
tnslsnr 6462oracle 0u CHR 1,3 3776 /dev/null
tnslsnr 6462oracle 1u CHR 1,3 3776 /dev/null
tnslsnr 6462oracle 2u CHR 1,3 3776 /dev/null
tnslsnr 6462 oracle 3w REG 8,8 305574 1052527 /u01/app/oracle/db_1/network/log/listener.log
tnslsnr 6462oracle 4r FIFO 0,6 18543 pipe
tnslsnr 6462oracle 7w FIFO 0,6 18544 pipe
tnslsnr 6462oracle 8u IPv4 18547 TCP *:ncube-lm (LISTEN)
tnslsnr 6462oracle 12u unix 0xffff810475438e80 18552 /var/tmp/.oracle/s#6462.2
tnslsnr 6462 oracle13u IPv4 3661562 TCPxml-ora1:ncube-lm->xml-ora1:45221 (ESTABLISHED)
lsof指定了三個參數:
第一個是 -a,它表示當所有的參數都爲真時,才顯示這個文件。
第二個參數是 -p 605,它限制僅輸出 PID 爲 605 的進程,通過 ps 命令獲取PID。\
最後一個參數 -d ^txt,它表示篩選出其中 txt類型的記錄(脫字符號 [^] 表示排除)。
輸出提供了關於進程行爲的信息。cwd 行所示,該應用程序的工作目錄爲 /home/oracle。文件描述符 0、1 和 2 分配給了/dev/null(大量使用符號鏈接,所以顯示相應的僞設備)。
文件描述符 3是隻寫的,並且指向/u01/app/oracle/db_1/network/log/listener.log,寫入監聽日誌。
文件描述符 8 和 13 可以告訴您,該應用程序正以IPv4 模式監聽1521端口,並以 IPv4 模式建立連接。
5、查找打開某個文件的應用程序
有一個文件或目錄,並且需要知道哪個應用程序控制了該文件(打開了該文件)。例如我想知道/u01/app/oracle/db_1/network/log/listener.log這個日誌文件被那個oracle監聽打開和使用着。
[root@xml-ora1 ~]# lsof/u01/app/oracle/product/10.2/db_1/network/log/listener.log
COMMAND PID USER FD TYPE DEVICE SIZE NODE NAME
tnslsnr 6462 oracle 3w REG 8,8 7305704 105251527/u01/app/oracle/product/10.2/db_1/network/log/listener.log
正如輸出所示,進程 tnslsnr(PID 爲 6462)控制了文件 /u01/app/oracle/product/10.2/db_1/network/log/listener.log,並且只進行寫入操作。如果出於某種原因,您需要刪除這個文件,那麼正確的做法是中止該進程,而不是直接刪除這個文件。否則,這個守護進程下次可能無法正常啓動,或者可能稍後會啓動另一個實例,從而導致爭用。
有時您只知道在文件系統的某處打開了文件。在卸載文件系統時,如果該文件系統中有任何打開的文件,那麼操作將會失敗。通過指定裝入點的名稱,您可以使用lsof 顯示一個文件系統中所有打開的文件。
使用 lsof 找出誰在使用文件系統:
[oracle@xml-ora1 ~]$ lsof /home/oracle/ COMMAND PID USER FD TYPE DEVICE SIZE NODE NAME tnslsnr 6462 oracle cwd DIR 8,6 4096 195841 /home/oracle/ bash 23896 oracle cwd DIR 8,6 4096 195841 /home/oracle/ sftp-serv 26499 oracle cwd DIR 8,6 4096 195841 /home/oracle/ sftp-serv 29054 oracle cwd DIR 8,6 4096 195841 /home/oracle/ bash 31185 oracle cwd DIR 8,6 4096 195841 /home/oracle/ lsof 31213 oracle cwd DIR 8,6 4096 195841 /home/oracle/ |
/tmp目錄被垃圾文件塞滿了,用ls 又看不到太大文件, 誰幹的?
[oracle@xml-ora1 ~]$ lsof /tmp
COMMAND PID USER FD TYPE DEVICE SIZE NODE NAME
java 3337 oracle mem REG 8,2 32768 3342343/tmp/hsperfdata_oracle/3337
java 3404 oracle mem REG 8,2 32768 3342344/tmp/hsperfdata_oracle/3404
列出所有NFS(網絡文件系統)文件:[oracle@xml-ora1 ~]$ lsof -N
尋找本地斷開(無效)的打開文件:[oracle@xml-ora1~]$lsof +L1
用戶 oracle正在其 home 目錄中進行一些操作。有兩個 bash(一種 Shell)實例正在運行,並且當前目錄設置爲oracle 的 home 目錄。還有一個名爲sftp-serv的應用程序正運行於相同的目錄。
潛在的問題:lsof /export/home 與 lsof/export/home/(請注意尾部的斜槓)有所區別。第一種方式可以正常工作,因爲它指向了裝入點。第二種方式不會生成任何輸出,因爲它指向了目錄。如果您在 Shell 中使用 Tab 鍵自動完成命令,那麼可能碰到這個問題,其中會幫助您添加結尾的斜槓。在這種情況下,您可以刪除這個斜槓或者使用+D 指定目錄。前者是首選的方法,因爲與指定任意的目錄相比,其執行速度更快。
參數D可以遞歸查找某個目錄中所有打開的文件:
[oracle@xml-ora1 ~]$ lsof +D /home/oracle
加上+D參數,lsof會對指定目錄進行遞歸查找,注意這個參數要比grep版本慢
[oracle@xml-ora1 ~]$ lsof |grep /home/oracle
之所以慢是因爲+D首先查找所有的文件,然後一次性輸出。
6、恢復刪除的文件
當 UNIX 計算機受到入侵時,常見的情況是日誌文件被刪除,以掩蓋攻擊者的蹤跡。管理錯誤也可能導致意外刪除重要的文件,比如在清理舊日誌時,意外地刪除了數據庫的活動事務日誌。有時可以恢復這些文件,並且lsof 可以爲您提供幫助。
當進程打開了某個文件時,只要該進程保持打開該文件,即使將其刪除,它依然存在於磁盤中。這意味着,進程並不知道文件已經被刪除,它仍然可以向打開該文件時提供給它的文件描述符進行讀取和寫入。除了該進程之外,這個文件是不可見的,因爲已經刪除了其相應的目錄條目。
在/proc目錄部分中說過,通過在適當的目錄中進行查找,您可以訪問進程的文件描述符。lsof 可以顯示進程的文件描述符和相關的文件名。當向lsof 傳遞文件名時,比如在lsof /file/I/deleted 中,它首先使用 stat() 系統調用獲得有關該文件的信息,不幸的是,這個文件已經被刪除。在不同的操作系統中,lsof 可能可以從核心內存中捕獲該文件的名稱。
顯示了一個 Linux 系統,其中意外地刪除了 oracle數據庫的監聽日誌,我正使用grep 工具查找是否有人打開了該文件。
[oracle@xml-ora1 ~]$ lsof | grep listener.log tnslsnr 6462 oracle 3w REG 8,8 7307132 105251527 /u01/app/oracle/product/10.2/db_1/network/log/listener.log (deleted) |
在這個示例中,您可以看到 PID 6462打開文件的文件描述符爲 2,在 /proc/6426/fd/3中查看相應的信息:
[oracle@xml-ora1 ~]$ ll /proc/6462/fd/3
l-wx------ 1 oracle oinstall 64 Sep 1814:18 /proc/6462/fd/3 ->/u01/app/oracle/product/10.2/db_1/network/log/listener.log (deleted)
通過/proc 查找刪除的文件內容:
[oracle@xml-ora1 ~]$ tail /proc/6462/fd/3
20-SEP-2012 13:49:36 * service_update *xmlgis * 0
20-SEP-2012 13:59:39 * service_update *xmlgis * 0
20-SEP-2012 14:09:42 * service_update *xmlgis * 0
20-SEP-2012 14:11:24 * service_update *xmlgis * 0
20-SEP-2012 14:21:27 * service_update *xmlgis * 0
20-SEP-2012 14:31:30 * service_update *xmlgis * 0
20-SEP-2012 14:41:33 * service_update *xmlgis * 0
20-SEP-2012 14:51:36 * service_update *xmlgis * 0
20-SEP-2012 15:01:39 * service_update *xmlgis * 0
20-SEP-2012 15:11:42 * service_update *xmlgis * 0
Linux 的優點在於,它保存了文件的名稱,甚至可以告訴我們它已經被刪除。在遭到破壞的系統中查找相關內容時,這是非常有用的內容,因爲攻擊者通常會刪除日誌以隱藏他們的蹤跡。我們知道lsnr 進程使用了listener.log文件,所以可以使用ps 命令找到這個 PID,然後可以查看這個進程打開的所有文件。
在REDHAT中查找刪除的文件
[oracle@xml-ora1 ~]$ lsof | grep deleted
[oracle@xml-ora1 ~]$ lsof +L1
COMMAND PID USER FD TYPE DEVICE SIZE NLINK NODE NAME
oracle 25342 oracle 7u REG 8,8 0 0 104793747/u01/app/oracle/product/10.2/db_1/dbs/lkinstxmlgis(deleted)
oracle 25344 oracle 7u REG 8,8 0 0 104793747 /u01/app/oracle/product/10.2/db_1/dbs/lkinstxmlgis (deleted)
如果可以通過文件描述符查看相應的數據,那麼您就可以使用 I/O 重定向將其複製到文件中:
[oracle@xml-ora1~]$cat /proc/6462/fd/3 > /u01/app/oracle/product/10.2/db_1/network/log/listener.log
此時,您可以中止該守護進程(這將刪除 FD,從而刪除相應的文件),將這個臨時文件複製到所需的位置,然後重新啓動該守護進程。
[oracle@xml-ora1 ~]$ lsnrctl stop
[oracle@xml-ora1 ~]$ lsnrctl start
[oracle@xml-ora1 ~]$ lsof | grep listener.log
tnslsnr 6882 oracle 3w REG 8,8 7308113 13565953 /u01/app/oracle/product/10.2/db_1/network/log/listener.log
對於許多應用程序,尤其是日誌文件和數據庫,這種恢復刪除文件的方法非常有用。正如您所看到的,有些操作系統(以及不同版本的lsof)比其他的系統更容易查找相應的數據。
7、查找網絡連接
網絡連接也是文件,這意味着可以使用 lsof獲得關於它們的信息。只知道相應的端口,那麼可以使用-i 參數利用套接字信息進行搜索。
查找監聽端口1521 的進程:
[oracle@xml-ora1 ~]$ lsof -i :1521
COMMAND PID USER FD TYPE DEVICE SIZE NODE NAME
java 3337 oracle 34u IPv6 8215146 TCPxml-ora1:61437->xml-ora1:ncube-lm (ESTABLISHED)
java 3337 oracle 35u IPv6 8215147 TCPxml-ora1:61438->xml-ora1:ncube-lm (ESTABLISHED)
oracle 24636 oracle 14u IPv4 8384208 TCP xml-ora1:ncube-lm->xml-ora1:45193(ESTABLISHED)
需要以 protocol:@ip:port的形式向 lsof 實用程序傳遞相關信息,其中的 protocol 爲 TCP 或 UDP(可以使用 4 或 6 作爲前綴,表示 IP 的版本),IP 爲可解析的名稱或 IP 地址,而 port 爲數字或表示該服務的名稱(來自 /etc/services)。需要一個或多個元素(端口、IP、協議)。
列出所有網絡連接:[oracle@xml-ora1~]$ lsof -i
列出所有TCP網絡連接:[oracle@xml-ora1 ~]$ lsof -i udp
列出所有UDP網絡連接:[oracle@xml-ora1 ~]$ lsof -i tcp
列出所有IP4網絡連接:[oracle@xml-ora1 ~]$ lsof -i4 *
列出固定IP網絡連接:[oracle@xml-ora1 ~]$lsof -i @222.76.206.226
8、lsof恢復oracle誤刪除文件例子
2.1 查看ORACLE運行的進程
[oracle@xml-ora1 ~]$ uname -a
Linux xml-ora1 2.6.18-194.el5 #1 SMP TueMar 16 21:52:39 EDT 2010 x86_64 x86_64 x86_64 GNU/Linux
[oracle@xml-ora1 ~]$ cat /etc/redhat-release
Red Hat Enterprise Linux Server release 5.5(Tikanga)
[oracle@xml-ora1 ~]$ ps -ef | grep ora_
oracle 23923 23896 0 09:43 pts/3 00:00:00 grep ora_
oracle 25342 1 0 Aug06 ? 00:00:52 ora_pmon_xmlgis
oracle 25344 1 0 Aug06 ? 00:00:00 ora_psp0_xmlgis
oracle 25346 1 0 Aug06 ? 00:00:00 ora_mman_xmlgis
oracle 25348 1 0Aug06 ? 00:00:13 ora_dbw0_xmlgis
2.2 創建測試環境
創建表空間、表、數據以及數據文件:
SQL> create tablespace test_del datafile '/u01/app/oracle/oradata/xmlgis/test_del.dbf'size 50m;
Tablespace created.
SQL> select file_name from dba_data_files where file_name like'%del%';
FILE_NAME
--------------------------------------------------------------------------------
/u01/app/oracle/oradata/xmlgis/test_del.dbf
SQL> select name from v$datafile where name like '%del%';
NAME
--------------------------------------------------------------------------------
/u01/app/oracle/oradata/xmlgis/test_del.dbf
SQL> create table test_del tablespace test_del as select * from dba_objects;
Table created.
SQL> commit;
Commit complete.
SQL> alter system checkpoint;
System altered.
SQL> select count(*) from test_del;
COUNT(*)
----------
51459
SQL>select OWNER,OBJECT_NAME from test_del WHERE OWNER<>'SYS' AND ROWNUM<3;
OWNER OBJECT_NAME
--------------------------------------------------------------------------------
PUBLIC DUAL
PUBLIC SYSTEM_PRIVILEGE_MAP
[oracle@xml-ora1 ~]$ strings/u01/app/oracle/oradata/xmlgis/test_del.dbf | grep"SYSTEM_PRIVILEGE_MAP"
SYSTEM_PRIVILEGE_MAP
I_SYSTEM_PRIVILEGE_MAP
SYSTEM_PRIVILEGE_MAP
2.2 查看dbwr0打開的數據文件
[oracle@xml-ora1 ~]$ lsof -a -p 25348 -d ^txt | egrep"COMMAND|dbf"
Output information may be incomplete.
COMMAND PID USER FD TYPE DEVICE SIZE NODE NAME
oracle 25348 oracle 18uW REG 8,8 566239232 105186656 /u01/app/oracle/oradata/xmlgis/system01.dbf
…..省略其它文件…..
oracle 25348 oracle 48uW REG 8,8 52436992 21364739 /u01/app/oracle/oradata/xmlgis/test_del.dbf
2.3 刪除test_del.dbf數據文件
SQL> !
[oracle@xml-ora1 ~]$ ll/u01/app/oracle/oradata/xmlgis/test_del.dbf
-rw-r----- 1 oracle oinstall 52436992 Sep20 14:17 /u01/app/oracle/oradata/xmlgis/test_del.dbf
[oracle@xml-ora1 ~]$ rm/u01/app/oracle/oradata/xmlgis/test_del.dbf
[oracle@xml-ora1 ~]$ ll/u01/app/oracle/oradata/xmlgis/test_del.dbf
ls:/u01/app/oracle/oradata/xmlgis/test_del.dbf: No such file or directory
[oracle@xml-ora1 ~]$ exit
Exit
SQL> select file_name from dba_data_files where file_name like'%del%';
FILE_NAME
--------------------------------------------------------------------------------
/u01/app/oracle/oradata/xmlgis/test_del.dbf
SQL> select name from v$datafile where name like '%del%';
NAME
--------------------------------------------------------------------------------
/u01/app/oracle/oradata/xmlgis/test_del.dbf
SQL> insert into test_del select * from dba_objects;
51459 rows created.
SQL> commit;
Commit complete.
SQL> select count(*) from test_del;
COUNT(*)
----------
102918
SQL> alter system checkpoint;
System altered.
SQL> create table test_del_new tablespace test_del as select * from dba_objects;
Table created.
操作正常,說明數據文件雖然被刪除,但是可以繼續寫入,說明可以恢復。但是注意,不能關掉DBWR0進行,重新啓動後將丟失文件描述符,則無法恢復。
2.4 刪除文件描述符查找
[oracle@xml-ora1 ~]$ lsof | grep test_del
oracle 25348 oracle 48uW REG 8,8 52436992 21364739 /u01/app/oracle/oradata/xmlgis/test_del.dbf (deleted)
oracle 25350 oracle 30u REG 8,8 52436992 21364739 /u01/app/oracle/oradata/xmlgis/test_del.dbf (deleted)
oracle 25356 oracle 45u REG 8,8 52436992 21364739 /u01/app/oracle/oradata/xmlgis/test_del.dbf (deleted)
oracle 25358 oracle 44u REG 8,8 52436992 21364739 /u01/app/oracle/oradata/xmlgis/test_del.dbf (deleted)
oracle 32244 oracle 15u REG 8,8 52436992 21364739 /u01/app/oracle/oradata/xmlgis/test_del.dbf (deleted)
oracle 32244 oracle 19u REG 8,8 52436992 21364739 /u01/app/oracle/oradata/xmlgis/test_del.dbf (deleted)
注意:/u01/app/oracle/oradata/xmlgis/test_delete.dbf(deleted)說明該數據庫文件被刪除了,但是卻出現了這麼多是描述符號。仔細看了下其中的信息,發現PID爲25348的纔是DBWR0進行寫入的文件,同時48uW也說明了是原來刪除的文件,那其它信息呢,根據PID去查找進程。得到如下信息
[oracle@xml-ora1 ~]$ ps -ef | egrep"25348|25350|25356|25358|32244" | grep -v egrep
oracle 25348 1 0Aug06 ? 00:00:13 ora_dbw0_xmlgis
oracle 25350 1 0 Aug06 ? 00:00:22 ora_dbw1_xmlgis
oracle 25356 1 0 Aug06 ? 00:02:29 ora_ckpt_xmlgis
oracle 25358 1 0 Aug06 ? 00:01:33 ora_smon_xmlgis
oracle 32244 32243 0 12:58 ? 00:00:03 oraclexmlgis(DESCRIPTION=(LOCAL=YES)(ADDRESS=(PROTOCOL=beq)))
原來除了DBWR0對該進程進行讀寫,還包括DBWR1,CKPT,SMON以及我當前連接的session進行讀寫。哪個纔是要恢復的文件呢?
2.5 查看/proc文件系統
Cd /proc/819/fd/ 就可以得到所要查找的數據
[oracle@xml-ora1 ~]$ ll /proc/25348/fd/* | grep test_del
lrwx------ 1 oracle oinstall 64 Sep 2014:15 /proc/25348/fd/48-> /u01/app/oracle/oradata/xmlgis/test_del.dbf (deleted)
看來他們都是對同一個文件進行打開,只是返回的值不同而且,而真正打開該文件的是DBWR0,恢復該文件即可。
驗證文件內容:
[oracle@xml-ora1 ~]$ strings /proc/25348/fd/48 | grep"TEST_DEL"
TEST_DEL
TEST_DEL
TEST_DEL
TEST_DEL_NEW
TEST_DEL
2.6 恢復誤刪除文件
[oracle@xml-ora1 ~]$ cat /proc/25348/fd/48>/u01/app/oracle/oradata/xmlgis/test_del.dbf
[oracle@xml-ora1 ~]$ ll/u01/app/oracle/oradata/xmlgis/test_del.dbf
-rw-r--r-- 1 oracle oinstall 52436992 Sep20 14:45 /u01/app/oracle/oradata/xmlgis/test_del.dbf
2.7. 驗證文件恢復
新建表在此表空間:
SQL> create table test_del_recover tablespace test_del as select * from dba_objects;
Table created.
SQL> alter system checkpoint;
System altered.
SQL> !
[oracle@xml-ora1 ~]$ ll/u01/app/oracle/oradata/xmlgis/test_del.dbf
-rw-r--r-- 1 oracle oinstall 52436992 Sep20 14:45 /u01/app/oracle/oradata/xmlgis/test_del.dbf
[oracle@xml-ora1 ~]$ strings /proc/25348/fd/48 | grep"TEST_DEL"
TEST_DEL
TEST_DEL
TEST_DEL
TEST_DEL_NEW
TEST_DEL
TEST_DEL_RECOVER
TEST_DEL_NEW
TEST_DEL