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

欢迎关注

   ▄▄▄▄▄▄▄   ▄      ▄▄▄▄ ▄▄▄▄▄▄▄  
   █ ▄▄▄ █ ▄▀ ▄ ▀██▄ ▀█▄ █ ▄▄▄ █  
   █ ███ █  █  █  █▀▀▀█▀ █ ███ █  
   █▄▄▄▄▄█ ▄ █▀█ █▀█ ▄▀█ █▄▄▄▄▄█  
   ▄▄▄ ▄▄▄▄█  ▀▄█▀▀▀█ ▄█▄▄   ▄    
   ▄█▄▄▄▄▄▀▄▀▄██   ▀ ▄  █▀▄▄▀▄▄█  
   █ █▀▄▀▄▄▀▀█▄▀█▄▀█████▀█▀▀█ █▄  
    ▀▀  █▄██▄█▀  █ ▀█▀ ▀█▀ ▄▀▀▄█  
   █▀ ▀ ▄▄▄▄▄▄▀▄██  █ ▄████▀▀ █▄  
   ▄▀▄▄▄ ▄ ▀▀▄████▀█▀  ▀ █▄▄▄▀▄█  
   ▄▀▀██▄▄  █▀▄▀█▀▀ █▀ ▄▄▄██▀ ▀   
   ▄▄▄▄▄▄▄ █ █▀ ▀▀   ▄██ ▄ █▄▀██  
   █ ▄▄▄ █ █▄ ▀▄▀ ▀██  █▄▄▄█▄  ▀  
   █ ███ █ ▄ ███▀▀▀█▄ █▀▄ ██▄ ▀█  
   █▄▄▄▄▄█ ██ ▄█▀█  █ ▀██▄▄▄  █▄  
16858 次点击
所在节点    推广
180 条回复
mingl0280
2020-07-04 23:18:09 +08:00
这个发帖的估计是没什么运维经验的在校生?打肿脸还要充胖子那种,自己需求非常不明确还要别人猜意思,而且某些操作让人目瞪口呆(例如什么日志打开中还删日志),更不要提那个 find /home+cron 操作简直是作死的神来之笔,用户在自己子目录下建一个 ln 到 /usr 的目录你就修机器去吧!
Jat001
2020-07-04 23:22:10 +08:00
@newtype0092
面对熟悉的问题时
知识匮乏的人,会迫不及待得炫耀自己:这题我会
而有实力的人,会把自身丰富的知识储备分享给别人

这个意义不大,实际场景用不到
用不到就是用不到,老板招你不是来实现用不到的场景的

这个不用自己写,调一下库就行
有库为什么还要自己造轮子?你每天都自己造轮子的话,工作还做不做?

这个我没用过,用的时候百度一下就知道了
每个人都有自己不懂的东西,用的到或者感兴趣的就去了解,用不到又不感兴趣的为什么要去了解?
wwhc
2020-07-04 23:26:44 +08:00
Linux 下 log 文件并没有统一的文件名后缀,只是大部分都用.log 而已,不是.log 后缀的很多。如果遇到 log 文件过大,我首先做的是确定 log 文件是由哪个进程生成的,检查这个进程的启动方式、日志轮换脚本,尽量利用自带的轮换日志脚本,实在没有才自己写脚本处理

楼主的这类面试方式,不大能招到有比较多运维经验者
hatebugs
2020-07-04 23:44:16 +08:00
看这个帖子一直在前面,又来看了评论,作为一个互联网运维,我觉得楼主的题做面试考核没啥问题。日常见到的互联网的中级开发,有些经常删了文件还来问为啥沒释放,这个问题从实践经验,和对操作系统的深度,都有面试者自由发挥的空间。
rockuw
2020-07-05 00:11:26 +08:00
看了大家的讨论,最近也做了不少技术面试,从面试官角度说一下我的看法。

面试官想从面试中考察哪些能力?

1. 技术能力: 包括广度和深度,其中深度是尤其重要,知其然还要知其所以然
2. 学习能力: 对于不熟悉的领域,是怎么从了解到掌握的,这个过程中最能体现逻辑性
3. 性格特质: 乐观 /皮实 /自省

这 3 个方面的权重不同的面试官把握的比例不一样,我的标准大概是 40:40:20,供参考。

好了,回到楼主的这些具体问题,我认为,如果面试者:

1. 能够在回答中讲出 find/xargs,广度加 1 分
2. 能够在回答中讲出软链接 /硬链接的区别 /进程对 fd 的管理机制,深度加 10 分
3. 能够在回答中讲出日志 rotate,广度加 1 分
4. 能够在回答中讲出日志 rotate 的实现原理,深度加 5 分
5. 能够在回答中讲出 ELK 的一些使用经验,广度加 1 分
6. 能够在回答中讲出 ELK 的一些设计要点(它解决了什么问题,为什么要这么解决,业界有哪些解决方案,各有什么优缺点),深度加 10 分

