美文网首页
【Linux恶作剧系列】1 如何写满磁盘而难以被发现

【Linux恶作剧系列】1 如何写满磁盘而难以被发现

作者: icymoon_90e6 | 来源:发表于2018-09-05 13:40 被阅读0次

    相信各位搞系统运维的同学,都收到过机器磁盘满了的报警短信,通常这时候心里一定想着,这是哪个不着调的把系统服务配错了或者把代码写飞了,没有log rotate,没有控制写入数据大小,没有限制core的行为...

    本文...本文打算写点别的方法,教你如何写满磁盘却又比较难被查到,嗯...也就是说,你查不出谁写满磁盘的时候,请重新复习这篇文章看看。

    0 背景知识

    系统命令 作用
    ls list, 列出当前目录下的目录和文件
    lsof 列出打开的文件
    df 报告文件系统磁盘空间使用率
    du disk usage,统计当前目录或文件使用了多大的磁盘

    1 小儿科的隐藏文件

    linux下以"."开头的文件为隐藏文件,直接使用ls命令查看不到,这可能导致一些新手同学发现目录够大,而目录下面空空如也。

    root@icymoon_dev> du -hs ./testdir/
    89M ./testdir/
    root@icymoon_dev> ls ./testdir/
    root@icymoon_dev>
    

    这个不难,ls 加“-a”参数就可以展示这些文件了。

    root@icymoon_dev> ls -a ./testdir/
    .  ..  .file
    root@icymoon_dev> ls -al ./testdir/
    total 91100
    drwxr-xr-x  2 root root     4096 Sep  5 11:34 .
    drwxr-xr-x. 3 root root     4096 Sep  5 11:35 ..
    -rw-r--r--  1 root root 93275613 Sep  5 11:34 .file
    root@icymoon_dev>
    

    2 进阶版,删除正在被写入的文件

    咱们先看个实验哈,以/boot分区为例;
    假设/boot分区开始是这样子:

    root@icymoon_dev> df | head -n 1 ; df | grep boot
    Filesystem      1K-blocks     Used  Available Use% Mounted on
    /dev/sda1          499656   406256      56704  88% /boot
    root@icymoon_dev> du -hs /boot/
    396M    /boot/
    root@icymoon_dev>
    

    我编写个程序不断地往/boot/test_file里写入,代码可以参考这里:

    root@icymoon_dev> vim writefile.c
    root@icymoon_dev> gcc writefile.c -Wall -o writefile
    root@icymoon_dev> nohup ./writefile &
    [2] 15865
    root@icymoon_dev> nohup: ignoring input and appending output to ‘nohup.out’
    

    写入同时可以观察/boot分区使用情况和新写入的文件,注意,这里du和df看到的增长情况是符合的~~

    root@icymoon_dev> du -hs /boot/
    398M    /boot/
    root@icymoon_dev> df | head -n 1 ; df | grep boot
    Filesystem      1K-blocks     Used  Available Use% Mounted on
    /dev/sda1          499656   407604      55356  89% /boot
    root@icymoon_dev> du -hs /boot/test_file
    1.6M    /boot/test_file
    root@icymoon_dev>
    

    然后,【有意思的地方来了】,删除掉正在写入的文件,耐心等待

    root@icymoon_dev> rm /boot/test_file
    rm: remove regular file ‘/boot/test_file’? y
    root@icymoon_dev> df | head -n 1 ; df | grep boot
    Filesystem      1K-blocks     Used  Available Use% Mounted on
    /dev/sda1          499656   418368      44592  91% /boot
    root@icymoon_dev> du -hs /boot/
    396M    /boot/
    

    告诉我你看到了什么?df看分区写到了91%,但是du看目录还是只有最初的396M。耐心地等下去,哪怕分区写满了,du看目录还是只用了396M。
    What?!这是什么鬼操作?!
    亲们,这个事情告诉我们,【划重点】不能随便删除正在写入的文件啊~~~
    那么,【划重点】这种情况怎么排查呢?lsof查找deleted文件,怎么处理呢?杀进程;

    root@icymoon_dev> lsof | head -n 1 ; lsof | grep deleted
    COMMAND      PID    TID     USER   FD      TYPE             DEVICE  SIZE/OFF       NODE NAME
    writefile  15865            root    3u      REG                8,1  27386928        332 /boot/test_file (deleted)
    root@icymoon_dev> df | head -n 1 ; df | grep boot
    Filesystem      1K-blocks     Used  Available Use% Mounted on
    /dev/sda1          499656   436684      26276  95% /boot
    root@icymoon_dev> kill -9 15865
    root@icymoon_dev> df | head -n 1 ; df | grep boot
    Filesystem      1K-blocks     Used  Available Use% Mounted on
    [2]+  Killed                  nohup ./writefile
    /dev/sda1          499656   406256      56704  88% /boot
    root@icymoon_dev>
    

    3 再进阶版,玩转mount

    什么?你说lsof这个太容易查了?咱们再来点别的

    3.1 准备工作

    先看看怎么把一个文件做成一个文件系统的image并且挂载,了解的朋友请跳过

    root@icymoon_dev> dd if=/dev/zero of=disk8M.image bs=1024 count=8192
    8192+0 records in
    8192+0 records out
    8388608 bytes (8.4 MB) copied, 0.0169399 s, 495 MB/s
    root@icymoon_dev> mke2fs -F disk8M.image -L "ramdisk" -b 1024 -m 0
    mke2fs 1.42.9 (28-Dec-2013)
    Discarding device blocks: done
    Filesystem label=ramdisk
    OS type: Linux
    Block size=1024 (log=0)
    Fragment size=1024 (log=0)
    Stride=0 blocks, Stripe width=0 blocks
    2048 inodes, 8192 blocks
    0 blocks (0.00%) reserved for the super user
    First data block=1
    Maximum filesystem blocks=8388608
    1 block group
    8192 blocks per group, 8192 fragments per group
    2048 inodes per group
    
    Allocating group tables: done
    Writing inode tables: done
    Writing superblocks and filesystem accounting information: done
    
    root@icymoon_dev> sudo chmod 777 disk8M.image
    ### mount这个image文件到一个目录
    root@icymoon_dev> sudo rmdir ramdisk/
    root@icymoon_dev> sudo mount -o r,w disk8M.image disk/
    mount: wrong fs type, bad option, bad superblock on /dev/loop0,
           missing codepage or helper program, or other error
    
           In some cases useful info is found in syslog - try
           dmesg | tail or so.
    root@icymoon_dev> sudo mount -o rw disk8M.image disk/
    ### 看看mount的成果
    root@icymoon_dev> df | head -n 1;df | grep icymoon
    Filesystem      1K-blocks      Used  Available Use% Mounted on
    /dev/loop0           7931        45       7886   1% /home/icymoon/disk
    

    3.2 可以开始玩了

    先copy进去个文件看看

    root@icymoon_dev> df | head -n 1;df | grep icymoon
    Filesystem      1K-blocks      Used  Available Use% Mounted on
    /dev/loop0           7931        45       7886   1% /home/icymoon/disk
    root@icymoon_dev> cp ./file /home/icymoon/disk
    root@icymoon_dev> ls /home/icymoon/disk
    file  lost+found
    root@icymoon_dev> df | head -n 1;df | grep icymoon
    Filesystem      1K-blocks      Used  Available Use% Mounted on
    /dev/loop0           7931      1802       6129  23% /home/icymoon/disk
    root@icymoon_dev> du -hs /home/icymoon/disk
    1.8M    /home/icymoon/disk
    

    文件可以正常复制进去,并且df和du显示了占了存储空间,对吧?接下来,如果我们再次挂载一个文件系统到同一个挂载点看看,

    root@icymoon_dev> sudo mount -o rw disk8M-2.image disk/
    root@icymoon_dev> mount | grep icymoon
    /home/icymoon/disk8M.image on /home/icymoon/disk type ext2 (rw,relatime)
    /home/icymoon/disk8M-2.image on /home/icymoon/disk type ext2 (rw,relatime)
    

    挂载成功,再检查一下文件大小吧

    root@icymoon_dev> sudo du -hs /home/icymoon/disk
    13K /home/icymoon/disk
    root@icymoon_dev> df | head -n 1;df | grep icymoon
    Filesystem      1K-blocks      Used  Available Use% Mounted on
    /dev/loop1           7931        45       7886   1% /home/icymoon/disk
    root@icymoon_dev> ls /home/icymoon/disk
    lost+found
    root@icymoon_dev>
    

    啊啊啊,我的文件哪里去了?查一下上一级挂载点,就会发现空间被占用了,这就是真相了

    root@icymoon_dev> df | grep home
    /dev/sda3       17970663 11536594   5518904  68% /home ##这里可以看到使用空间增长哦
    /dev/loop1           7931        45       7886   1% /home/icymoon/disk
    

    如果,我反复往一个挂载点上挂载很多次?嘿嘿,你试试呀~每次du都只能看到最新挂载上来的设备使用情况,但df...咳咳

    3.3 说点正事

    通常生产环境常见的这个问题,并不是有人无聊的恶作剧,而是设置好的分区挂载出问题没挂载上(比如当时被挂载的盘坏了神马的),然后程序写到了挂载点所在目录下,再然后,挂载被人为或者程序恢复了······,一切隐藏得天(难)衣(以)无(追)缝(查),遇到这类情况,请大家回忆一下本篇讲的东西,真相,只有一个!~~

    4 其他方法,替换df,lsof,du,ls······命令

    这个就不多说了,想怎么改,就怎么改吧

    PS:以上只供学习娱乐,如果被人揍了,或者玩飞了要从删库到跑路,别来找我,概不负责哈

    相关文章

      网友评论

          本文标题:【Linux恶作剧系列】1 如何写满磁盘而难以被发现

          本文链接:https://www.haomeiwen.com/subject/bnswwftx.html