前言

云盘下载的痛点:

  1. 要登陆,要下载各大云盘软件。
  2. 下载大文件时,主力电脑后台要一直挂着云盘服务。

在玩客云上搭建一个可以24小时下载任意云盘文件的的服务后:

  1. 免频繁登陆云盘,不用再下载各种云盘app。
  2. 下载大文件,无需值守。特别是晚上的时候再也不用亮着主力电脑的屏幕在那下载文件。
  3. 便宜,相较于大几千的nas设备。玩客云很香。

主要流程:

  1. 通过Alist 使用 WebDAV 方式接入云盘。查看AList文档

  2. ARM 设备(玩客云)上通过 rclone 将云盘挂载到本地。

  3. 把云盘文件拷贝到挂载在玩客云上的硬盘。

往期玩客云折腾

在拆了几次机器,刷了几次底包后,终于把服务搭起来了。

alist安装与配置

使用docker run命令创建并运行alist容器

1
2
3
4
5
6
7
8
9
docker run -d \
--restart=always \
-v /mnt/sda1/docker_data/alist:/opt/alist/data \
-p 5244:5244 \
-e PUID=0 \
-e PGID=0 \
-e UMASK=022 \
--name="alist" \
xhofe/alist:latest

浏览器输入ip:5244

登陆alist

首次启动,需要到日志中获取登陆密码

输入:

1
docker logs alist

找到这一行:

1
Successfully created the admin user and the initial password is: ghjfg 

用户名:admin

密码:ghjfg

注意把ghjfg替换成你自己的

添加云盘

以配置阿里云盘为例,其他云盘看alist官方文档。

阿里云盘 Open | AList文档 (nn.ci)

挂载路径建议填写云盘名称,设置的名称会在主页显示。

挂载路径

主页

点击查看夸克云盘配置方法
  • 获取夸克网盘cookie

​ 电脑端网页登陆夸克网盘,按F12进入调试页面;

  1. 点击网络
  2. 左侧名字找到list开头的请求
  3. 切换到请求头
  4. 找到cookie自断
  5. 复制cookie值

获取cookie

  • 配置alist

添加云存储,选择夸克盘

在cookie选项,粘贴cookie

粘贴cookie

reclone安装与配置

首先创建挂载目录

1
sudo mkdir -p /mnt/alist

安装 rclone及必要软件包

在 ARM 设备上先安装 rclonerclone 支持多种平台,包括 ARM。

安装 rclone

在 ARM 设备上通过以下命令安装 rclone

1
curl https://rclone.org/install.sh | sudo bash

or

1
sudo apt install rclone

检查并安装 FUSE:

rclone mount 依赖 FUSE(文件系统用户空间工具),如果系统没有正确安装或配置 FUSE,rclone 将无法挂载。

1
sudo apt-get install fuse

安装完 FUSE 后,确保 FUSE 模块已加载:

1
sudo modprobe fuse

没有任何输出即表示已加载

安装 FUSE3

系统中缺少 fusermount3也会出现挂载错误,FUSE3是 FUSE 的一个执行文件,用于管理用户空间的文件系统挂载。

1
sudo apt-get install fuse3

验证安装

安装完成后,验证 fusermount3 是否存在:

1
which fusermount3

这应该会显示 fusermount3 的路径,确认它已正确安装。

确保挂载点 /mnt/alist 有权限允许 rclone 挂载:

1
2
3
mkdir -p /mnt/alist
sudo chown root:root /mnt/alist
sudo chmod 755 /mnt/alistSS

rclone 配置 WebDAV

运行以下命令开始配置:

1
rclone config
  1. 选择 n 新建一个远程配置。

  2. 自己给配置命名,例如 aliyun-webdav

  3. 在存储类型中选择 webdav

  4. 输入 Alist 提供的 WebDAV URL(http://<alist-ip>:<port>/dav)。

    注意:http://<alist-ip>:<port>/dav是挂载alist中所有云盘,如果想挂单一云盘,比如阿里云请填写http://<alist-ip>:<port>/dav/aliyun/,其中aliyun字段是在alist中配置阿里云盘时定义的挂载路径。

  5. 选择 WebDAV 协议的类型,选择 Other site/service or software\ (other)。

  6. 输入alist登陆用户名

  7. 输入y使用 type in my own password

  8. 输入alist登陆密码

  9. 回车跳过bearer_token验证(Alist 通常不使用 Bearer Token 认证)

  10. 输入n跳过Edit advanced config?配置

  11. 检查配置是否正确,输入y确认完成配置

1
2
3
4
5
6
7
8
9
10
11
12
Configuration complete.
Options:
- type: webdav
- url: http://192.168.8.173:5244/dav/
- vendor: other
- user: yilan
- pass: *** ENCRYPTED ***
Keep this "aliyun-webdav" remote?
y) Yes this is OK (default)
e) Edit this remote
d) Delete this remote
y/e/d>

