<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          Linux下刪點(diǎn)日志也能搞死人

          共 3362字,需瀏覽 7分鐘

           ·

          2020-07-10 00:13

          81e8b27202daa760eb23be03d0c9fbc3.webpaf307f8f3ae54cff208ff76e83185d3e.webp


          點(diǎn)擊「閱讀原文」查看良許原創(chuàng)精品視頻。


          想了十天十夜不知道寫些什么,那就寫寫面試題吧。




          == 1 ==


          在面試應(yīng)聘者的時(shí)候,我常常會(huì)問:


          在 Linux 下,如何刪除一個(gè)目錄下的所有 log 文件?


          不知道是不是我人畜無害的圍笑給了應(yīng)聘者我很好應(yīng)付的錯(cuò)覺


          e922e25139b9dae74b15aa30f745ac1d.webp


          以至于應(yīng)聘者全都回答:rm *.log


          追問:該目錄下可能有很多子目錄(還可能是多級),如何把子目錄里的 log 文件也刪掉呢?


          答:rm -r *.log


          bab7a2650849e936d40c47ed49d41b1a.webp




          == 2 ==


          令我很意外的是,只有很少的應(yīng)聘者能想到 find 命令。


          而且想到的人也很少有記得具體用法的。


          a5c97fac1fc336193720ae1446195a82.webp


          目前為止只有一個(gè)應(yīng)聘者能夠給出完整的命令:

          find -name \*.log -exec rm -f {} \;

          注:這里的兩個(gè)斜杠都不是筆誤。這里除了?-exec ...,也可以用?-delete,或者用管道結(jié)合 xargs 來完成;又或者 ls -r | grep 也行。


          我覺得 find 應(yīng)該不算一個(gè)很罕見的命令?


          我們有一臺共享開發(fā)機(jī),因?yàn)榇蠹叶紤械脛h log ,經(jīng)常磁盤爆滿,后來我們給它加了個(gè)?crontab:

          0?4?*?*?*?find?/home/?-type?f?-name?"*.log*"?-size?+100M?-exec?bash?-c?"echo?-n?>?'{}'"?\;

          注:".log*"?后面的 * 是考慮了 log rotate。


          注意,這個(gè)命令沒有用 rm ,而是使用重定向來清空文件,原因后面會(huì)講。




          == 3 ==


          基于清理磁盤空間這個(gè)場景,我還會(huì)繼續(xù)問:


          你有遇到過刪了 log 文件,但是磁盤空間卻沒有釋放的情況嗎?


          有些候選人可能心里在想著:文件刪了不就刪了嗎,還有什么磁盤空間沒釋放?


          3ab1ab4e9cb179cd11428fc4309d9c7e.webp


          所以有時(shí)候我需要解釋一下,是 df 命令看到的磁盤空間沒有減少。


          還有個(gè)候選人努力想了想,和我確認(rèn),是不是正好這個(gè)目錄掛載的是其他磁盤,所以看起來當(dāng)前磁盤空間沒減少。(當(dāng)然不是)


          思路稍微開闊一點(diǎn)的候選人會(huì)想到:你個(gè)憨批莫不是刪了個(gè)軟鏈接吧?


          4cdab9ee05b1b97e47c6d3d89d22212f.webp


          當(dāng)然候選人的語氣會(huì)比較友好。


          然后我會(huì)和候選人繼續(xù)溝通:


          你提到了軟鏈接,那它和硬鏈接的區(qū)別是什么呢?


          有時(shí)候我懷疑這幾個(gè)連續(xù)的問題問到候選人開始懷疑人生,因?yàn)橛械暮蜻x人有點(diǎn)猶豫,覺得自己想說的其實(shí)是硬鏈接。


          a214a50cacb1a123fd3199710132a321.webp


          不過還是有幾個(gè)候選人知道,軟鏈接是一種文件類型,其內(nèi)容是目標(biāo)文件的路徑;硬鏈接是 inode 的別名,同一個(gè) inode 可以有多個(gè)鏈接,在 inode 里記錄了硬鏈接的數(shù)量(引用計(jì)數(shù))。


          比如這樣:


          創(chuàng)建一個(gè)空文件,看下inode和鏈接數(shù):

          $?touch?a.txt?#創(chuàng)建一個(gè)空文件$?stat?-c?'inode?%i, links %h'?a.txtinode?12058942,?links?1

          ?

          創(chuàng)建一個(gè)軟鏈接,再看看文件大小:

          $?ln?-s?a.txt?b.txt?#軟鏈接$ stat -c 'inode %i, links %h' b.txtinode 12058978, links 1
          $?ls?-l?b.txt?#大小5字節(jié)lrwxrwxrwx ... 5 ... b.txt -> a.txt
          $ readlink b.txt #文件內(nèi)容a.txt


          創(chuàng)建一個(gè)硬鏈接,看下inode和鏈接數(shù)

          $?ln?a.txt?c.txt?#硬鏈接,inode不變,鏈接數(shù)變成2$ stat -c 'inode %i, links %h' c.txtinode 12058942, links 2
          $ ls -l c.txt #大小0字節(jié),和a一樣lrwxrwxrwx?...?0?...?c.txt




          == 4 ==


          但實(shí)際生產(chǎn)上,遇到 “刪了文件、但空間不釋放” 通常和軟/硬鏈接沒有什么關(guān)系。


          9fa654790e46d4a3cc273d88a8701e1e.webp


          實(shí)(cai)戰(zhàn)(keng)經(jīng)驗(yàn)比較豐富的候選人會(huì)知道,這更可能是因?yàn)槲募涣硪粋€(gè)進(jìn)程打開。


          比如在終端 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 是內(nèi)核的 fd 編號。0=stdin, 1=stdout, 2=stder。


          可以看到,a.txt ?被標(biāo)記為已刪除,但因?yàn)檫M(jìn)程還開著它,可能會(huì)訪問文件的內(nèi)容,所以內(nèi)核會(huì)等到進(jìn)程關(guān)閉該文件(或進(jìn)程退出后)才在磁盤上移除這個(gè)文件。




          == 5 ==


          在面試中通常沒有機(jī)會(huì)再問下去了,但實(shí)踐中往往問題還沒解決。


          比如前述共享開發(fā)機(jī),就曾遇到了用 df 看磁盤空間800G已滿,但用 du 查看,所有文件卻只占用了 500G的情況。


          那么:


          1. 如何才能知道現(xiàn)在系統(tǒng)中有哪些文件已刪除、但是仍被占用呢?

          $ sudo lsof | grep deletedCOMMAND???PID??…??NAMEmain???893246??…? /../nohup.out?(deleted)...

          發(fā)現(xiàn)是有大量已經(jīng)被刪除、但仍被某些進(jìn)程打開的 nohup.out 。


          2. 坑是找到了,該怎么填呢?


          由于這是開發(fā)機(jī),很簡單,把進(jìn)程殺掉就好了,進(jìn)程退出時(shí),內(nèi)核會(huì)負(fù)責(zé)關(guān)閉文件,然后清理占用的空間。


          但如果是線上服務(wù)呢?


          Linux下有一個(gè) package 叫 logrotate,像 nginx 這些服務(wù)就是使用它來做日志切割/輪轉(zhuǎn)的。


          但 nginx 是在后臺持續(xù)運(yùn)行的,不能為了切個(gè)日志就停止服務(wù),所以它們是這樣約定的:

          1. logrotate 執(zhí)行 rename 系統(tǒng)調(diào)用(相當(dāng)于 mv 命令)重命名日志文件;

          2. 由于 inode 不變,這時(shí) nginx 會(huì)繼續(xù)寫入重命名后的日志文件;

          3. logrotate 給 nginx 發(fā)送一個(gè) SIGHUP 信號;

          4. nginx?在收到信號后會(huì)關(guān)閉當(dāng)前文件,并重新打開日志文件(即創(chuàng)建了新的日志文件)。


          注:為什么是用 SIGHUP 而不是其他信號,以后可能會(huì)另開一篇講講。


          這樣 logrotate 出來的日志,就可以放心刪除了。


          對于不支持類似邏輯的服務(wù)怎么辦呢?


          重啟大法。


          如果只是想清空這個(gè)文件,可以這樣(以前面python為例):

          $?echo?-n?>?/proc/2390/fd/3

          這樣文件是清空了,適用于 append only 的日志文件,但對于其他場景可能存在一定風(fēng)險(xiǎn)。


          要是不怕背 P0 的話,還可以這么作死:

          $ sudo gdb(gdb)?attach?$PID(gdb)?call?ftruncate(3,?0)?#按需修改fd$1 = 0

          注:ftruncate只是清空文件,如果想關(guān)閉文件,可以結(jié)合 dup、dup2、open和close來搞事,不細(xì)說了。


          a3c08f35593bb198cc2d3d346f4c8a99.webp




          == 6 ==


          看到這里你應(yīng)該明白了為什么前面那個(gè) find 命令不直接用 rm 了吧?


          照例總結(jié)下:

          1. 可以用 find 查找文件

          2. 軟鏈接存的是路徑,硬鏈接共享inode

          3. 刪除被進(jìn)程打開的文件,磁盤空間不會(huì)釋放

          4. lsof 很好用(不只是看文件的占用)



          良許個(gè)人微信


          添加良許個(gè)人微信即送3套程序員必讀資料


          → 精選技術(shù)資料共享

          → 高手如云交流社群





          本公眾號全部博文已整理成一個(gè)目錄,請?jiān)诠娞柪锘貜?fù)「m」獲取!

          推薦閱讀:

          Linux下diff命令用法詳解

          Linus:我們都老了,但Linux維護(hù)后繼無人

          Linux系統(tǒng)中虛擬設(shè)備文件的各種實(shí)用用法


          5T技術(shù)資源大放送!包括但不限于:C/C++,Linux,Python,Java,PHP,人工智能,單片機(jī),樹莓派,等等。在公眾號內(nèi)回復(fù)「1024」,即可免費(fèi)獲取!!


          瀏覽 26
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評論
          圖片
          表情
          推薦
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  台湾精品一区二区 | 亚洲少妇网 | 韩国不卡一区二区 | 精品人妻免费视频 | 一级片免费观看 |