公众号旧文

为什么 Windows 经常提示文件被占用,但 Linux 却几乎从来不会?

作者:胖子阅读 —

相信屏幕前的你,一定遇到过下面的这种情况。

某天你在编辑一个 Word 文档,还没保存。

这时你想把这个文档发到微信,或者移动到别的文件夹。

系统就会提示:

文件正在被另一个程序使用,请关闭程序后重试

近来,在接触 Linux 后,我却发现 Linux 几乎从来不会弹这种提示。

甚至 Linux 连正在运行中的程序文件本身都可以直接删除。

原来这背后,有一个 Windows 和 Linux 非常巨大的底层区别。

一、Windows :程序和文件绑定

Windows 的逻辑是程序正在使用这个文件。

于是系统会对很多文件直接加锁。

所以只要程序还开着,你就经常会看到文件被占用。

很多软件升级时,Windows 还会提示请重新启动计算机。

因为系统没法直接替换正在使用的文件。

二、Linux 世界则完全不同

Linux 的设计理念非常反直觉。

很多人会以为:

磁盘上的文件 = 正在运行的程序

而 Linux 里真正运行的,很多时候已经不是文件了,而是内存里的进程。

程序启动后,代码、数据、状态,很多都已经加载进内存。

后面你再去删除文件、覆盖文件、替换文件,很多情况下根本不会影响运行中的旧进程。

三、程序删了,网站还能继续运行

如果你在 Linux 下:

rm /usr/sbin/nginx

很多人的第一反应肯定是网站会立刻挂掉。

但实际上 Nginx 还能继续正常运行。

因为真正工作的是内存里的 nginx 进程,而不是磁盘上的:

/usr/sbin/nginx

也就是说虽然文件已经被删了。

但进程还活着,于是网站照样还能访问。

四、Linux 删除的,只是名字

这背后还有一个特别关键的事情。

Linux 删除文件时,真正删除的东西,很多时候只是文件名。

Linux 内核真正关心的其实是 inode,也就是文件对象本身。

只要还有进程正在使用这个 inode,即使文件名已经没了。

内核依然不会真正释放数据,所以程序还能继续运行。

甚至:

lsof | grep deleted

还能看到:

(deleted)

的程序。

也就是说文件已经没有名字了,但进程依然活着。

五、Linux 为什么很少出现文件被占用

因为 Linux 默认并不像 Windows 那样强制锁定文件。

Linux 更像是在说:你爱删就删,后果自己承担。

于是你可以删除文件、替换文件、覆盖程序,内核基本不会阻止你。

这让 Linux 非常灵活,很多服务可以做到热更新、不停机部署。

但代价就是,Linux 特别容易出现一种情况:

磁盘上的文件和内存里的程序,根本不是同一个版本。

六、今天我就踩了一个大坑

我有个 Python 写的 Tailscale 监控脚本。

平时一直通过 systemd 在后台运行。

4 月 19 日我重构过一次代码,用了 Python 3.10 的新语法:

str | None

但问题是这台 Debian 11 服务器上的 Python 是 3.9

我原本以为,代码改坏了,程序就应该立刻出问题。

但神奇的是之后十几天,这个监控脚本居然一直运行正常。

我也完全没意识到代码已经不兼容了。

直到 4 月 30 日,服务器因为某些原因自动重启。

这一次 Python 3.9 才终于重新读取了磁盘上的新代码。

结果程序当场暴毙,日志里开始疯狂刷:

TypeError: unsupported operand type(s) for |: 'type' and 'NoneType'

这我才意识到运行中的程序,很多时候是内存里的那个,而不是磁盘上保存的新文件。

扩展阅读:

关于“胖子百科”被“网络技术联盟站”多次洗稿的说明

关于“胖子百科”被瑞哥小号“网络技术干货圈”更多次洗稿的说明

给 网络技术联盟站 瑞哥 的一封公开信