输入q退出配置

挂载云盘到本地

使用 rclone mount 挂载alist云盘到本地:

1
rclone mount aliyun-webdav:/ /mnt/alist --daemon
  • aliyun-webdav:/ 是配置的远程名称,表示通过 WebDAV 访问云盘(alist挂载的云盘)
  • /mnt/alist 是要挂载的本地目录。
  • --daemon 表示在后台挂载,挂载过程不会阻塞终端。

执行后没有任何回应大概率就是成功了

成功挂载

验证挂载

挂载成功后,你可以使用以下命令查看挂载情况:

1
mount | grep /mnt/alist

返回类似alist-webdav: on /mnt/alist type fuse.rclone (rw,nosuid,nodev,relatime,user_id=0,group_id=0)

1
df -h

验证挂载

并通过以下命令查看挂载的文件:

1
ls /mnt/alist

可以看到之前alist添加的云盘存储,这里添加了阿里云盘和夸克云盘。

阿里云、夸克挂载到本地

alist主页

设置开机自动挂载

先卸载挂载。避免后续systemd启动已经在运行的挂载后,出现挂载服务状态出错。

1
sudo umount /mnt/alist

如果希望每次启动时自动挂载阿里云盘,可以通过 systemd 配置自动挂载:

  1. 创建一个 systemd 服务文件:

    1
    sudo nano /etc/systemd/system/rclone-alist.service
  2. 添加以下内容:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    [Unit]
    Description=Mount Aliyun using rclone
    After=network-online.target

    [Service]
    Type=simple
    ExecStart=/usr/bin/rclone mount aliyun-webdav:/ /mnt/alist --vfs-cache-mode writes
    ExecStop=/bin/fusermount -u /mnt/alist
    Restart=on-failure
    RestartSec=5s
    StartLimitInterval=10s
    StartLimitBurst=3

    [Install]
    WantedBy=default.target

    注意:1. 如果挂载的阿里云盘ExecStart需添加参数

    1
    --header "Referer:https://www.aliyundrive.com/"

    2.ExecStart这一行的aliyun-webdav注意替换成前面设置的reclone配置名

  3. 重新加载systemd配置

    1
    sudo systemctl daemon-reload
  4. 启用并启动服务:

    1
    2
    sudo systemctl enable rclone-alist
    sudo systemctl restart rclone-alist
  5. 查看服务运行状态:

    1
    sudo systemctl status rclone-alist
  6. 停止服务:

    1
    sudo systemctl stop rclone-alist

使用

直接cp命令拷贝

比如想把云盘的电影下载到连接在玩客云的硬盘上(tip:我的硬盘挂载在/mnt/sda1目录上)

1
2
cd /mnt/alist/夸克云盘/来自:分享/影音/电影
cp 负负得正.2024.1080p.WEB-DL.H264.AAC.mp4 /mnt/sda1

运行后,cpu的负荷马上起来了。

拷贝

查看硬盘目录,电影已经下载了1.6个g。

硬盘目录

完成下载

完成下载

使用脚本逐个下载

使用rsync脚本逐个目录同步拷贝

  • 下载成功后不删除源文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
#!/bin/bash

# 颜色定义
YELLOW='\033[1;33m'
NC='\033[0m' # No Color

SRC_DIR="/mnt/alist/夸克云盘/800个电脑游戏"
DEST_DIR="/mnt/sda1/游戏"
LOG_FILE="/root/shell_script/夸克下载/copy_log.txt"
MAX_LOG_SIZE=$((20 * 1024 * 1024)) # 20 MB
RETRY_LIMIT=3 # 最大重试次数
DELETE_RETRY_LIMIT=5 # 删除操作的最大重试次数
DELETE_DELAY=5 # 删除操作前的延迟(秒)

# 检查日志文件大小
check_log_size() {
if [ -f "$LOG_FILE" ]; then
local log_size=$(wc -c < "$LOG_FILE")
if (( log_size > MAX_LOG_SIZE )); then
echo "$(date '+%Y-%m-%d %H:%M:%S') - 日志文件超过20MB,已清空" > "$LOG_FILE"
fi
fi
}

