客户机是外网的 Windows 11,服务器是群晖。
客户机上安装 WSL Alpine Linux 来运行 rsync 进行文件下载。Alpine 相对比 Ubuntu、Debian,要小巧轻量,占用存储空间少,启动速度也很快。
一、安装 WSL Alpine Linux
在 Windows 中,打开 cmd 或 PowerShell,输入安装指令:
wsl --install --no-distribution
加参数 --no-distribution 阻止安装默认的 Linux 发行包(Ubuntu)
参考:https://learn.microsoft.com/en-us/windows/wsl/install
打开 Microsoft Store,搜索 alpine
二、挂载外部 Windows 路径
默认 Linux 子系统会自动挂载各个盘符。但有个分区,在 Windows 11 中是挂载在目录下,没有分配盘符。通过目录无法访问,需要另外挂载。
通过编辑 /etc/fstab 文件,可以自动挂载,不用每次调用 mount 命令。
在 /etc/fstab 中添加:
C:/UserProfiles/Workspace /mnt/w drvfs uid=1000,gid=1000,metadata,umask=22,fmask=111 0 0
参考:
https://blog.csdn.net/thinszx/article/details/128515061
https://learn.microsoft.com/en-us/windows/wsl/wsl-config
不过,经测试,Alpine 中,启动时,加载 fstab 出错,通过 dmesg 查看输出,提示 c:/userprofiles/workspace 这个目录找不到。
但在 ubuntu wsl 中,却可以顺利挂载。
最终,还是在 Alpine 启动完成后,用 mount 命令来完成挂载。
mount -t drvfs -o metadata,uid=1000,gid=1000,fmask=113,dmask=002 C:/UserProfiles/Workspace /mnt/w
mount 命令中,参数 metadata 非常重要,不然 fatfs/ntfs 的文件,无法设置 mod,使用 chmod 755 ./ 命令,设置不起作用,目录访问权限不会被更改。
三、在 Alpine Linux 中安装 rsync
使用 ssh 方式连接服务器,需要一起安装 openssh
apk update
apk add rsync
apk add openssh
rsync 有两种连接方式,一个是 ssh,默认端口 22;一个是 rsync,默认端口是 873
四、运行 rsync
参考:https://zhuanlan.zhihu.com/p/659314811
rsync -avpe 'ssh -p 22' user@remoteAddress:/volume1/myArchive/share /mnt/w/rsync
如果要求本地成为服务器的镜像,不要有多出来的文件,需要加 --delete 参数,删除比服务器多的文件。参考:https://www.cnblogs.com/kevingrace/p/5766139.html
rsync -avpe 'ssh -p 22' --delete user@remoteAddress:/volume1/myArchive/share /mnt/w/rsync
五、脚本自动运行
#!/bin/ash
mount -t drvfs -o uid=1000,gid=1000,umask=022,metadata C:/UserProfiles/Workspace/rsync /mnt/w
#su pos -c /home/pos/rsync.sh
su pos -c expect <<-EOF
set timeout 30;
spawn rsync -avpe "ssh -p 3322" --delete user@<myserver>:/volume1/myfiles/share /mnt/w/
expect {
"*yes/no" { send "yes\r"; exp_continue }
"*password:" { send "o3q8hsMr\\\$y:33\r" }
}
expect eof
EOF
umount /mnt/w
由于 mount 需要 root 权限,因此入口用户是 root,而 rsync 则由 su 命令转为普通用户来执行。
脚本中使用了 expect 来自动输入密码,需要通过 apk add expect 安装。
在发送密码的字符串中,存在特殊字符 "$",需要转义,直接用 "\$" 还不能完成转义,需要二次转义,对 "\" 也要转义。
"\\\$",其中 "\\" 最终为 "\","\$" 为 "$",也就是将 "\\\$" 转成 "\$",这里就转义两次,不然输出的字符不是预期的结果。
为什么要转义多次,是因为命令被多次传递。一个命令嵌套一个命令,就会导致这种情况。
六、在 Windows 中调用 WSL 脚本
wsl -u root -d alphin -e /root/sync.sh
七、在windows 中设置计划任务
在 Windows 计划任务中创建定时任务
set ws=wscript.CreateObject("wscript.shell")
ws.run "wsl -u root -d Alpine -e /root/rsync.sh", 0
参考:https://zhuanlan.zhihu.com/p/612755941