Linux 下删点日志也能搞死人

2020-07-04 12:54:47 +08:00
 felix021

想了十天十夜不知道写些什么,那就写写面试题吧。

1

在面试应聘者的时候,我常常会问:

在 Linux 下,如何删除一个目录下的所有 log 文件?

不知道是不是我人畜无害的围笑给了应聘者我很好应付的错觉

以至于应聘者全都回答:rm *.log

追问:该目录下可能有很多子目录,如何把子目录里的 log 文件也删掉呢?

答:rm -r *.log

2

令我很意外的是,真的只有很少的应聘者能想到 find 命令。

而且想到的人也很少有记得具体用法的。

目前为止只有一个应聘者能够给出完整的命令:

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

注:这里的两个斜杠都不是笔误。

我觉得 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.txt
inode 12058942, links 1

创建一个软链接,再看看文件大小:

$ ln -s a.txt b.txt #软链接
$ stat -c 'inode %i, links %h' b.txt
inode 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.txt
inode 12058942, links 2

$ ls -l c.txt #大小 0 字节,和 a 一样
lrwxrwxrwx ... 0 ... c.txt

4

但实际生产上,遇到 “删了 log 文件、但空间不释放” 通常和软 /硬链接没有什么关系。

实战经验比较丰富的候选人会知道,这往往是因为 log 文件正被另一个进程打开。

比如在终端 1 打开 a.txt:

$ python
>>> f = open("a.txt")

然后在终端 2 可以看到该文件被 Python 打开:

$ lsof a.txt
COMMAND  PID ...     NODE NAME
python  2390 ... 12058942 a.txt

删掉 a.txt ,再查看 python 打开的文件列表:

$ rm a.txt
$ ls -l /proc/2390/fd
lrwx------ 1 user ... 00:04 0 -> /dev/pts/5
lrwx------ 1 user ... 00:04 1 -> /dev/pts/5
lrwx------ 1 user ... 00:04 2 -> /dev/pts/5
lr-x------ 1 user ... 00:04 3 -> /tmp/a.txt (deleted)

注:0 、1 、2 、3 是内核的 fd 编号。0=stdin, 1=stdout, 2=stder 。

可以看到,a.txt  被标记为已删除,但因为进程还开着它,可能会访问文件的内容,所以内核会等到进程关闭该文件(或进程退出后)才在磁盘上移除这个文件。

5

在面试中通常没有机会再问下去了,但实践中往往问题还没解决。

比如前述共享开发机,就曾遇到了磁盘空间共 800G,但用 du 命令查看,所有文件只占用了 500G 的情况。

那么:

1. 如何才能知道现在系统中有哪些文件已删除、但是仍被占用呢?

$ sudo lsof | grep deleted
COMMAND   PID  …  NAME
main   893246  …  /../nohup.out (deleted)
...

发现是有大量已经被删除、但仍被某些进程打开的 nohup.out 。

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

由于这是开发机,很简单,把进程杀掉就好了,进程退出时,内核会负责关闭文件,然后清理占用的空间。

但如果是线上服务呢?

Linux 下有一个 package 叫 logrotate,像 nginx 这些服务就是使用它来做日志切割 /轮转的。

但 nginx 是在后台持续运行的,不能为了切个日志就停止服务,所以它们是这样约定的:

  1. logrotate 执行 rename 系统调用(相当于 mv 命令)重命名日志文件;
  2. 由于 inode 不变,这时 nginx 会继续写入重命名后的日志文件;
  3. logrotate 给 nginx 发送一个 SIGHUP 信号;
  4. nginx 在收到信号后会关闭当前文件,并重新打开日志文件(即创建了新的日志文件)。

注:为什么是用 SIGHUP 而不是其他信号,以后可能会另开一篇讲讲。

这样 logrotate 出来的日志,就可以放心删除了。

对于不支持类似逻辑的服务怎么办呢?

重启大法。

如果不怕背 P0 的话,还可以这么作死:

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

注:看起来文件是清空了,但可能存在其他坑,后果自负。ftruncate 只是清空文件,如果想关闭文件,可以结合 dup 、dup2 、open 和 close 来搞事,不细说了。

6

看到这里你应该明白了为什么前面那个 find 命令不直接用 rm 了吧?

照例总结下:

  1. 可以用 find 查找文件
  2. 软链接存的是路径,硬链接共享 inode
  3. 删除被进程打开的文件,磁盘空间不会释放
  4. lsof 很好用(不只是看文件的占用)

还想知道其他有意思的面试题吗?

