Lsof命令使用

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


發佈了115 篇原創文章 · 獲贊 21 · 訪問量 67萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章