所以大家不要纠结于"find"是不是标准答案这个点了,面试的过程是双方对焦的过程,面试官希望能够看到 /挖掘出你的亮点。

至于上面提到的学习能力和性格特质的考察其实更难,我也还没有太多的经验就不多说了。

最后,给我们团队打个广告,欢迎有兴趣的同学一起来共建业界最好的 Serverless 平台: https://v2ex.com/t/651136
zthxxx
2020-07-05 01:12:21 +08:00
@Jat001 #100 兄弟,你这个确实就叫基础知识欠缺

来面试的明说不是科班出身,基础知识又没有,又说反正能写出代码完事,很容易让面试官想到这人培训班来的
Jat001
2020-07-05 01:26:33 +08:00
@zthxxx 我是野路子自学的,一天培训班都没上过,我不信培训班不教基础知识和面试方法。我干这行 5 6 年了,也有科班出身的同事,但工作中没人交流基础知识,都是 API 、文档、自己看代码。业务为主,能写代码、少出 bug 就行。
felix021
2020-07-05 01:32:54 +08:00
@Jat001 术语存在的意义是提高交流的效率。就像 GoF 里面的那些模式,名字本身叫什么无所谓,关键是达成共识后,交流的双方可以用简洁的语言完成高效的信息传递。

培训班的目的是就业,基础知识的 ROI 太低,课程里可能会涉及,但一定不会深究。因此出身培训班的人,通常天花板会比科班出身低,这就是大厂不愿意招那些培训班出身程序员的原因。
Jat001
2020-07-05 01:38:00 +08:00
@felix021 贵司工作中真的会交流术语吗?大部分公司不都是业务导向吗?需求确定了,leader 顶多跟你研究一下系统架构怎么设计,但没人会管你用什么设计模式写代码吧?
royzxq
2020-07-05 01:41:15 +08:00
我去,我说怎么看行文这么有我条甚至部门既视感,再看头像更眼熟了。

打开 lark 一搜果然. hhhh 强烈建议开发机上可以部署 pm2. 共享的开发机 pm2 我尝试了但是起不来
Jat001
2020-07-05 01:42:57 +08:00
@felix021 另外天花板是什么,大厂的代码就比小公司的优雅?不都是写业务代码?大厂不愿意招培训班出身的不是因为大厂资源丰富,科班的都招不过来,根本看不上培训班出来的吗?
blless
2020-07-05 01:50:29 +08:00
@Jat001 兄弟,我也是非科班出身,以前也是抱着你差不多念头。
之所以觉得自己不了解这些概念,没听过一些名词无非就是觉得自己不用这些也能解决问题。你肯定有解决问题的能力。我觉得你还没遇上解决问题能力跟你一样,基础比你扎实的多的人。我也是遇到这样的人的时候才觉得自己被全方位碾压,我也不说啥难听的。但是听我一句劝,想好好吃程序这碗饭,还是要把很多基础,概念,理论都理解贯通得好
royzxq
2020-07-05 01:54:30 +08:00
原来还有删掉了空间不释放的情况呀,学到了
NVDA
2020-07-05 02:02:19 +08:00
作为一个 someone does everything 很好奇什么测试服务会打几十个 g 的 log...
felix021
2020-07-05 02:04:56 +08:00
@Mirage09 用线上流量来批量测试的时候,测试环境 log level 低,或者测试分支添加了大量测试日志。
necomancer
2020-07-05 02:05:15 +08:00
@CRVV
@mingl0280
大佬说得好啊!
Jat001
2020-07-05 02:06:12 +08:00
@blless 我认同你的观点,解决问题能力强、基础又扎实的人确实牛逼。但我走上编程这条路本来不是为了吃饭,只是对用技术解决问题很感兴趣,另外我本身对死记硬背也深恶痛绝,所以我还是会坚持实用主义直到对编程失去兴趣的那一天。
NVDA
2020-07-05 02:07:39 +08:00
@felix021 一般情况下我们就直接换机器了
WittBulter
2020-07-05 02:13:10 +08:00
帖子内容的技术比重是有的,但是我一看到字节 /头条+面经之类的内容,我就知道下面要打成一片 😂....
字节的同学们好像特别喜欢营造技术媚俗感 (我没有评论好坏)
felix021
2020-07-05 02:20:25 +08:00
@WittBulter 每个人的感受都不一样,有些人觉得很有帮助,有些人觉得很浅,有些人觉得有些内容不合适,其实都很正常; 头疼的是那些自以为绝对正确就开喷的,反驳嘛浪费时间,不反驳嘛又显得怂,太难了。

另外,你说的这个技术媚俗感,我不是很能 get 。不过头条招聘的整体标准确实感觉比其他厂高,可能是你所说的这个媚俗感的原因?(所以招人真的难)

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

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

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

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

© 2021 V2EX