linux 查看磁盘空间_Linux下删点日志也能搞死人
想了十天十夜不知道寫些什么,那就寫寫面試題吧。
== 1 ==
在面試應聘者的時候,我常常會問:
在 Linux 下,如何刪除一個目錄下的所有 log 文件?
不知道是不是我人畜無害的圍笑給了應聘者我很好應付的錯覺
以至于應聘者全都回答:rm *.log
追問:該目錄下可能有很多子目錄(還可能是多級),如何把子目錄里的 log 文件也刪掉呢?
答:rm -r *.log
== 2 ==
令我很意外的是,只有很少的應聘者能想到 find 命令。
而且想到的人也很少有記得具體用法的。
目前為止只有一個應聘者能夠給出完整的命令:
find -name \*.log -exec rm -f {} \;注:這里的兩個斜杠都不是筆誤。這里除了?-exec ...,也可以用?-delete,或者用管道結合 xargs 來完成;又或者 ls -r | grep 也行。
我覺得 find 應該不算一個很罕見的命令?
我們有一臺共享開發機,因為大家都懶得刪 log ,經常磁盤爆滿,后來我們給它加了個?crontab:
0?4?*?*?*?find?/home/?-type?f?-name?"*.log*"?-size?+100M?-exec?bash?-c?"echo?-n?>?'{}'"?\;注:".log*"?后面的 * 是考慮了 log rotate。
注意,這個命令沒有用 rm ,而是使用重定向來清空文件,原因后面會講。
== 3 ==
基于清理磁盤空間這個場景,我還會繼續問:
你有遇到過刪了 log 文件,但是磁盤空間卻沒有釋放的情況嗎?
有些候選人可能心里在想著:文件刪了不就刪了嗎,還有什么磁盤空間沒釋放?
所以有時候我需要解釋一下,是 df 命令看到的磁盤空間沒有減少。
還有個候選人努力想了想,和我確認,是不是正好這個目錄掛載的是其他磁盤,所以看起來當前磁盤空間沒減少。(當然不是)
思路稍微開闊一點的候選人會想到:你個憨批莫不是刪了個軟鏈接吧?
當然候選人的語氣會比較友好。
然后我會和候選人繼續溝通:
你提到了軟鏈接,那它和硬鏈接的區別是什么呢?
有時候我懷疑這幾個連續的問題問到候選人開始懷疑人生,因為有的候選人有點猶豫,覺得自己想說的其實是硬鏈接。
不過還是有幾個候選人知道,軟鏈接是一種文件類型,其內容是目標文件的路徑;硬鏈接是 inode 的別名,同一個 inode 可以有多個鏈接,在 inode 里記錄了硬鏈接的數量(引用計數)。
比如這樣:
創建一個空文件,看下inode和鏈接數:
$?touch?a.txt?#創建一個空文件$?stat?-c?'inode?%i, links %h'?a.txtinode?12058942,?links?1創建一個軟鏈接,再看看文件大小:
$?ln?-s?a.txt?b.txt?#軟鏈接$ stat -c 'inode %i, links %h' b.txtinode 12058978, links 1$?ls?-l?b.txt?#大小5字節lrwxrwxrwx ... 5 ... b.txt -> a.txt$ readlink b.txt #文件內容a.txt創建一個硬鏈接,看下inode和鏈接數
$?ln?a.txt?c.txt?#硬鏈接,inode不變,鏈接數變成2$ stat -c 'inode %i, links %h' c.txtinode 12058942, links 2$ ls -l c.txt #大小0字節,和a一樣lrwxrwxrwx?...?0?...?c.txt== 4 ==
但實際生產上,遇到 “刪了文件、但空間不釋放” 通常和軟/硬鏈接沒有什么關系。
實(cai)戰(keng)經驗比較豐富的候選人會知道,這更可能是因為文件正被另一個進程打開。
比如在終端 1 打開 a.txt:
$ python>>>?f?=?open("a.txt")然后在終端 2 可以看到該文件被 Python 打開:
$?lsof?a.txtCOMMAND??PID?...?????NODE?NAMEpython??2390?...?12058942?a.txt刪掉 a.txt,再查看 python 打開的文件列表:
$ rm?a.txt$ ls -l /proc/2390/fdlrwx------ 1 user ... 00:04 0 -> /dev/pts/5lrwx------ 1 user ... 00:04 1 -> /dev/pts/5lrwx------ 1 user ... 00:04 2 -> /dev/pts/5lr-x------ 1 user ... 00:04 3 -> /tmp/a.txt (deleted)注:0、1、2、3 是內核的 fd 編號。0=stdin, 1=stdout, 2=stder。
可以看到,a.txt ?被標記為已刪除,但因為進程還開著它,可能會訪問文件的內容,所以內核會等到進程關閉該文件(或進程退出后)才在磁盤上移除這個文件。
== 5 ==
在面試中通常沒有機會再問下去了,但實踐中往往問題還沒解決。
比如前述共享開發機,就曾遇到了用 df 看磁盤空間800G已滿,但用 du 查看,所有文件卻只占用了 500G的情況。
那么:
1. 如何才能知道現在系統中有哪些文件已刪除、但是仍被占用呢?
$ sudo lsof | grep deletedCOMMAND???PID??…??NAMEmain???893246??…? /../nohup.out?(deleted)...發現是有大量已經被刪除、但仍被某些進程打開的 nohup.out 。
2. 坑是找到了,該怎么填呢?
由于這是開發機,很簡單,把進程殺掉就好了,進程退出時,內核會負責關閉文件,然后清理占用的空間。
但如果是線上服務呢?
Linux下有一個 package 叫 logrotate,像 nginx 這些服務就是使用它來做日志切割/輪轉的。
但 nginx 是在后臺持續運行的,不能為了切個日志就停止服務,所以它們是這樣約定的:
logrotate 執行 rename 系統調用(相當于 mv 命令)重命名日志文件;
由于 inode 不變,這時 nginx 會繼續寫入重命名后的日志文件;
logrotate 給 nginx 發送一個 SIGHUP 信號;
nginx?在收到信號后會關閉當前文件,并重新打開日志文件(即創建了新的日志文件)。
注:為什么是用 SIGHUP 而不是其他信號,以后可能會另開一篇講講。
這樣 logrotate 出來的日志,就可以放心刪除了。
對于不支持類似邏輯的服務怎么辦呢?
重啟大法。
如果只是想清空這個文件,可以這樣(以前面python為例):
$?echo?-n?>?/proc/2390/fd/3這樣文件是清空了,適用于 append only 的日志文件,但對于其他場景可能存在一定風險。
要是不怕背 P0 的話,還可以這么作死:
$ sudo gdb(gdb)?attach?$PID(gdb)?call?ftruncate(3,?0)?#按需修改fd$1 = 0注:ftruncate只是清空文件,如果想關閉文件,可以結合 dup、dup2、open和close來搞事,不細說了。
== 6 ==
看到這里你應該明白了為什么前面那個 find 命令不直接用 rm 了吧?
照例總結下:
可以用 find 查找文件
軟鏈接存的是路徑,硬鏈接共享inode
刪除被進程打開的文件,磁盤空間不會釋放
lsof 很好用(不只是看文件的占用)
良許個人微信
添加良許個人微信即送3套程序員必讀資料
→ 精選技術資料共享
→ 高手如云交流社群
本公眾號全部博文已整理成一個目錄,請在公眾號里回復「m」獲取!
推薦閱讀:
Linux下diff命令用法詳解
Linus:我們都老了,但Linux維護后繼無人
Linux系統中虛擬設備文件的各種實用用法
5T技術資源大放送!包括但不限于:C/C++,Linux,Python,Java,PHP,人工智能,單片機,樹莓派,等等。在公眾號內回復「1024」,即可免費獲取!!
總結
以上是生活随笔為你收集整理的linux 查看磁盘空间_Linux下删点日志也能搞死人的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python爬虫天气预报_Python爬
- 下一篇: 松下伺服esi文件_松下贴片机操作教程