Closed Worldy-MCX closed 10 months ago
这个 errno 挺怪的,也得支持下。参考着 coreutils 的 cp 指令完善了 copy_file_range 不受支持的时候的处理方式,可以试试 https://github.com/TISUnion/PrimeBackup/actions/runs/7262053115 (注:有 bug,见下面评论)
尝试复现了一下这个 issue,发现无法复现
环境:
目录结构(未列出全部内容):
/tmp/minecraft_server -> /mnt/d/test/minecraft_server/
├── 1.20.1_fabric_lmg # MC 服务器工作目录
│ ├── minecraft_server.jar
│ ├── server.properties
│ └── world
└── mcdr_server # MCDR 工作目录
├── 1.20.1_fabric_lmg -> /mnt/d/test/minecraft_server/1.20.1_fabric_lmg/
├── config
├── pb_files
└── config.yml
其中,D 盘(/mnt/d
)是 windows 下普通的一块 NTFS 文件系统的磁盘,/tmp
为 ext4 文件系统
配置文件 - MCDR:
working_directory: '1.20.1_fabric_lmg'
配置文件 - PB:
"backup": {
"source_root": "./1.20.1_fabric_lmg",
"targets": [
"world"
],
"ignored_files": [
"session.lock"
],
"follow_target_symlink": true,
"hash_method": "xxh128",
"compress_method": "zstd",
"compress_threshold": 64
},
在 world 文件夹中手动创建 <64B 的小文件,确保 PB 未对其进行压缩,从而走到 file_utils.copy_file_fast
逻辑
经测试,可以正常创建备份、正常回档,未发生任何错误
使用下面脚本在 /mnt/d
磁盘下尝试调用 os.copy_file_range
,未见任何报错
import os
with open('1.txt', 'w') as f:
f.write('aaaaa')
with open('1.txt', 'rb') as f1, open('2.txt', 'wb') as f2:
while os.copy_file_range(f1.fileno(), f2.fileno(), 2 ** 30):
pass
print('ok')
/mnt/d/test$ python3 test_copy_file_range.py
ok
/mnt/d/test$ cat 2.txt
aaaaa
这个可以正常回档https://github.com/TISUnion/PrimeBackup/issues/7#issuecomment-1862725029
WSL 发行版:Ubuntu 18.04.6 LTS
排除权限问题
python3 test_copy_file_range.py
Traceback (most recent call last):
File "/mnt/d/test/test_copy_file_range.py", line 7, in <module>
while os.copy_file_range(f1.fileno(), f2.fileno(), 2 ** 30):
OSError: [Errno 38] Function not implemented
/mnt/d/test$ sudo python3 test_copy_file_range.py
Traceback (most recent call last):
File "/mnt/d/test/test_copy_file_range.py", line 7, in <module>
while os.copy_file_range(f1.fileno(), f2.fileno(), 2 ** 30):
OSError: [Errno 38] Function not implemented
/mnt/d/test$ su -
Password:
/mnt/d/test# python3 test_copy_file_range.py
Traceback (most recent call last):
File "/mnt/d/test/test_copy_file_range.py", line 7, in <module>
while os.copy_file_range(f1.fileno(), f2.fileno(), 2 ** 30):
OSError: [Errno 38] Function not implemented
3次测试文件内容均为以下结果
/mnt/d/test$ cat 1.txt
aaaaa
/mnt/d/test$ cat 2.txt
/mnt/d/test$ls -l
-rwxrwxrwx 1 test test 5 Dec 20 02:07 1.txt*
-rwxrwxrwx 1 test test 0 Dec 20 02:07 2.txt*
-rwxrwxrwx 1 test test 213 Dec 20 02:03 test_copy_file_range.py*
难道是python版本问题?明天再试试
Python 3.9.18,test_copy_file_range.py
运行正常
/mnt/d/test$ df -T .
Filesystem Type 1K-blocks Used Available Use% Mounted on
drvfs 9p 1463216468 894235964 568980504 62% /mnt/d
/mnt/d/test$ python3.9 -V
Python 3.9.18
/mnt/d/test$ python3.9 test_copy_file_range.py
ok
/mnt/d/test$ cat 2.txt
aaaaa
环境:
提问:win下python3有没有copy_file_range
这个函数
尝试:win10下python的两个版本都有报错
PS D:\test> python3.9.exe -V
Python 3.9.13
PS D:\test> python3.9.exe .\test_copy_file_range.py
Traceback (most recent call last):
File "D:\test\test_copy_file_range.py", line 7, in <module>
while os.copy_file_range(f1.fileno(), f2.fileno(), 2 ** 30):
AttributeError: module 'os' has no attribute 'copy_file_range'
PS D:\test> python3.10.exe .\test_copy_file_range.py
Traceback (most recent call last):
File "D:\test\test_copy_file_range.py", line 7, in <module>
while os.copy_file_range(f1.fileno(), f2.fileno(), 2 ** 30):
AttributeError: module 'os' has no attribute 'copy_file_range'
提问:copy_file_range
函数是在这个/usr/local/lib/python3.9/os.py模块内吗,如果是的话我在win下(C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.10_3.10.3056.0_x64__qbz5n2kfra8p0\Lib\os.py)和wsl下的os.py
内都没有找到copy_file_range
这个函数.
要是提问的有不对的请指出来,谢谢
win下python3有没有copy_file_range这个函数
https://docs.python.org/zh-cn/3/library/os.html#os.copy_file_range
提问:copy_file_range 函数是在这个/usr/local/lib/python3.9/os.py模块内吗,如果是的话我在win下(C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.10_3.10.3056.0_x64__qbz5n2kfra8p0\Lib\os.py)和wsl下的os.py内都没有找到copy_file_range这个函数.
os
模块的 copy_file_range
是 c api 实现的,没有 .py 编写的代码。要看具体实现,你需要翻看 cpython 的源码
明白了谢谢,找了好久没找到wsl相关的copy_file_range系统调用,无奈问了AI说wsl不支持os.copy_file_range函数.是不是AI忽悠我 有时间再研究吧,估计现在看源码很困难了.
若需要,这里是 Python3.9.18 copy_file_range 的源码:https://github.com/python/cpython/blob/376d66eb5080cf8076d767b0916c103463343963/Modules/posixmodule.c#L10419
在 Ubuntu 18.04.6 LTS 的 WSL 发行版中,编译 Python 3.9.18 后测试 test_copy_file_range.py
,运行正常
/mnt/d/test$ cat /etc/os-release | grep VERSION=
VERSION="18.04.6 LTS (Bionic Beaver)"
/mnt/d/test$ uname -r
5.15.133.1-microsoft-standard-WSL2
/mnt/d/test$ python3.9 -V
Python 3.9.18
/mnt/d/test$ python3.9 test_copy_file_range.py
ok
环境同 https://github.com/TISUnion/PrimeBackup/issues/7#issuecomment-1863290804 ,只是换成了 Ubuntu 18.04.6
发行版ubuntu使用wsl1安装,后来进行一次wsl --update
虽然升级了wsl的内核,但是ubuntu发行版的内核没有跟着升级.还在使用wsl1,而不是wsl2,导致内核不支持从而无法使用copy_file_range()
也就是说wsl1不支持copy_file_range()
,wsl2支持copy_file_range()
最开始使用这个命令来查看当前系统版本是错误的,这里只是wsl的版本
PS C:\Users> wsl --version
WSL 版本: 2.0.9.0
内核版本: 5.15.133.1-1
WSLg 版本: 1.0.59
MSRDC 版本: 1.2.4677
Direct3D 版本: 1.611.1-81528511
DXCore 版本: 10.0.25131.1002-220531-1700.rs-onecore-base2-hyp
Windows 版本: 10.0.22631.2861
进入wsl的ubuntu系统后实际查看的内核版本
wsl -d ubuntu
~$ uname -r
4.4.0-22621-Microsoft
使用wsl -l -v
查看发行版,发现VERSION
为1
PS C:\Users> wsl -l -v
NAME STATE VERSION
* Ubuntu Running 1
使用以下命令重新导入后
# 导出发行版
wsl --export ubuntu G:\data\wsl\images\ubuntu-18.04.6-LTS.tar
# 注销并卸载发行版
wsl --unregister ubuntu
# 导入发行版
wsl --import ubuntu-18.04.6-LTS G:\data\wsl\ubuntu G:\data\wsl\images\ubuntu-18.04.6-LTS.tar --version 2
可以成功运行test_copy_file_range.py
脚本
PS C:\Users> wsl
~$ uname -r
5.15.133.1-microsoft-standard-WSL2
~$ python3 test_copy_file_range.py
ok
~$ cat 2.txt
aaaaa
环境
WSL 版本: 2.0.9.0 内核版本: 5.15.133.1-1 WSLg 版本: 1.0.59 MSRDC 版本: 1.2.4677 Direct3D 版本: 1.611.1-81528511 DXCore 版本: 10.0.25131.1002-220531-1700.rs-onecore-base2-hyp Windows 版本: 10.0.22631.2861
mcdreforged 2.12.1 PrimeBackup 1.5.0 Python 3.9.18
日志
配置文件
./config/prime_backup/config.json
./config.yml
MCDR工作目录:~/minecraft_server/mcdr_server/
软链接目录