不如投个简历来亲身体验下:

~ 投递链接 ~

投放研发工程师(上海)

https://job.toutiao.com/s/J8DRDyG

高级广告研发工程师(北京)

https://job.toutiao.com/s/J8DNwJY

欢迎关注

   ▄▄▄▄▄▄▄   ▄      ▄▄▄▄ ▄▄▄▄▄▄▄  
   █ ▄▄▄ █ ▄▀ ▄ ▀██▄ ▀█▄ █ ▄▄▄ █  
   █ ███ █  █  █  █▀▀▀█▀ █ ███ █  
   █▄▄▄▄▄█ ▄ █▀█ █▀█ ▄▀█ █▄▄▄▄▄█  
   ▄▄▄ ▄▄▄▄█  ▀▄█▀▀▀█ ▄█▄▄   ▄    
   ▄█▄▄▄▄▄▀▄▀▄██   ▀ ▄  █▀▄▄▀▄▄█  
   █ █▀▄▀▄▄▀▀█▄▀█▄▀█████▀█▀▀█ █▄  
    ▀▀  █▄██▄█▀  █ ▀█▀ ▀█▀ ▄▀▀▄█  
   █▀ ▀ ▄▄▄▄▄▄▀▄██  █ ▄████▀▀ █▄  
   ▄▀▄▄▄ ▄ ▀▀▄████▀█▀  ▀ █▄▄▄▀▄█  
   ▄▀▀██▄▄  █▀▄▀█▀▀ █▀ ▄▄▄██▀ ▀   
   ▄▄▄▄▄▄▄ █ █▀ ▀▀   ▄██ ▄ █▄▀██  
   █ ▄▄▄ █ █▄ ▀▄▀ ▀██  █▄▄▄█▄  ▀  
   █ ███ █ ▄ ███▀▀▀█▄ █▀▄ ██▄ ▀█  
   █▄▄▄▄▄█ ██ ▄█▀█  █ ▀██▄▄▄  █▄  
16850 次点击
所在节点    推广
180 条回复
blless
2020-07-04 18:58:19 +08:00
老运维了,我是不敢随便用 rm *或者用 find 加脚本后 exec … 有相当大的概率 匹配到 /目录
CRVV
2020-07-04 19:06:37 +08:00
@msg7086
> 竟然真的有人认为面试的时候问问题是期待别人精确回答?

通常情况下当然不会这么想,但是楼主的原文里面有不少带这种含义的句子。

"令我很意外的是,真的只有很少的应聘者能想到 find 命令"
这里很明白地在表示自己期望别人回答用 find 来查找文件。

3 里面提到说有人回答说可能是删了软链接,这当然是一个正确的回答。

但是楼主随后就断言
"但实际生产上,遇到 “删了 log 文件、但空间不释放” 通常和软 /硬链接没有什么关系。"
明确地否定了这个答案。

"实战经验比较丰富的候选人会知道,这往往是因为 log 文件正被另一个进程打开。"
也就是说回答前面那种答案的人,实战经验少。

在我看来这个文件被占用的答案才是实战经验少,估计是刚毕业吧,因为线上服务的日志都是有人专门管理的,我在公司从来没听说过删日志这个操作,在自己的机器上随便玩倒是经常删。

原文里面有一句 "但如果是线上服务呢?",然后楼主在下面的回帖说是多人共用的开发机,那这完全是两码事。

如果是你可以随便折腾的开发机,那这个问题的很多前提都不成立。另外开发机上的日志可能更重要,也许是同事若干天的劳动成果。

这种问题,要么是开放的随便怎么回答都可以,那么你出的题目就不能有这么明显的局限性。比如你可以问怎样批量进行文件操作,可以问磁盘满了怎么解决。但是不能把情景人为地组合在一起,因为这样组出来的情景就不合逻辑了。
newtype0092
2020-07-04 19:07:53 +08:00
@msg7086
面对不熟悉的问题时
知识匮乏的人,只会用愤怒、讥讽掩盖自己的气急败坏
有实力的人,能从自身丰富的知识储备来寻找答案,并汲取有用经验

某些人的面试三板斧:
这个意义不大,实际场景用不到
这个不用自己写,调一下库就行
这个我没用过,用的时候百度一下就知道了

我是一点也不愿意和这些人做同事的。。。
defunct9
2020-07-04 19:14:09 +08:00
rust 的 fd 是个好工具,推荐下
xuanbg
2020-07-04 19:19:21 +08:00
日志通过 Fluentd 搞进 ES 里面去,讨厌的 log 文件就没有了。Kibana 删索引文件可方便了,查日志也方便。
msg7086
2020-07-04 19:34:58 +08:00
@CRVV #82

