在介绍如何安全删除文件之前,先介绍一下Linux下是如何删除文件的.Linux是通过link的数量来控制文件删除的,当一个文件不存在任何link的时候,这个文件才会被删除.
    一般情况下一个文件会有两个link计数器:i_count和i_nlink. i_count表示该文件目前被调用的数量,i_nlink指的的是文件的硬链接数目.也就是说当一个文件被某一个进程引用时,对应的i_count数量会增加;当给文件创建硬链接时,对应的i_nlink数目会增加.Linux下的rm命令实际上就是调用的unlink系统函数,rm操作就是将i_nlink数量减1,将文件名到inode的链接删除.


rm - remove files or directories


如上小节所述,rm删除文件只是减少了i_nlink的数量并且把文件名到inode的链接删除,那么使用rm删除文件就存在两个问题:

  • 如果进程引用了该文件,那么使用rm删除后,进程依然可以读写文件,并且磁盘空间不会释放,对于此种情况,kill掉相应的进程就可以解决.
  • rm删除文件,只是减少了link计数器,文件block并没有真正的擦除,这对于某些机密数据来说不可取的,很容易利用Linux下的debugfs等工具恢复.这个时候就需要用到另外一个工具:shred.

shred - overwrite a file to hide its contents, and optionally delete it


shred的功能覆盖文件,即使使用一些高级的文件恢复工具也不能恢复.


    -f, --force 必要时修改权限以使目标可写
    -n, --iterations=N 覆盖N 次,而非使用默认的3 次
        --random-source=file 从指定文件中取出随机字节
    -s, --size=N 粉碎数据为指定字节的碎片(可使用K、M 和G 作为单位)
    -u, --remove 覆盖后截断并删除文件
    -v, --verbose 显示详细信息
    -x, --exact 不将文件大小增加至最接近的块大小
    -z, --zero 最后一次使用0 进行覆盖以隐藏覆盖动作

shred 默认是不删除文件的,如果要删除文件请加上-u参数.需要注意的一点是对于一些日志文件系统,shred操作并不一定生效.如果希望磁盘里面的文件永远不能恢复,那么还是进行物理销毁比较靠谱.


truncate - shrink or extend the size of a file to the specified size


truncate是用来解决另外一个问题的,假设你的磁盘上存在一个1T的日志文件,直接rm删除,那么大多数情况下会悲剧,rm期间磁盘IO打满,CPU负载过高…..这个时候选用truncate是不错的选择,用法如下:


       -c, --no-create
              do not create any files

       -o, --io-blocks
              treat SIZE as number of IO blocks instead of bytes

       -r, --reference=RFILE
              base size on RFILE

       -s, --size=SIZE
              set or adjust the file size by SIZE


删除这个1T的日志文件,可以写一个简单的shell循环脚本,每次删除固定的大小,可以平滑/安全的的删除该文件.示例如下:

    for ((i=1000;i>0;i=i-5))
    do
        echo "truncate $iG ......"
        truncate -s ${i}G AAA.log
        sleep 5
    done
    rm AAA.log


另外推荐关于Secure Erase 的Paper两篇

Secure Deletion of Data from Magnetic and Solid-State Memory
ATA Secure Erase