# 记录日志
log_message() {
local message=$1
local add_separator=${2:-false} # 新参数,控制是否添加分割线

if [ -w "$LOG_FILE" ] || touch "$LOG_FILE"; then
if [ "$add_separator" = true ]; then
echo "★★★★★★★★★★ $(date +"%Y-%m-%d %H:%M:%S") ★★★★★★★★★★" >> "$LOG_FILE"
fi
echo "$(date '+%Y-%m-%d %H:%M:%S') - $message" >> "$LOG_FILE"
else
echo "日志文件不可写,退出脚本" >&2
exit 1
fi
}

# 检查目标目录剩余空间是否足够
check_space() {
local dir_size=$(du -sb "$1" | awk '{print $1}')
local free_space=$(($(df "$DEST_DIR" | tail -1 | awk '{print $4}') * 1024))
if (( dir_size > free_space )); then
log_message "剩余空间不足以存放:$1"
exit 1
fi
}

# 尝试删除源文件
attempt_delete() {
local item=$1
local item_name=$(basename "$item")
local attempt=1

while (( attempt <= DELETE_RETRY_LIMIT )); do
sleep $DELETE_DELAY # 增加延迟
log_message "尝试删除(第 $attempt 次):$item_name"

# 尝试删除
rm -rf "$item"

# 立即检查是否删除成功
if [ ! -e "$item" ]; then
log_message "✓ 成功删除源文件:$item_name"
return 0 # 删除成功,立即退出函数
else
log_message "✗ 删除源文件失败:$item_name"
fi

((attempt++))
done

# 如果达到重试限制仍未删除成功
if [ -e "$item" ]; then
log_message "❌ 重试 $DELETE_RETRY_LIMIT 次后仍然无法删除:$item_name"
return 1
else
log_message "✓ 最终检查发现文件已删除:$item_name"
return 0
fi
}

# 尝试拷贝文件或目录
attempt_copy() {
local item=$1
local item_name=$(basename "$item")
local attempt=1

while (( attempt <= RETRY_LIMIT )); do
log_message "尝试拷贝(第 $attempt 次):$item_name"

# 捕获 rsync 错误信息
if rsync -a "$item" "$DEST_DIR/" 2>>"$LOG_FILE"; then
log_message "✓ 成功拷贝:$item_name"

return 0
else
log_message "✗ 拷贝失败:$item_name,错误信息记录在日志中"
fi

((attempt++))
done

log_message "❌ 重试 $RETRY_LIMIT 次后仍然无法拷贝:$item_name"
return 1
}

# 逐个拷贝文件和目录
copy_items() {
local total_items=$(ls -1 "$SRC_DIR" | wc -l)
local current_item=0

log_message "开始复制任务 - 总计 $total_items 个项目"

for item in "$SRC_DIR"/*; do
((current_item++))
local item_name=$(basename "$item")

log_message "[$current_item/$total_items] 处理项目:$item_name" true
check_space "$item"

if ! attempt_copy "$item"; then
log_message "❗ 无法完成拷贝:$item_name,跳过该项目"
fi

check_log_size
done

log_message "复制任务完成 - 总计处理 $total_items 个项目" true
}

# 检查源和目标目录是否存在
if [ ! -d "$SRC_DIR" ]; then
log_message "源目录不存在:$SRC_DIR"
exit 1
fi

if [ ! -d "$DEST_DIR" ]; then
log_message "目标目录不存在:$DEST_DIR"
exit 1
fi

# 执行拷贝
copy_items
  • 下载成功后删除源文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
#!/bin/bash

# 颜色定义
YELLOW='\033[1;33m'
NC='\033[0m' # No Color

SRC_DIR="/mnt/alist/夸克云盘/800个电脑游戏"
DEST_DIR="/mnt/sda1/游戏"
LOG_FILE="/root/shell_script/夸克下载/copy_log.txt"
MAX_LOG_SIZE=$((20 * 1024 * 1024)) # 20 MB
RETRY_LIMIT=3 # 最大重试次数
DELETE_RETRY_LIMIT=5 # 删除操作的最大重试次数
DELETE_DELAY=5 # 删除操作前的延迟(秒)

# 检查日志文件大小
check_log_size() {
if [ -f "$LOG_FILE" ]; then
local log_size=$(wc -c < "$LOG_FILE")
if (( log_size > MAX_LOG_SIZE )); then
echo "$(date '+%Y-%m-%d %H:%M:%S') - 日志文件超过20MB,已清空" > "$LOG_FILE"
fi
fi
}

# 记录日志
log_message() {
local message=$1
local add_separator=${2:-false} # 新参数,控制是否添加分割线

if [ -w "$LOG_FILE" ] || touch "$LOG_FILE"; then
if [ "$add_separator" = true ]; then
echo "★★★★★★★★★★ $(date +"%Y-%m-%d %H:%M:%S") ★★★★★★★★★★" >> "$LOG_FILE"
fi
echo "$(date '+%Y-%m-%d %H:%M:%S') - $message" >> "$LOG_FILE"
else
echo "日志文件不可写,退出脚本" >&2
exit 1
fi
}

# 检查目标目录剩余空间是否足够
check_space() {
local dir_size=$(du -sb "$1" | awk '{print $1}')
local free_space=$(($(df "$DEST_DIR" | tail -1 | awk '{print $4}') * 1024))
if (( dir_size > free_space )); then
log_message "剩余空间不足以存放:$1"
exit 1
fi
}

# 尝试删除源文件
attempt_delete() {
local item=$1
local item_name=$(basename "$item")
local attempt=1

while (( attempt <= DELETE_RETRY_LIMIT )); do
sleep $DELETE_DELAY # 增加延迟
log_message "尝试删除(第 $attempt 次):$item_name"

# 尝试删除
rm -rf "$item"

# 立即检查是否删除成功
if [ ! -e "$item" ]; then
log_message "✓ 成功删除源文件:$item_name"
return 0 # 删除成功,立即退出函数
else
log_message "✗ 删除源文件失败:$item_name"
fi

((attempt++))
done

# 如果达到重试限制仍未删除成功
if [ -e "$item" ]; then
log_message "❌ 重试 $DELETE_RETRY_LIMIT 次后仍然无法删除:$item_name"
return 1
else
log_message "✓ 最终检查发现文件已删除:$item_name"
return 0
fi
}

# 尝试拷贝文件或目录
attempt_copy() {
local item=$1
local item_name=$(basename "$item")
local attempt=1

while (( attempt <= RETRY_LIMIT )); do
log_message "尝试拷贝(第 $attempt 次):$item_name"

# 捕获 rsync 错误信息
if rsync -a "$item" "$DEST_DIR/" 2>>"$LOG_FILE"; then
log_message "✓ 成功拷贝:$item_name"
attempt_delete "$item"
return 0
else
log_message "✗ 拷贝失败:$item_name,错误信息记录在日志中"
fi

((attempt++))
done

log_message "❌ 重试 $RETRY_LIMIT 次后仍然无法拷贝:$item_name"
return 1
}

# 逐个拷贝文件和目录
copy_items() {
local total_items=$(ls -1 "$SRC_DIR" | wc -l)
local current_item=0

log_message "开始复制任务 - 总计 $total_items 个项目"

for item in "$SRC_DIR"/*; do
((current_item++))
local item_name=$(basename "$item")

log_message "[$current_item/$total_items] 处理项目:$item_name" true
check_space "$item"

if ! attempt_copy "$item"; then
log_message "❗ 无法完成拷贝:$item_name,跳过该项目"
fi

check_log_size
done

log_message "复制任务完成 - 总计处理 $total_items 个项目" true
}

# 检查源和目标目录是否存在
if [ ! -d "$SRC_DIR" ]; then
log_message "源目录不存在:$SRC_DIR"
exit 1
fi

if [ ! -d "$DEST_DIR" ]; then
log_message "目标目录不存在:$DEST_DIR"
exit 1
fi

# 执行拷贝
copy_items

辅助脚本

解决云盘文件部分下载失败

思路:删除云盘中下载成功文件,保留失败文件,再次运行脚本进行下载

失败日志如下

报错

脚本:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#!/bin/bash

# 设置工作目录
BASE_DIR="/mnt/alist/夸克云盘/800个电脑游戏/《400套付费套装书合集》,价值上万!"

# 使用固定的临时文件名
KEEP_LIST="keep_files.tmp"

# 从jj.txt提取文件路径并保存到临时文件
grep "File name too long (36)" jj.txt | sed 's/.*"\(.*\)": File name.*/\1/' > "$KEEP_LIST"

# 如果目录存在
if [ -d "$BASE_DIR" ]; then
# 遍历目录中的所有文件
find "$BASE_DIR" -type f | while read -r file; do
# 检查文件是否在保留列表中
if ! grep -Fq "$file" "$KEEP_LIST"; then
# 如果不在保留列表中,则删除
rm -f "$file"
echo "Deleted: $file"
else
echo "Kept: $file"
fi
done
else
echo "Directory not found: $BASE_DIR"
fi

# 清理临时文件
rm -f "$KEEP_LIST"

使用方法,把日志报错,复制到jj.txt,编辑jj.txt,把挂载的的根目录(/mnt/sda1)替换成云盘的根目录;脚本和jj.txt放到一个目录,执行脚本。

最后

再贴个裸机两三天的玩客云

玩客云