一次系统升级之后,我的许多 Python 程序突然开始报错:
[...] File "/usr/lib/python3.8/site-packages/pkg_resources/__init__.py", line 2762, in _get_metadata for line in self.get_metadata_lines(name): File "/usr/lib/python3.8/site-packages/pkg_resources/__init__.py", line 1415, in get_metadata_lines return yield_lines(self.get_metadata(name)) File "/usr/lib/python3.8/site-packages/pkg_resources/__init__.py", line 1405, in get_metadata value = self._get(path) File "/usr/lib/python3.8/site-packages/pkg_resources/__init__.py", line 1609, in _get with open(path, 'rb') as stream: PermissionError: [Errno 13] Permission denied: '/usr/lib/python3.8/site-packages/Telethon-1.17.4-py3.8.egg-info/PKG-INFO'
WTF 滚坏了!立即回滚!
回滚完之后,我开始调查这个事件——因为 [archlinuxcn] 的这个包是我管的呀。而且我记得之前也遇到过一次类似的情况,当时没有深究。
检查一下软件包里的文件的权限:
>>> tar tvf python-telethon-1.17.4-1-any.pkg.tar.zst | grep PKG-INFO -rw------- root/root 3659 2020-10-24 10:05 usr/lib/python3.8/site-packages/Telethon-1.17.4-py3.8.egg-info/PKG-INFO >>> tar tvf python-telethon-1.17.4-1-any.pkg.tar.zst | grep -- ---- -rw------- root/root 3659 2020-10-24 10:05 usr/lib/python3.8/site-packages/Telethon-1.17.4-py3.8.egg-info/PKG-INFO -rw------- root/root 12078 2020-10-24 10:05 usr/lib/python3.8/site-packages/Telethon-1.17.4-py3.8.egg-info/SOURCES.txt -rw------- root/root 1 2020-10-24 10:05 usr/lib/python3.8/site-packages/Telethon-1.17.4-py3.8.egg-info/dependency_links.txt -rw------- root/root 27 2020-10-24 10:05 usr/lib/python3.8/site-packages/Telethon-1.17.4-py3.8.egg-info/requires.txt -rw------- root/root 15 2020-10-24 10:05 usr/lib/python3.8/site-packages/Telethon-1.17.4-py3.8.egg-info/top_level.txt
好奇怪,Telethon 这些包信息文件怎么只让 root 读了呢?
从 PyPI 上下载 Telethon 的原始 tar 归档回来看看,发现最近几个版本里,文件权限全部只有自己可以读(-rw-------
),而所有者是 u0_a167/10167
。开发者突然在 Android 系统上打包了呢……安装的时候,部分文件的权限被保留了下来(Arch Linux 打包时强烈反对使用 root 权限执行,因此我用 devtools 打包,解包部分自然是普通用户操作的,所有者无法被保留)。
然后我又看了一下之前的版本,哦豁,所有者成开发者的 id 了,但是有三个版本的 pyc 文件,还有好几个 pyc 文件都是 -rwxrwxrwx
。大概系统上的低权限用户可以去改改,然后看谁跑 Telegram 机器人就拿谁的权限?
经过跟开发者的讨论,最终干掉了 pyc 文件,也不在 Android 上打包了。777 权限问题还待解决。不过我更在意的是,为什么会发生这种状况呢?setuptools 干嘛不修一修呢?别的工具创建的用于发布的 tar 归档会不会有类似的问题呢?
结果找了找,发现 setuptools 前年就有人报告这个问题,但是并没有解决。行吧,我打包时统一修正一下权限好了……
下一个 GitHub 生成的 tar 归档看看?咦,-rw-rw-r-- root/root
,是处理过了么?啊对,git archive 生成的包是怎么样的?去试了试,原来一样的啊。看来 git 想到了这个问题并且处理了,只是 002 的 umask 有点意外。
Arch Linux 为了普通用户打出文件为 root 所有的 tar 归档使用了 fakeroot,那么 git 是怎么实现的呢?翻了翻代码,git 是自己生成 tar 文件的,写死了所有者是 root/root,但是权限位还是有专门的 umask,默认是 002。可以配置,比如git config --global tar.umask user
一下,就会取当前 umask 作为 tar 归档里文件的 umask 了。
至于传统的 GNU autotools 构建系统创建的 tar 归档,我也创建了一个看了一下,并没有特殊处理,跟手动跑 tar 一样。