1) 想不到 find 可以想别的办法。
我觉得楼主实际要表达的意思是,应聘者连 find 都不知道,还要我去告诉他们,我还能指望他们给出更高水平的答案?

2) 生产上删了 log 空间不释放,这个问题其实原本应该是应聘者问面试官的。
在执行 find 和 rm 之前,应该先主动检测有没有正在运行的服务已经打开了文件。
这是需要应聘者提前要求 clarification 的,而不应该做 assumption 说 log 文件都已经被安全关闭,可以直接删除。

当然,这条是对应聘者要求过高了,所以如果没有提前问,直接回答一股脑删了,面试官补问空间不释放的时候再答打开的文件描述符我觉得也是很合理的。你也可以回答说可能是 ZFS 文件系统在后台缓慢释放空间,等等。

3) 线上服务日志有专人管理,你自己连日志都不碰,说明你实战经验丰富?
事情都甩锅给别人来做说明实战经验多,事情自己来做说明实战经验少,这个说法我还是头一次听到,挺新鲜的。
你们招的都是高中毕业生么,那种没摸过服务器的「实战经验多」的人吧,我们这些玩过十几年 Linux 实战经验少的人肯定马上就被刷掉了。
zk8802
2020-07-04 19:36:57 +08:00
谢谢楼主写文章分享这些不算基础的基础知识,很开眼界。太多人只纠结在如何从文章中写得不完善的地方入手开喷,而不是取文章之精华。这些大部分都是 losers,希望楼主不要在意。
freelancher
2020-07-04 19:55:09 +08:00
????运维基础啊。和研发有毛线关系???

你把工资提到 2W 。别人的回答层次就上来了。估计就几千块钱的岗位。
E1n
2020-07-04 20:08:30 +08:00
自信又回来了 w
CRVV
2020-07-04 20:11:08 +08:00
@msg7086

2.
楼主的原文里可没有说要检查文件有没有关,而且楼主还给出了文件没关情况下释放磁盘空间的方法。
你觉得应聘者可以有更高级的回答,那当然是好事。但是楼主作为面试官,他给出的答案就是一股脑删了,而且本来在用的文件,用 rm 不会删除的东西,也被删了。我喷的就是他预期的这个答案。

3.
我的原文是
"在我看来这个文件被占用的答案才是实战经验少,估计是刚毕业吧,因为线上服务的日志都是有人专门管理的,我在公司从来没听说过删日志这个操作,在自己的机器上随便玩倒是经常删。"
被你曲解成了
"事情都甩锅给别人来做说明实战经验多,事情自己来做说明实战经验少"

楼主说删了一个日志文件,磁盘空间没被释放,出现这个情况的原因是这个文件还在被占用。

正式服务器被占用的日志文件不能删,运维不可能在工作中发现,欸我删了一个日志文件怎么磁盘没释放结果是日志文件还在被占用。
有专人管理的意思是说他不能让服务器出现日志把磁盘占满的情况,这都有监控的,快满了要报警,报警了就要解决,这是他的工作。如果都已经磁盘满了需要手动 rm 文件或者 echo> 了,那这系统已经病入膏肓了,这是不能允许出现的情况。不是说现在磁盘满了系统挂了这都是运维的事和我没关系。

你玩过十几年 Linux,知道删除一个被打开的文件不会释放磁盘空间,但你大概率不是通过删日志文件学到这件事情的。
但是,楼主已经给定了线上服务器日志文件管理这个场景,在正常操作服务器的前提下,就已经排除掉了文件没关这种可能性。但还说可能是这样,那我只能说是没经验了。


> 请详细描述如何用不同的方式正确地储存和清理日志

这完全是另外一个问题,楼主原本的问题是 "在 Linux 下,如何删除一个目录下的所有 log 文件?"
如果我看到这个问题,我不可能回答 "请详细描述如何用不同的方式正确地储存和清理日志"。
面试官当然可以问 "请详细描述如何用不同的方式正确地储存和清理日志"。
但如果你想问的是这个问题,然后实际问的是 "在 Linux 下,如何删除一个目录下的所有 log 文件",那这正是我要喷的点。
petelin
2020-07-04 20:26:31 +08:00
我也不支持楼主。 没意义的问题,具体场景只有你知道,你不说我怎么知道文件夹下面还有不是日志的东西?但是你就默认有 那我只能说你开心就好
HunterPan
2020-07-04 20:32:02 +08:00
不喜欢这种方式,难道面试不是问对方最擅长的么?计算机知识太多了,一方面掌握的很好就不错了.
20150517
2020-07-04 20:33:58 +08:00
牛逼啊,推公众号么就推好了,一个个怼下来是怎么回事
rockyou12
2020-07-04 21:01:53 +08:00
@felix021 抬杠哪个不会?你 ssh 客户端怕安全问题,咋没整堡垒机呢?堡垒机 dashboard 也没有看不到文件系统的把,那你折腾啥呢?

----
建议多思考和理解别人存在的现实问题,而不是只活在自己臆想的世界里。

p.s. 被种过马的 ssh 客户端,比如 putty 和 xshell 我通常选择敬而远之。
papa2
2020-07-04 21:40:04 +08:00
楼主想通过提问知道到候选人知识面的广度和深度,那提问就需要开放式才对,对于很多候选人来说,给出最简单的原理和解决思路就好了,因为你提问就没用让人发散思维去回答,难道不回答就是没想到?
miaowumiaowu
2020-07-04 22:05:39 +08:00
分享到了 bupt 系群里被喷成了筛子 TAT......于是不建议本校同学们投这个内推......感觉要是进去了上级会有点 particularly clueless, or negatively biased, or both......
webassembly
2020-07-04 22:14:06 +08:00
我擦 咋就喷起来了。如果基础不够好,思维不够开放,这种面试体验可能会很差,楼主作为面试官确实是应该要适当的引导。但是单这篇文章来说,这个问题展开的过程是很棒的,我从中学会了一些解决问题的思路和根本不了解的知识点。
tlday
2020-07-04 22:39:03 +08:00
行文风格让我知道了这几个二维码的目标用户水平。
不太喜欢知识密度这么低的技术文章,抱歉。
22yune
2020-07-04 22:58:35 +08:00
首先,楼主文章写的蛮好的;

其次,下面喷的也有道理。

希望大家发言都能尽量友善点。

对于被评论的人,可以想一下,没有人针对谁,大家评论的是言论展示出的观点、态度或什么特质。不需要有被冒犯的感觉。
Jat001
2020-07-04 23:07:27 +08:00
每个人的知识面都是有限的,这种 google 一下几分钟就能解决的事不知道可以换点别的问题问。

说个今天遇到个面试,python 岗位。我不是科班出身,从来没系统地学过计算机科学,很多技术名词都没接触过,但这从来没妨碍过我写代码、完成任务,而且一般开发的时候也没人会交流这些东西。

1. flask 的上下文
我知道 app_context 这种东西,也知道什么时候用 current_app request session g 等变量,但你非要问我 flask 的上下文是干啥的,不好意思,我给不出一个教科书似的答案。

2. 多态
第一次听说,回头查了下,这不就是面向对象吗,我虽然不知道什么是多态,但我会写 class,知道什么是继承,也会用重载。

3. 闭包
我只听说过 js 里的闭包,一直认为这玩意跟匿名函数是一回事,平常也只用过 lambda,后来查了才知道有区别。

就问了这三个问题就得出了一个我基础不行的结论,合着所谓的基础就是背技术概念吗。我平常遇到不知道的名词是会去看看,但我从来不背概念,因为写代码不需要背概念,知道什么时候用什么不就完了。pm 给我需求,我提供解决方案并实现,这才是我的工作,而不是向 pm 解释我的代码。

最让我恶心的是,面试的时候另一个不负责问话的人一直在小声逼逼,“这都不知道”,“那还聊什么”,要不是问话的人比较客气,我 tm 都想怼他,你这么牛逼,那来说说 pytorch 跟 caffe 之间的区别是什么。虽然是远程面试,但他在那里逼逼啥我听得很清楚,有什么意见不能面试结束再聊?我估计旁边那个人是领导,问了这三个问题就结束了。

回到楼主的问题,我 find 用得多比较熟,但我不会因为别人没用过 find 而觉得他技术不行,甚至很多开发都不用 unix 而是 windows,你问他们这问题有啥意义吗?而且 linux 下这么多命令你不看 manual 不看 help 能熟练用几个?就算天天用的命令你能马上告诉我每个参数代表什么吗?

不要以为自己会点东西就觉得这是理所当然的,其他人也应该会,知识面越广才会发现未知的东西也越多,不知道不可怕,会点东西就沾沾自喜才可怕。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/687093

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX