我尝试了两个方案:
1、pysmb库。总是出错,而且很难排查。
2、smbclient 命令。用 python os 库执行 smbclient 命令时,如果有多条的话,构造起来偏复杂。
所以还是 mount 命令比较方便。
代码中注释了需要执行的几条命令,可以现在命令行尝试是否成功,再用 python 代码执行。
import subprocess, os, time
# SMB共享的参数
smb_share = "//11.11.11.11/共享"
mount_point = "/mnt/smb"
username = "admin"
password = "11111111"
password_me = "11111111"
source_file = f"{mount_point}/aaaaaaaaaaaaaaaaaaaaaaa/aaaaaaaaaaaaaaaaaa.xlsx"
destination = "/home/aaaaaaaaa.xlsx"
"""
执行命令:
sudo mount -t cifs //11.11.11.11/共享 /mnt/smb -o username=admin,password=11111111
cp /mnt/smb/aaaaaaaaaaaaaaaaaaaaaaa/aaaaaaaaaaaaaaaaaa.xlsx /home/aaaaaaaaa.xlsx
sudo umount -l /mnt/smb/
"""
# 挂载SMB共享
mount_cmd = f"sudo mount -t cifs {smb_share} {mount_point} -o username={username},password={password}"
print(mount_cmd)
try:
subprocess.run(mount_cmd, shell=True, check=True, text=True, input=password_me + '\n')
print("SMB共享挂载成功。")
except subprocess.CalledProcessError as e:
print("挂载SMB共享失败:", e)
exit(1)
time.sleep(1)
# 列出文件
print('-'*10)
try:
subprocess.run(["ls","/mnt/smb/aaaaaaaaaaaaaaaaaaaaaaa/"], check=True)
print("列出文件。")
except subprocess.CalledProcessError as e:
print("列出文件失败:", e)
print('-'*10)
# 复制文件
try:
subprocess.run(["cp", source_file, destination], check=True)
print("文件复制成功。")
except subprocess.CalledProcessError as e:
print("文件复制失败:", e)
# 卸载SMB共享
umount_cmd = f"sudo umount -l {mount_point}"
try:
subprocess.run(umount_cmd, shell=True, check=True)
print(f"挂载点 {mount_point} 已延迟卸载。")
except subprocess.CalledProcessError as e:
print(f"延迟卸载失败: {e}")
在 crontab 中设置定时任务时,mount 会要求 sudo 权限。我最初尝试让 Python 文件运行在 sudo 权限,但是 python 的很多库都无法 import 。解决起来很复杂。
最终采用:修改 sudoers 文件,允许特定用户或特定命令在不输入密码的情况下使用 sudo 执行 mount 操作。输入
sudo visudo
在文件中添加类似如下的内容:
username ALL=(ALL) NOPASSWD: /usr/bin/mount
这里的 username 是执行 crontab 任务的用户。
保存并退出文件:visudo 会自动检查语法,确保文件内容正确后保存退出。
以上设置完成以后,代码第26行需改为:
subprocess.run( f"sudo mount -t cifs {smb_share} {mount_point} -o username={username},password={password}", shell=True, check=True )
crontab 的定时任务的运行环境里,subprocess 的 input 是无法实现的。
其实 sudoers 文件里,可以在 mount 命令后把参数都写好,这样就可以精准控制挂载哪些文件时不用输入 sudo 的密码。但是这条命令里参数太多,我还没找到写上去不出语法错误的写法。或许可以把这条命令写入 shell 文件,给这个文件开 sudo 权限。暂时没尝试。