公众号旧文
为什么 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'
这我才意识到运行中的程序,很多时候是内存里的那个,而不是磁盘上保存的新文件。
扩展阅读: