简介 系统名称：ezbookkeeping 这个系统是再github上开源的，完全免费，没有会员广告限制，所有数据全部存储在自己的服务器上 功能方面也是比较全面的，除了基础的收支记录，账户管理，报表等功能外，还支持账单一键导入，可以导入支付宝微信账单，也可以导入银行账单 项目/下载地址 项目地址：https://github.com/mayswind/ezbookkeeping 也可以前往资源库搜索下载，本站提供linux1.0.1版本下载 搭建环境 这个系统支持子啊windows、linux等系统上运行 我这边使用的是linux系统 第一步：下载ezbookkeeping 打开项目地址 点击顶部的标签 点击最新的版本号 找到适合自己处理器和系统的版本，右键复制链接地址 使用SSH连接到自己服务器，在/opt目录下创建一个新文件夹 mkdir /opt/ezbookkeeping 进入刚刚创建的文件夹 cd ezbookkeeping 使用wget命令下载 wget 刚刚复制的下载链接 wget https://github.com/mayswind/ezbookkeeping/releases/download/v1.0.1/ezbookkeeping-1.0.1-linux-amd64.tar.gz 解压下载的文件 tar -zxvf ezbookkeeping-1.0.1-linux-amd64.tar.gz 第二步：测试运行 解压出来后，可以看到有一堆文件，其中里面有个文件名为ezbookkeeping，这个就是这个系统的二进制运行文件，使用下面命令测试运行 ./ezbookkeeping server run 使用浏览器访问服务器地址加8080端口，如果正常的话会打开登录界面 第三步：设置开机自启 可以正常运行后就没问题了，接下来就是配置开机自启了 进入system服务 cd /etc/systemd/system 使用vi编辑器新建一个文件 vi ezbookkeeping.service 把下面内容复制站体进去，记得根据自己实际情况修改路径 [Unit] Description=ezBookkeeping Server After=network.target [Service] Type=simple User=root WorkingDirectory=/opt/ezbookkeeping ExecStart=/opt/ezbookkeeping/ezbookkeeping server run Restart=on-failure StandardOutput=append:/opt/ezbookkeeping/log/ezbookkeeping.log StandardError=append:/opt/ezbookkeeping/log/ezbookkeeping.log [Install] WantedBy=multi-user.target 修改完成后保存并退出，然后授权可执行权限 刷新system配置文件 systemctl daemon-reload 启动 systemctl start ezbookkeeping 设置开机自启 systemctl enable ezbookkeeping.service 修改配置文件（可选） ezbookkeeping并没有管理员账户，然后用管理员账户修改系统配置，新增删除账户之类的，所有的配置都需要直接修改配置文件 修改配置文件可以参考官方的手册来修改 官方手册地址：https://ezbookkeeping.mayswind.net/zh_Hans 例如我需要关掉用户可以注册 首先我先看一下官方的手册，找到关于用户注册的 然后打开配置文件 vi conf/ezbookkeeping.ini 然后找到刚刚我们查询手册上对应的选项名 现在是true就是启用，要关闭就改成false，修改完成后保存退出 然后重启服务 systemctl restart ezbookkeeping.service 再次打开就可以看到创建用户点击不了了 注意事项 该项目没有管理界面，所有管理都需要命令行实现，要么修改配置文件要么使用命令 具体配置以及命令可以参考官方手册 喜欢折腾的可以研究看看 更新 使用二进制文件部署的，更新的时候下载最新版的包解压，然后覆盖原来的二进制文件ezbookkeeping和public目录以及templates目录即可 不要替换 conf/、data/、log/、storage/目录， conf目录存放配置文件 data目录存放数据库 log目录存放日志 storage目录存放用户上传的文件 更新完成后进入到二进制文件目录，执行更新数据数据库结构操作 命令： ./ezbookkeeping database update
简介 之前我的博客和服务器上的其他系统都是我手动备份数据的，因为懒，所以懒得整自动备份 最近连手动备份也懒了，想想还是整个自动备份吧 我使用的工具是restic是本地/远程备份工具，可以实现增量备份 + 去重 + 压缩 + 加密 + 快照管理 可以把数据备份到 本地磁盘、NAS、SFTP、S3 等支持的后端 功能 描述 增量备份 每次只保存变化的数据，节省空间 去重 不同备份间重复数据只保存一次 压缩 数据存储时自动压缩，节省存储空间 加密 备份自动加密，保证安全 快照管理 可以查看、保留、删除历史版本 跨平台 Linux / Windows / macOS 都支持 思路 我的服务器使用的是联想M73，只有一个硬盘位，所以打算外接一个USB硬盘来存储备份文件 刚开始想使用网盘进行备份的，后面发现很多网盘备份工具都不知此个人版的网盘，只支持企业版，当然也不是没有办法，先把网盘挂载成webdav，然后存进去就可以了 但是我懒，反正家里面有硬盘 第一步：格式化硬盘 首先把USB硬盘插上去，然后使用下面命令查看硬盘信息，可以看到这里已经读出我的硬盘了，是/dev/sdc1 lsblk -f 硬盘格式是ntfs，这个格式对linux并不友好，我需要格式化成ext4格式 首先卸载硬盘，如果没有挂载的话就忽略这一步，如果不知道硬盘有没有挂载就直接执行也没事，没有挂载会有提示 umount /dev/sdc1 然后格式化硬盘，中间可能会弹出提示，输入y回车继续 mkfs.ext4 -L backup /dev/sdc1 等待完成 第二步：挂载硬盘 使用下面命令查看确定硬盘的UUID，记得把UUID复制下来 blkid /dev/sdc1 使用vi编辑下面文件 vi /etc/fstab 在文件最后面添加挂载信息，把下面这一行复制修改UUID为你硬盘的UUID，ntfs-3g改成硬盘格式，然后粘贴到文件的最后面，因为是移动硬盘，所以我们加了nofail,x-systemd.device-timeout=10，这个是开机等待10秒，不管有没有检测到这个设备都直接开机，如果不加的话移动硬盘出现问题挂载不了就会导致开机卡住，开不了机 UUID=068273068272FA0F /mnt/usb ntfs-3g defaults,nofail,x-systemd.device-timeout=10 0 0 添加完成后，保存退出 执行立即挂载命令，但是我这提示挂载失败，挂载点不存在 mount -a 这个是因为我的系统里面没有/mnt/usb这个目录，所以挂载不上，我先创建一个/mnt/usb目录 mkdir /mnt/usb 然后再次执行挂载命令，提示不是错误，只是 systemd 在提醒：你修改了 /etc/fstab，但 systemd 还缓存着旧配置。 不过 mount -a 是直接读 /etc/fstab 的，不依赖 systemd，所以已经生效了 mount -a 使用下面命令查看是否挂载成功，看到有挂载点就是成功了 lsblk -f 使用下面命令让 systemd 下次启动时用新的配置 systemctl daemon-reload 第三步：下载release release可以直接使用系统源yum、apt下载，但是版本比较老，我是直接去github项目地址下载的 项目地址：https://github.com/restic/restic/ 首先创建一个文件夹，用来存放release的二进制运行文件 mkdir /opt/release 进入刚刚创建的文件夹 cd /opt/release 进入release项目地址 点击顶部的标签 点击最新的版本号 滑倒下面，找到对应自己服务器操作系统和处理器的版本，右键，复制链接地址 回到SSH终端，使用wget命令下载 wget https://github.com/restic/restic/releases/download/v0.18.1/restic_0.18.1_linux_amd64.bz2 下载完成后解压出来，然后使用ls命令查看解压出来的文件 bunzip2 restic_0.18.1_linux_amd64.bz2 ls 解压出来的文件名太长了，我们重命名一下 mv restic_0.18.1_linux_amd64 restic 修改文件权限，让文件可执行 chmod +x restic 第四步：创建备份文件列表 使用vi编辑器创建一个txt文件，名称为：backup_dirs.txt vi backup_dirs.txt 然后把需要备份的文件目录写进去，这样后面我们需要增加或者删除备份目录就直接修改这个文件列表即可 /home/wwwroot/www.ersansi.top /root/Dufs-data /usr/local/frpc /usr/local/hysteria2 /root/mysql-bak-up 编辑完成后保存并退出 第五步：初始化备份仓库 我们先在刚刚挂载的USB移动硬盘上创建一个文件夹，用于存放备份文件 mkdir -p /mnt/usb/restic-repo 在创建一个密码文件，用于存储备份加密密码，这个密码很重要，恢复备份的时候也需要这个密码 echo "你的备份密码" > /opt/release/.restic-passwd 修改文件权限 chmod 600 .restic-passwd 初始化仓库，看到下图的结果就是初始化成功了 /opt/release/restic -r /mnt/usb/restic-repo --password-file /opt/release/.restic-passwd init 第六步：测试备份 使用下面命令测试一下是否可以正常备份,backup后面就是你需要备份的文件目录路径 /opt/release/restic -r /mnt/usb/restic-repo --password-file /opt/release/.restic-passwd backup 你的需要备份的文件路径 /opt/release/restic -r /mnt/usb/restic-repo --password-file /opt/release/.restic-passwd backup /usr/local/frpc 看最后一行，快照ID是1c0a9736，说明备份成功了 查看一下快照内容 /opt/release/restic -r /mnt/usb/restic-repo --password-file /opt/release/.restic-passwd snapshots 测试还原 /opt/release/restic -r /mnt/usb/restic-repo --password-file /opt/release/.restic-passwd restore 快照ID --target 需要还原到的目录 /opt/release/restic -r /mnt/usb/restic-repo --password-file /opt/release/.restic-passwd restore 1c0a9736 --target /root/test-restore 可以看到也是可以正常还原的 第七步：创建脚本 因为我的备份有mysql，我需要先把数据库导出来，然后再进行备份，所以我需要一个脚本来导出数据库，数据库导出成功后才能备份 首先创建一个.sh文件 vi full-backup.sh 然后把下面内容复制修改一下粘贴到里面 #!/bin/bash # ------------------------------- # 全量备份 MySQL + 文件到 Restic # ------------------------------- # ---------------- MySQL 配置 ---------------- MYSQL_USER="数据库用户名" MYSQL_PASSWORD="数据库密码" MYSQL_HOST="数据库地址" MYSQL_BACKUP_DIR="导出到的文件目录路径" DB_TO_BACKUP="需要导出的数据库，需要导出所有则去掉引号输入0" EMAIL="接收邮件的邮箱，需要安装对应服务才能使用发送邮件功能" # ---------------- Restic 配置 ---------------- RESTIC_BIN="restic二进制文件路径" RESTIC_REPO="需要备份到的仓库路径" RESTIC_PASSWORD_FILE="密码文件路径" BACKUP_DIRS_FILE="备份列表路径" mkdir -p "$MYSQL_BACKUP_DIR" send_mail() { local subject="$1" local body="$2" echo -e "$body" | mail -s "$subject" -r "服务器备份 <发送邮件的邮箱>" "$EMAIL" } # ---------------- 1. MySQL 备份 ---------------- if [ "$DB_TO_BACKUP" == "0" ]; then DBS=$(/usr/bin/mysql -u"$MYSQL_USER" -p"$MYSQL_PASSWORD" -h "$MYSQL_HOST" -e "SHOW DATABASES;" | grep -Ev "(Database|information_schema|performance_schema|mysql|sys)") else DBS="$DB_TO_BACKUP" fi for db in $DBS; do echo "备份数据库: $db" if ! /usr/bin/mysqldump -u"$MYSQL_USER" -p"$MYSQL_PASSWORD" -h "$MYSQL_HOST" "$db" > "$MYSQL_BACKUP_DIR/$db.sql"; then echo "[$(date)] 数据库 $db 导出失败" >&2 send_mail "MySQL 备份失败" "数据库 $db 导出失败，请检查服务器" exit 1 fi done echo "MySQL 备份成功: $(date)" # ---------------- 2. Restic 备份 ---------------- echo "开始 Restic 备份..." if ! $RESTIC_BIN -r "$RESTIC_REPO" --password-file "$RESTIC_PASSWORD_FILE" backup --files-from "$BACKUP_DIRS_FILE"; then echo "[$(date)] Restic 备份失败" >&2 send_mail "Restic 备份失败" "文件备份失败，请检查服务器" exit 1 fi echo "Restic 备份完成: $(date)" send_mail "备份成功" "MySQL + 文件备份成功完成！" 编辑完成后保存退出，然后授权文件可执行 chmod +x full-backup.sh 执行测试一下是否可用 ./full-backup.sh 第七步：创建服务 测试脚本成功了，接下来就是创建system的任务文件了 vi /etc/systemd/system/full-backup.service 把下面内容复制粘贴进去，记得把路径改成自己脚本所在的路径 [Unit] Description=全量备份 MySQL + 文件 After=network.target [Service] Type=oneshot ExecStart=/opt/release/full-backup.sh StandardOutput=journal StandardError=journal RemainAfterExit=no [Install] WantedBy=multi-user.target 编辑完成后保存并退出，然后修改权限为可执行权限 第八步：创建定时器 上面创建了服务，用来运行sh脚本，但是我们还需要一个定时器来触发服务，这样就可以实现再指定的时间断进行备份了 vi /etc/systemd/system/full-backup.timer 然后把下面内容复制粘贴进去 [Unit] Description=每天凌晨 3 点执行全量备份 [Timer] Unit=full-backup.service OnCalendar=*-*-* 03:00:00 Persistent=true [Install] WantedBy=timers.target OnCalendar=-- 03:00:00 表示每天的 03:00:00 运行（-- 代表任意年-月-日） Persistent=true 如果机器在 03:00 没开机，开机后会立即补跑一次（防止错过） 编辑好后保存并退出，然后修改权限为可执行 chmod +x /etc/systemd/system/full-backup.timer 第九步：应用配置 所有文件全部配置好后，我们就可以应用配置了 首先重载一下systemd配置文件 systemctl daemon-reload 然后设置定时器开机就启动 systemctl enable full-backup.timer 最后手动启动定时器 systemctl start full-backup.timer 启动完成后我们可以执行下面命令查看定时任务 systemctl list-timers --all restic命令 为了方便理解，我这里列一下文件路径 restic二进制文件路径：/opt/release/restic 仓库路径：/mnt/usb/restic-repo 密码文件路径：/opt/release/.restic-passwd 备份列表文件路径：/opt/release/backup_dirs.txt 快照ID：1d0ce954 恢复目标目录：/root/bakup 快照挂载点：/usr/local/frpc 初始化仓库 第一次备份的时候需要先初始化仓库，后面不需要 restic路径 init -r 仓库路径 --password-file 密码文件路径 套入我上面的路径就是下面命令 /opt/release/restic init -r /mnt/usb/restic-repo --password-file /opt/release/.restic-passwd 备份目录 直接指定备份目录： restic路径 backup 需要备份的目录 -r 仓库路径 --password-file 密码文件路径 指定备份文件列表文件： restic路径 backup --files-from 列表文件路径 -r 仓库路径 --password-file 密码文件路径 替换成我上面的文件文件路径 /opt/release/restic backup --files-from /opt/release/backup_dirs.txt -r /mnt/usb/restic-repo --password-file /opt/release/.restic-passwd 列出所有快照 restic路径 snapshots -r 仓库路径 --password-file 密码文件路径 替换成我上面的路径 /opt/release/restic snapshots -r /mnt/usb/restic-repo --password-file /opt/release/.restic-passwd 查看仓库状态 restic路径 stats -r 仓库路径 --password-file 密码文件路径 替换成我上面的路径 /opt/release/restic stats -r /mnt/usb/restic-repo --password-file /opt/release/.restic-passwd 查看快照详细文件列表 restic路径 ls 快照ID -r /仓库路径 --password-file /密码文件路径 替换成我上面的路径 /opt/release/restic ls 1d0ce954 -r /mnt/usb/restic-repo --password-file /opt/release/.restic-passwd 恢复快照到指定目录 restic路径 restore 快照ID -r 仓库路径 --password-file 密码文件路径 --target 恢复目标目录 替换成我上面的路径 /opt/release/restic restore 1d0ce954 -r /mnt/usb/restic-repo --password-file /opt/release/.restic-passwd --target /root/bakup 恢复指定快照中的指定目录 例如我现在备份仓库中有很多目录，我只需要恢复其中一个目录，不需要恢复整个快照，那是可以直接指定恢复的目录的 下面示例是我只需要恢复快照id为1d0ce954的里面的etc目录 restic路径 restore 快照ID -r 仓库路径 --password-file 密码文件路径 --target 需要恢复到的路径 --include 需要恢复的目录 替换成上面的路径： /opt/release/restic restore 快照ID -r /mnt/usb/restic-repo --password-file /opt/release/.restic-passwd --target /tmp/restore --include /etc 恢复指定快照中的指定文件 restic路径 restore 快照ID -r 仓库路径 --password-file 密码文件路径 --target 需要恢复到的路径 --include 需要恢复的文件路径 只把 /etc下的hosts 恢复到 /tmp/restore/etc /opt/release/restic restore 1d0ce954 -r /mnt/usb/restic-repo --password-file /opt/release/.restic-passwd --target /tmp/restore --include /etc/hosts 排除一些目录，只恢复其他内容 restic路径 restore 快照ID -r 仓库路径 --password-file 密码文件路径 --target 需要恢复到的路径 --include 需要恢复的目录 --exclude 需要排除的目录路径 比如只恢复 /home，但不要 /home/cache /opt/release/restic restore d0ce954 -r /mnt/usb/restic-repo --password-file /opt/release/.restic-passwd --target /tmp/restore --include /home --exclude /home/cache 清理未引用的数据（垃圾回收） restic路径 forget --prune -r 仓库路径 --password-file 密码文件路径 替换成上面路径 /opt/release/restic forget --prune -r /mnt/usb/restic-repo --password-file /opt/release/.restic-passwd 设置保留策略（例如：保留最近 7 天的备份） restic路径 forget --keep-daily 7 --prune -r 仓库路径 --password-file 密码文件路径 替换成上面路径： /opt/release/restic forget --keep-daily 7 --prune -r /mnt/usb/restic-repo --password-file /opt/release/.restic-passwd 校验备份完整性 restic路径 check -r 仓库路径 --password-file 密码文件路径 替换成上面路径： /opt/release/restic check -r /mnt/usb/restic-repo --password-file /opt/release/.restic-passwd 挂载快照（FUSE，需要 Linux） restic路径 mount 挂载点 -r 仓库路径 --password-file 密码文件路径 替换成上面路径： /opt/release/restic mount /usr/local/frpc -r /mnt/usb/restic-repo --password-file /opt/release/.restic-passwd 删除指定快照 restic路径 -r 仓库路径 forget <快照ID1> --prune --password-file 密码文件路径 替换成上面路径 /opt/release/restic -r /mnt/usb/restic-repo forget 1d0ce954 --prune --password-file /opt/release/.restic-passwd 如果有多个快照ID则用空格隔开 restic 仓库被“锁死” 当出现下面这种情况的时候就是仓库被锁死了 [root@localhost release]# ./restic -r /mnt/usb/restic-repo forget ffe4c067 fe00aad1 00beadc1 ad0a0b0f 1ea88b86 d313de4a e1f93c8f e5c48e66 d2d71009 8aec1486 6f077dac ea03135c 9679064e db494ee8 3efbd0cc --prune --password-file .restic-passwd repository 5204d5cd opened (version 2, compression level auto) repo already locked, waiting up to 0s for the lock unable to create lock in backend: repository is already locked by PID 5798 on localhost.localdomain by root (UID 0, GID 0) lock was created at 2026-01-21 16:54:35 (50h9m9.49936224s ago) storage ID fb71889d the `unlock` command can be used to remove stale locks [root@localhost release]# 仓库被锁死的原因是上一次 restic 任务 异常中断 / 崩溃 / 断电 / 强制关闭 锁文件没有被正常清理 现在 restic 认为“还有一个进程在使用仓库”，所以拒绝操作 可以使用下面命令解锁 ./restic -r /mnt/usb/restic-repo unlock --password-file .restic-passwd restic执行文件路径 -r 仓库路径 unlock --password-file 密码文件路径 restic菜单脚本 我还做了一个菜单脚本，方便使用restic，需要的可以下载把里面的环境参数修改一下即可使用 下面是菜单脚本的内容，记得把上面的环境变量修改和自己相符的 #!/bin/bash # 配置 RESTIC_BIN="restic二进制文件路径" REPO="仓库路径" PASSFILE="密码文件路径" RESTORE_TARGET="默认的快照恢复目标目录" DEFAULT_MOUNT="默认挂载快照的目录" FULL_BACKUP="备份脚本路径" # 检查 restic 和 full-backup.sh 是否存在 if [ ! -x "$RESTIC_BIN" ]; then echo "错误: Restic 未找到，请检查路径: $RESTIC_BIN" exit 1 fi if [ ! -x "$FULL_BACKUP" ]; then echo "错误: full-backup.sh 未找到或不可执行: $FULL_BACKUP" exit 1 fi # 通用暂停函数 function pause() { echo read -p "按 Enter 返回菜单..." } # 显示快照列表 function show_snapshots() { clear echo "=== 快照列表 ===" $RESTIC_BIN snapshots -r $REPO --password-file $PASSFILE | less -SFXR echo "================" pause } # 显示快照文件列表 function show_snapshot_files() { show_snapshots read -p "请输入快照ID查看文件: " SNAPSHOT_ID clear echo "=== 快照 $SNAPSHOT_ID 文件列表 ===" $RESTIC_BIN ls $SNAPSHOT_ID -r $REPO --password-file $PASSFILE | less -SFXR echo "================" pause } # 菜单循环 while true; do clear echo "=====================================" echo " Restic 备份管理菜单" echo " 仓库: $REPO" echo " 密码文件: $PASSFILE" echo "=====================================" echo " 1) 初始化仓库" echo " 2) 执行完整备份 (full-backup.sh)" echo " 3) 查看快照列表" echo " 4) 查看仓库状态" echo " 5) 查看快照文件内容" echo " 6) 恢复快照 (支持指定目录/文件)" echo " 7) 删除旧快照并清理" echo " 8) 校验仓库完整性" echo " 9) 挂载快照 (浏览文件)" echo "10) 卸载快照" echo "11) 手动执行 forget/keep 策略" echo " 0) 退出" echo "=====================================" read -p "请选择操作: " choice case $choice in 1) echo "⚠️ 初始化仓库会清空原有数据，仅首次使用时需要执行！" read -p "确认初始化仓库？(yes/no): " confirm if [ "$confirm" == "yes" ]; then $RESTIC_BIN init -r $REPO --password-file $PASSFILE else echo "已取消。" fi pause ;; 2) echo "开始完整备份..." if "$FULL_BACKUP"; then echo "备份完成。" else echo "备份失败，请检查 full-backup.sh 日志。" fi pause ;; 3) show_snapshots ;; 4) clear echo "=== 仓库状态 ===" $RESTIC_BIN stats -r $REPO --password-file $PASSFILE | less -SFXR echo "================" pause ;; 5) show_snapshot_files ;; 6) show_snapshots read -p "请输入快照ID: " SNAPSHOT_ID read -p "请输入要恢复的路径(例如 /etc，留空恢复全部): " INCLUDE_PATH read -p "请输入恢复目标目录(默认 $RESTORE_TARGET): " TARGET TARGET=${TARGET:-$RESTORE_TARGET} mkdir -p "$TARGET" if [ -z "$INCLUDE_PATH" ]; then $RESTIC_BIN restore $SNAPSHOT_ID -r $REPO --password-file $PASSFILE --target "$TARGET" else $RESTIC_BIN restore $SNAPSHOT_ID -r $REPO --password-file $PASSFILE --target "$TARGET" --include "$INCLUDE_PATH" fi echo "恢复完成，文件在: $TARGET" pause ;; 7) read -p "请输入保留的天数(默认7): " DAYS DAYS=${DAYS:-7} echo "模拟执行: 将显示哪些快照会被删除 (dry-run)" $RESTIC_BIN forget --keep-daily $DAYS --prune --dry-run -r $REPO --password-file $PASSFILE | less -SFXR read -p "确认执行删除？(yes/no): " CONFIRM if [ "$CONFIRM" == "yes" ]; then $RESTIC_BIN forget --keep-daily $DAYS --prune -r $REPO --password-file $PASSFILE echo "清理完成。" else echo "已取消清理。" fi pause ;; 8) clear echo "校验仓库完整性..." $RESTIC_BIN check -r $REPO --password-file $PASSFILE | less -SFXR pause ;; 9) read -p "请输入挂载目录(默认 $DEFAULT_MOUNT): " MOUNT_DIR MOUNT_DIR=${MOUNT_DIR:-$DEFAULT_MOUNT} mkdir -p "$MOUNT_DIR" echo "挂载中... 浏览路径: $MOUNT_DIR" $RESTIC_BIN mount "$MOUNT_DIR" -r $REPO --password-file $PASSFILE & echo "已挂载，可用 'fusermount -u $MOUNT_DIR' 卸载。" pause ;; 10) read -p "请输入要卸载的目录(默认 $DEFAULT_MOUNT): " MOUNT_DIR MOUNT_DIR=${MOUNT_DIR:-$DEFAULT_MOUNT} fusermount -u "$MOUNT_DIR" 2>/dev/null || umount "$MOUNT_DIR" echo "已卸载 $MOUNT_DIR" pause ;; 11) echo "执行自定义 forget 策略示例:" echo "保留最近7天, 4周, 12月, 每年1个快照" read -p "模拟执行查看将删除哪些快照？(yes/no): " DRYRUN if [ "$DRYRUN" == "yes" ]; then $RESTIC_BIN forget --keep-daily 7 --keep-weekly 4 --keep-monthly 12 --keep-yearly 1 --prune --dry-run -r $REPO --password-file $PASSFILE | less -SFXR fi read -p "确认执行实际删除？(yes/no): " CONFIRM if [ "$CONFIRM" == "yes" ]; then $RESTIC_BIN forget --keep-daily 7 --keep-weekly 4 --keep-monthly 12 --keep-yearly 1 --prune -r $REPO --password-file $PASSFILE echo "删除完成。" else echo "已取消删除。" fi pause ;; 0) echo "退出菜单。" exit 0 ;; *) echo "无效选择，请重试。" pause ;; esac done 也可以前往资源库搜索下载 新full-backup.sh脚本 之前的脚本功能比较简单，所以更新了一下脚本 MySQL 数据库备份 支持备份单个数据库、多数据库或全部数据库（排除系统库）。 严格检查备份完整性： 捕获 mysqldump 返回码和错误输出。 能区分错误类型： 用户名或密码错误 → “连接数据库失败（用户名或密码错误）” 数据库不存在 → “数据库不存在” 无法连接 MySQL 主机/端口 → “无法连接数据库（主机或端口错误）” 其他未知错误 → “未知错误（请检查数据库是否存在或权限是否正确）” 如果有任何数据库导出失败： 会将所有失败的数据库和原因汇总在邮件中。 立即停止脚本执行，确保数据完整性。 成功导出数据库会生成 .sql 文件，并显示文件大小（MB/GB）。 文件/目录备份 支持通过 backup_dirs.txt 列表备份任意目录。 严格检查目录存在性： 在开始备份前逐个检查目录是否存在且可访问。 若发现目录不存在或不可访问： 立即停止备份。 发送邮件通知，并列出出错目录。 使用 Restic 进行备份。 捕获 Restic 输出，若失败立即停止并发送详细邮件。 每个目录备份完成后，会统计并记录大小。 总备份大小统计 使用 Restic stats --mode raw-data --last 1 获取最新快照的实际数据大小。 自动将字节转换为 MB 或 GB 显示，确保总备份大小准确。 快照 ID 获取最新 Restic 快照的短 ID 并显示，便于后续恢复或管理。 邮件通知 支持成功和失败邮件通知。 失败邮件： 包含 MySQL 导出失败详情或文件目录备份失败目录。 成功邮件： 列出所有 MySQL 数据库导出文件及大小。 列出所有备份目录及大小。 总备份大小、快照 ID、备份开始和结束时间、耗时。 进度与日志 控制台输出详细进度： MySQL 每个数据库导出情况。 文件/目录备份列表。 每个文件/目录的大小。 方便用户监控备份状态。 数据完整性保证 严格模式： 任何数据库导出失败或文件目录备份失败，脚本立即停止。 避免不完整备份进入 Restic 仓库。 邮件提供详细失败信息，便于快速定位问题。 脚本内容 #!/bin/bash # ------------------------------- # 全量备份 MySQL + 文件到 Restic # ------------------------------- # 作者：贰叁肆博客 # ------------------------------- # ---------------- 配置 ---------------- # MySQL 配置 MYSQL_USER="数据库用户名" MYSQL_PASSWORD="数据库密码" MYSQL_HOST="数据库地址" MYSQL_BACKUP_DIR="导出路径" DB_TO_BACKUP=数据库名" # 0表示备份所有数据库，多个用空格隔开 # 邮件配置 EMAIL="收件地址" MAIL_ENABLE=true # 邮件通知开关 true/false # Restic 配置 RESTIC_BIN="restic二进制文件路径" RESTIC_REPO="备用仓库路径" RESTIC_PASSWORD_FILE="密码文件路径" BACKUP_DIRS_FILE="备份列表文件路径" mkdir -p "$MYSQL_BACKUP_DIR" # ---------------- 邮件发送函数 ---------------- send_mail() { if [ "$MAIL_ENABLE" = true ]; then local subject="$1" local body="$2" echo -e "$body" | mail -s "$subject" -r "服务器备份 <发件邮箱>" "$EMAIL" fi } # ---------------- 开始计时 ---------------- START_TIME=$(date +%s) BACKUP_START=$(date '+%Y-%m-%d %H:%M:%S') # ---------------- 1. MySQL 备份 ---------------- FAILED_DBS=() DB_SIZE_INFO="" if [ "$DB_TO_BACKUP" == "0" ]; then DBS=$(/usr/bin/mysql -u"$MYSQL_USER" -p"$MYSQL_PASSWORD" -h "$MYSQL_HOST" -e "SHOW DATABASES;" | grep -Ev "(Database|information_schema|performance_schema|mysql|sys)") else DBS="$DB_TO_BACKUP" fi for db in $DBS; do echo "==== 开始备份数据库: $db ====" echo "正在导出数据库 $db ..." # 捕获 mysqldump 输出和返回码 DUMP_OUTPUT=$(/usr/bin/mysqldump -u"$MYSQL_USER" -p"$MYSQL_PASSWORD" -h "$MYSQL_HOST" "$db" 2>&1) EXIT_CODE=$? if [ $EXIT_CODE -ne 0 ]; then rm -f "$MYSQL_BACKUP_DIR/$db.sql" if echo "$DUMP_OUTPUT" | grep -q "Access denied"; then FAIL_REASON="连接数据库失败（用户名或密码错误）" elif echo "$DUMP_OUTPUT" | grep -q "Unknown database"; then FAIL_REASON="数据库不存在" elif echo "$DUMP_OUTPUT" | grep -q "Can't connect to MySQL server" || \ echo "$DUMP_OUTPUT" | grep -q "Lost connection to MySQL server"; then FAIL_REASON="无法连接数据库（主机或端口错误）" else FAIL_REASON="$DUMP_OUTPUT" fi FAILED_DBS+=("$db : $FAIL_REASON") continue fi echo "$DUMP_OUTPUT" > "$MYSQL_BACKUP_DIR/$db.sql" SIZE_BYTES=$(stat -c%s "$MYSQL_BACKUP_DIR/$db.sql" 2>/dev/null) SIZE_BYTES=${SIZE_BYTES:-0} if [ "$SIZE_BYTES" -ge 1073741824 ]; then SIZE_FMT=$(awk "BEGIN{printf \"%.2f GB\", $SIZE_BYTES/1024/1024/1024}") else SIZE_FMT=$(awk "BEGIN{printf \"%.2f MB\", $SIZE_BYTES/1024/1024}") fi echo "数据库 $db 导出完成，文件大小: $SIZE_FMT" DB_SIZE_INFO+="$db.sql : $SIZE_FMT\n" done if [ ${#FAILED_DBS[@]} -ne 0 ]; then FAIL_STEP="以下数据库导出失败:\n$(printf "%s\n" "${FAILED_DBS[@]}")" send_mail "MySQL 备份失败" "备份失败步骤:\n$FAIL_STEP\n请检查数据库连接或权限。" exit 1 fi echo "==== MySQL 备份完成 ====" # ---------------- 2. Restic 备份 ---------------- echo "==== 开始 Restic 备份 ====" echo "备份目录/文件列表:" cat "$BACKUP_DIRS_FILE" echo "------------------------" if ! $RESTIC_BIN -r "$RESTIC_REPO" --password-file "$RESTIC_PASSWORD_FILE" \ backup --files-from "$BACKUP_DIRS_FILE" --verbose 2>&1 | tee /tmp/restic-backup.log; then send_mail "Restic 备份失败" "备份失败步骤: Restic 文件备份失败\n详细信息:\n$(cat /tmp/restic-backup.log)" exit 1 fi echo "==== Restic 备份完成 ====" # ---------------- 3. 目录大小信息 ---------------- DIR_SIZE_INFO="" while IFS= read -r line; do if [ -e "$line" ]; then SIZE_BYTES=$(du -sb "$line" 2>/dev/null | awk '{print $1}') SIZE_BYTES=${SIZE_BYTES:-0} if [ "$SIZE_BYTES" -ge 1073741824 ]; then SIZE_FMT=$(awk "BEGIN{printf \"%.2f GB\", $SIZE_BYTES/1024/1024/1024}") else SIZE_FMT=$(awk "BEGIN{printf \"%.2f MB\", $SIZE_BYTES/1024/1024}") fi DIR_SIZE_INFO+="$line : $SIZE_FMT\n" else DIR_SIZE_INFO+="$line : 不存在\n" fi done < "$BACKUP_DIRS_FILE" # ---------------- 4. 成功邮件信息 ---------------- END_TIME=$(date +%s) BACKUP_END=$(date '+%Y-%m-%d %H:%M:%S') ELAPSED_TIME=$((END_TIME-START_TIME)) # 获取本次备份总大小 (使用 restore-size) BACKUP_SIZE_BYTES=$($RESTIC_BIN -r "$RESTIC_REPO" --password-file "$RESTIC_PASSWORD_FILE" \ stats --json --mode restore-size latest | jq -r '.total_size // 0') if [ "$BACKUP_SIZE_BYTES" -ge 1073741824 ]; then BACKUP_SIZE=$(awk "BEGIN{printf \"%.2f GB\", $BACKUP_SIZE_BYTES/1024/1024/1024}") else BACKUP_SIZE=$(awk "BEGIN{printf \"%.2f MB\", $BACKUP_SIZE_BYTES/1024/1024}") fi SNAPSHOT_ID=$($RESTIC_BIN -r "$RESTIC_REPO" --password-file "$RESTIC_PASSWORD_FILE" \ snapshots --json | jq -r 'sort_by(.time)[-1].short_id') MAIL_BODY="备份成功！ === MySQL 导出文件 === $DB_SIZE_INFO === 文件/目录备份 === $DIR_SIZE_INFO 总备份大小: $BACKUP_SIZE 快照 ID: $SNAPSHOT_ID 开始时间: $BACKUP_START 结束时间: $BACKUP_END 耗时: ${ELAPSED_TIME}s " send_mail "备份成功" "$MAIL_BODY" echo "==== 备份完成 ====" echo "总耗时: ${ELAPSED_TIME}s"
简介 Navidrome 是一个轻量级的、自托管的音乐服务器，类似 Subsonic，但更加现代和开源。它可以让你在任何设备上访问和播放自己的音乐库，并支持转码、Web 界面、API 等多种功能。 支持linux部署和windows部署 地址 Github项目地址：https://github.com/navidrome/navidrome 官网地址：https://www.navidrome.org/ 官网手册地址：https://www.navidrome.org/docs/ 也可以从本站的资源库里面搜索下载，本站资源库提供的版本是linux-amd64版本 部署环境 操作系统：Almalinux 第一步：下载/解压Navidrome 下载 首先打开github项目地址 然后点击顶部的标签 点击最新的版本号 滑倒下面，找到对应自己服务器的版本，点击右键，复制链接地址 使用SSH工具链接服务器，然后使用下面命令创建文件夹 mkdir /opt/navidrome 进入刚刚创建的文件夹 cd /opt/navidrome 使用wgeet命令下载刚刚复制的链接的文件 wget https://github.com/navidrome/navidrome/releases/download/v0.58.0/navidrome_0.58.0_linux_amd64.tar.gz 下载完成后，使用ls命令查看刚刚下载的文件 ls 解压 使用tar命令解压刚刚下载的文件 tar -zxvf navidrome_0.58.0_linux_amd64.tar.gz 使用ls命令查看解压出来的文件 我们只需要保留navidrome这个文件就行，其他的直接使用rm命令删除 rm -f LICENSE navidrome_0.58.0_linux_amd64.tar.gz README.md 配置navidrome 使用vi命令创建一个配置文件 vi navidrome.toml 然后把下面配置内容根据自己需求修改一下，复制粘贴进去 # ========================================== # Navidrome 配置文件示例 (最全) # ========================================== # ------------------- # 服务器设置 # ------------------- Port = 4533 # Web界面端口 Address = "0.0.0.0" # 监听地址，0.0.0.0 表示所有网卡 BaseURL = "" # 如果部署在子目录，例如 /music LogLevel = "info" # 日志等级: debug / info / warn / error # ------------------- # 数据库设置 # ------------------- DataFolder = "/srv/navidrome/data" # 数据库和缓存文件存放目录 DBType = "sqlite3" # 数据库类型: sqlite3 / postgres DBPath = "navidrome.db" # sqlite 数据库文件路径（如果使用 sqlite3） # PostgreSQL 连接设置（如果 DBType=postgres） PostgresHost = "localhost" PostgresPort = 5432 PostgresUser = "navidrome" PostgresPassword = "password" PostgresDB = "navidrome" # ------------------- # 音乐库设置 # ------------------- MusicFolder = "/srv/navidrome/music" # 音乐文件目录，必须存在且可读写 ScanInterval = "5m" # 自动扫描音乐库的间隔，可设为 "10m"、"1h" AllowedExtensions = ["mp3", "flac", "ogg", "m4a"] # 支持的音频文件格式 FullScanOnStartup = true # 启动时是否执行全量扫描 PlaylistImport = true # 启动时是否导入已有播放列表 # ------------------- # 用户与安全 # ------------------- NoAuth = false # true 表示无需登录 SignupEnabled = true # 是否允许用户注册 AllowSignUpAdmin = false # 注册用户是否默认管理员，建议 false DefaultUserQuota = 0 # 用户配额，0表示无限 UserSessionQuota = 5 # 每个用户同时允许的会话数 SessionTimeout = "24h" # 会话过期时间 # ------------------- # 播放与转码 # ------------------- FFmpegPath = "/usr/local/bin/ffmpeg" # FFmpeg 可执行文件路径 Transcoding = true # 是否开启实时转码 MaxBitrate = 320 # 转码最大码率 kbps TranscodingCacheMaxSize = "100MB" # 转码缓存大小 AllowDownload = true # 是否允许客户端下载音乐 EnableCoverArt = true # 是否生成封面图 # ------------------- # API 设置 # ------------------- EnableSubsonic = true # 是否开启 Subsonic API SubsonicSalt = "随机字符串" # Subsonic API 密钥盐 EnableWebhooks = false # 是否开启 Webhooks 事件通知 EnableSpotify = false # 是否启用 Spotify 集成 SpotifyClientID = "" # Spotify Client ID SpotifyClientSecret = "" # Spotify Client Secret EnableLastFM = false # 是否集成 LastFM LastFMAPIKey = "" # LastFM API Key EnableListenBrainz = false # 是否集成 ListenBrainz ListenBrainzUsername = "" # ListenBrainz 用户名 ListenBrainzPassword = "" # ListenBrainz 密码 # ------------------- # 缓存设置 # ------------------- ImageCacheMaxSize = "100MB" # 封面图缓存大小 BackgroundCacheMaxSize = "100MB" # 背景缓存大小 # ------------------- # 高级与调试 # ------------------- Debug = false # 开启调试模式 EnableSSL = false # 如果你打算直接用 Navidrome 提供 HTTPS SSLCertFile = "/path/to/cert.pem" # SSL 证书路径 SSLKeyFile = "/path/to/key.pem" # SSL 私钥路径 下面是我的配置文件 # ------------------- # 服务器设置 # ------------------- Port = 4533 # Web界面端口 Address = "0.0.0.0" # 监听地址，0.0.0.0 表示所有网卡 BaseURL = "" # 如果部署在子目录，例如 /music LogLevel = "info" # 日志等级: debug / info / warn / error # ------------------- # 数据库设置 # ------------------- DataFolder = "/opt/navidrome/data" # 数据库和缓存文件存放目录 DBType = "sqlite3" # 数据库类型: sqlite3 / postgres DBPath = "/opt/navidrome/data/navidrome.db" # sqlite 数据库文件路径（如果使用 sqlite3） # ------------------- # 音乐库设置 # ------------------- MusicFolder = "/opt/navidrome/music" # 音乐文件目录，必须存在且可读写 ScanInterval = "5m" # 自动扫描音乐库的间隔，可设为 "10m"、"1h" AllowedExtensions = ["mp3", "flac", "ogg", "m4a"] # 支持的音频文件格式 FullScanOnStartup = true # 启动时是否执行全量扫描 PlaylistImport = true # 启动时是否导入已有播放列表 # ------------------- # 用户与安全 # ------------------- NoAuth = true # true 表示无需登录 SignupEnabled = false # 是否允许用户注册 AllowSignUpAdmin = false # 注册用户是否默认管理员，建议 false DefaultUserQuota = 0 # 用户配额，0表示无限 UserSessionQuota = 5 # 每个用户同时允许的会话数 SessionTimeout = "168h" # 会话过期时间 # ------------------- # 播放与转码 # ------------------- FFmpegPath = "/usr/local/bin/ffmpeg" # FFmpeg 可执行文件路径 Transcoding = true # 是否开启实时转码 MaxBitrate = 320 # 转码最大码率 kbps TranscodingCacheMaxSize = "1GB" # 转码缓存大小 AllowDownload = true # 是否允许客户端下载音乐 EnableCoverArt = true # 是否生成封面图 # ------------------- # API 设置 # ------------------- EnableSubsonic = true # 是否开启 Subsonic API SubsonicSalt = "随机字符串" # Subsonic API 密钥盐 EnableWebhooks = false # 是否开启 Webhooks 事件通知 EnableSpotify = false # 是否启用 Spotify 集成 SpotifyClientID = "" # Spotify Client ID SpotifyClientSecret = "" # Spotify Client Secret EnableLastFM = false # 是否集成 LastFM LastFMAPIKey = "" # LastFM API Key EnableListenBrainz = false # 是否集成 ListenBrainz ListenBrainzUsername = "" # ListenBrainz 用户名 ListenBrainzPassword = "" # ListenBrainz 密码 # ------------------- # 缓存设置 # ------------------- ImageCacheMaxSize = "1GB" # 封面图缓存大小 BackgroundCacheMaxSize = "1GB" # 背景缓存大小 编辑完成后，按键盘上的esc键退出编辑模式，然后输入:wq会出保存并退出 使用ls命令查看现有文件 刚刚我们的配置文件中写了数据库路径和音乐文件存放路径，我们需要创建对应的文件夹 使用mkdir命令创建data文件夹和music文件夹，然后使用ls名称查看是否创建对位置 mkdir ./data ./music 安装ffmpeg ffmpeg是开源多媒体处理工具，它主要用于音视频的 编码、解码、转码、录制和流式传输，我们在配置文件中写了启用编码，所以要安装这东西 有点linux源仓库里面有ffmpeg，有点没有，我们直接手动编译安装 说是手动，但是其实就是手动运行脚本 使用vi命令创建一个名称为install_ffmpeg.sh的文件 vi install_ffmpeg.sh 把下面内容复制粘贴进去，或者是直接到本站资源库里面搜索 #!/bin/bash # ============================================= # FFmpeg 静态编译安装/更新脚本 (AlmaLinux) # ============================================= set -e INSTALL_DIR="/usr/local/bin" TMP_DIR="/tmp/ffmpeg_install" FFMPEG_URL="https://johnvansickle.com/ffmpeg/releases/ffmpeg-release-amd64-static.tar.xz" echo "==> 准备临时目录..." rm -rf "$TMP_DIR" mkdir -p "$TMP_DIR" cd "$TMP_DIR" echo "==> 下载最新 FFmpeg..." wget -q --show-progress "$FFMPEG_URL" -O ffmpeg-static.tar.xz echo "==> 解压..." tar xJf ffmpeg-static.tar.xz cd ffmpeg-*-amd64-static echo "==> 安装/更新到 $INSTALL_DIR ..." sudo cp -f ffmpeg ffprobe "$INSTALL_DIR/" sudo chmod +x "$INSTALL_DIR/ffmpeg" "$INSTALL_DIR/ffprobe" echo "==> 清理临时文件..." rm -rf "$TMP_DIR" echo "==> 安装完成！版本信息：" ffmpeg -version echo "==> 如果重新运行脚本，将会更新到最新版本。" 按键盘上的ESC键退出编辑模式，输入:wq回车保存退出 使用chmod命令修改权限，让脚本可以运行 chmod +x install_ffmpeg.sh 运行脚本 ./install_ffmpeg.sh 测试启动 先测试一下是否可以正常启动，启动信息如果没有报错就是成功启动了 ./navidrome 设置开机自启动 进入/etc/systemd/system/文件夹下 cd /etc/systemd/system/ 使用vi命令创建一个名字为navidrome.service的文件 vi navidrome.service 把下面内容根据你的情况修改一下，主要是修改文件路径 [Unit] Description=navidrome daemon After=syslog.target network.target Wants=network.target [Service] Type=simple #启动文件路径 ExecStart=/opt/navidrome/navidrome Restart= always RestartSec=1min ExecStop=/usr/bin/killall navidrome [Install] WantedBy=multi-user.target 按键盘上的ESC退出编辑模式，输入:wq回车保存并退出 使用chmod命令给文件授权 chmod +x navidrome.service 让系统重新读取所有服务配置文件 systemctl daemon-reload 设置开机自启 systemctl enable navidrome 启动、停止、重启命令 启动命令 systemctl start navidrome 停止命令 systemctl stop navidrome 重启命令 systemctl restart navidrome 登录navidrome 使用浏览器，在地址栏输入IP:端口登录navidrome 第一次登录先要创建一个管理员账户 设置中文 点击右上角的用户图标 选择Personal 点击Language的下拉框，找到简体中文并选中 手机端 Navidrome 本身并没有官方手机客户端，但因为它兼容 Subsonic API，所以可以使用任何支持 Subsonic 的第三方音乐客户端。 软件推荐 Android 端推荐 1、Dsub（免费/开源） 支持离线缓存、流式播放、播放列表 支持 Subsonic API，兼容 Navidrome 下载方式： 前往项目地址下载或者本站资源库搜索下载 项目地址：https://github.com/paroj/DSub2000 2、Ultrasonic 界面简洁，支持流式播放和下载 支持多种音频格式 支持 Subsonic API 下载方式： 前往项目地址下载或者本站资源库搜索下载 项目地址：https://github.com/ultrasonic/ultrasonic 3、Subsonic 官方客户端 经典客户端，功能齐全 兼容 Navidrome 下载方式：闭源软件，本站不提供下载，自行百度 iOS 端推荐 1、Marvis Pro 高级音乐管理，支持 Subsonic 2、Subsonic iOS 官方 Subsonic 客户端，可用于 Navidrome 3、Dsub for iOS（部分第三方开发） 类似 Android 端 Dsub 下载方式：IOS端本站不提供下载 软件连接 这里使用安卓端的Dsub为例，其他软件也大同小异 打开软件，点击左上角的三条杠 点击设置 点击服务器 点击添加服务器 点击刚刚添加的服务器，进入编辑 输入服务器名称（随便填）然后服务器地址，用户名，密码，把测试连接上的允许不安全连接 填写完成后点击测试连接，连接成功即可
简介 家里面有一台联系M73，之前用来做软路由的，后面不用软路由了，就放着一直吃灰了，现在打算折腾一下，打算安装win10，做轻办公 但是配置比较低，所以打算安装win10精简版 在网上找了好久，没有找到自己喜欢的win10精简版，打算自己动手精简一个 工具 首先你得有一台电脑，windows系统，这个是基础 然后我们会使用到三个工具 1、微软官方win10下载器 2、MSMG Toolkit 3、DISM++ 工具地址 微软官方win10下载器：https://www.microsoft.com/zh-cn/software-download/windows10 MSMG Toolkit：https://msmgtoolkit.in/downloads.html 也可以前往本站资源库搜索下载 下载工具 如果是前往本站资源库下载的可以忽略此步骤 下载微软官方win10下载器 打开上面我们给的下载地址，点击“创建windows10安装媒体”下面的【立即下载】 下载精简工具MSMG Toolkit 打开我们上面给的地址，点击【Download】 点击【Toolkit_v13.7.7z】，然后点击右边的【Download】 准备工作 创建一个新的文件夹，把我们下载的工具全部丢进去 下载官方win10 双击运行刚刚我们下载的微软win10官方下载器MediaCreationTool_22H2.exe 点击【运行】 等待加载完成，然后点击【接受】 选择为另一台电脑创建安装介质（U盘、DVD或ISO文件），然后点击【下一步】 这里可以保持默认，直接点击下一步，也可以更具自己的情况选择，我是直接保持默认的 选择ISO文件，然后点击【下一步】 选择下载存放的位置和名称，我们直接选择刚刚创建的存放工具的文件夹，也可以选择其他地方，自己知道存放在什么地方就可以，然后点击【保存】 等待下载完成 点击【完成】 加载镜像文件 把我们的精简工具Toolkit_v13.7.7z解压出来，进入解压的文件夹，把刚刚下载的ISO丢到工具里面的ISO文件夹里面 开始 运行工具 返回上一级目录，双击Start.cmd运行工具 这是这个工具的免责申明，大概意思就是使用这个工具自定义的系统在使用过程中出现BUG，数据丢失等行为不关这个工具的事，同意输入A，不同意输入B 输入“A”进入工具 回车继续进入 加载镜像 第一个选项是加载镜像文件，输入1选择镜像文件 我们的镜像文件格式是ISO，选择3 输入镜像文件名称，不用输.ISO 回车开始解压镜像文件 继续回车，退回到第一步，我们还需要加载一次镜像文件，刚刚只是解压出来，并还没加载，继续输入1 在输入一次1加载镜像文件 这里报错了，提示只能使用wim格式的文件，我们的文件是esd格式的，说我们可以使用MCT工具提取，如果没有报错的话就会出现下面选择版本的选项，按回车继续 回到主菜单后，继续输入1 输入6选择使用MCT工具 让我们选择一个版本，这里我选择专业版，输入4，然后回车，等待提取完成 回车继续 再次输入1 再次输入1 可以看到我们刚刚使用MCT工具提取的系统文件了，输入1并回车 输入y继续 第二个输入n，这个是是否加载镜像的启动文件，我们只需要精简系统，不需要修改启动文件，输入n回车 这个是询问是否挂载windows的恢复环境，我们只是精简系统，不用动这个，输入n并回车 等待加载完成 回车继续 删除文件 输入3，选择删除选项 这三个选项是让你选择删除的模式 菜单说明 1 Remove Windows Components 交互式菜单 你进入后会看到系统组件分类（应用、驱动、服务、功能） 可以逐项选择要删除的功能（比如 Cortana、OneDrive、Xbox、Defender、Edge） 适合手动精简，推荐用这个 2 Remove Windows Apps Using Apps List 使用一个文本文件（appslist.txt），里面写明要删除的 UWP 应用 运行后会批量删除列表里的应用 适合已经整理好固定精简方案的人（例如想自动批处理多次精简） 3 Remove Windows Components Using Package List 使用一个 组件包列表文件（packagelist.txt） 可以批量删除系统组件（不仅仅是应用，还包括服务、功能） 属于高级用法，适合有经验的人做“脚本化精简” 一般用于企业批量部署 我们选择1 菜单说明 1 Select Windows Components 进入后会显示组件分类（Apps、System、Multimedia、Defender、Edge 等） 你可以逐项选择要删除的组件 选完后只是“标记”，不会立即删除 2 Start Removing Windows Components 真正开始删除 必须先在 1 里选好要删的东西，再来这里执行 [C] Compatibility 有些组件前面会有 * 星号，说明它们被“兼容性保护”锁住了（为了保证系统更新、某些功能正常） 如果你确定要删除这些锁定组件（比如 Microsoft Edge、Defender 等），需要先在这里解锁 [X] Go Back 返回上级菜单 建议操作顺序 先进 1 Select Windows Components，选你想删除的内容 如果发现某些要删的东西前面带 * → 去 [C] Compatibility 解锁 回来后再进 2 Start Removing Windows Components，执行删除 输入1，进入选择要删除的内容，这是一个分类，我们一个分类一个分类看 Internet 菜单 我们先进入第一个分类，输入1，这里面有两个选项，一个是IE浏览器，一个EDGE浏览器 这个看情况选择，虽然说IE已经弃用了，但是某些特定情况下还是会用到的，例如进入某银行的某系统之类的，大多数人是用不到的，但是为了保持兼容性，不建议删掉 然后就是EDGE浏览器，这个也不建议删除，很多windows的服务还是依赖它的 我们直接按X返回 Multimedia 菜单 输入2进入Multimedia菜单 1 First Logon Animation → 首次登录动画 2 Game Explorer → 旧版游戏中心 3 Lock Screen Backgrounds → 锁屏壁纸 4 Screen Savers → 屏保 6 Sound Themes → 系统提示音主题 8 Wallpapers Themes → 桌面壁纸 9 Windows Media Player → 很多第三方播放器（PotPlayer、VLC）更好用 11 Windows Personalization Themes → 个性化主题包 12 Windows TIFF IFilter (OCR) → OCR 功能，一般人用不到。 13 * Windows System Assessment Tool (WinSAT) → 删除后某些老游戏/旧程序可能报错 根据上面解释，选择自己要删除的东西，我这里选择删除1,2,9,12 注意，删除的需要中间用英文的逗号隔开，输入完成后回车 解锁被锁定项 看到前面有-的就是选中需要删除的了，这里2并没有选中，因为前面带*，我们需要先去解锁 输入x返回 再次输入x返回 输入c进入解锁菜单 为了避免麻烦，后面还需要解锁，我们直接输入a并回车解锁所有，但是如果解锁所有后后面的操作就需要非常小心，选择完需要删除的程序后再次确定一遍，以免删除掉重要东西 看到所有项目前面都变成了-后就是解锁成功了，输入x返回 输入1从新进入删除菜单 从新进入刚刚的Multimedia菜单，把刚刚锁定的不能解锁的重新选择了，输入2 再次输入我们需要删除的选项，刚刚9和12选择成功了，前面有-了，这次我选择1和2，输入1,2回车 可以看到1，2项也选择成功了 输入x并回车返回 Network 菜单 输入3进入 可以看到有9项可以删除 1 Offline Files → 离线文件同步，一般笔记本用户不用 2 OpenSSH → 如果你平时需要远程 SSH 登录，可以保留；不需要可以删 3 Remote Desktop Client → 远程桌面客户端，删掉后无法通过 Windows 自带远程连接远程电脑 4 Remote Differential Compression (RDC) → 远程差异压缩，很少用 5 Simple TCP/IP Services → 很老的 TCP/IP 服务（Character Generator、Daytime 等），没用 6 Telnet Client → Telnet 客户端，现在几乎没人用 7 TFTP Client → 简单文件传输协议客户端，基本不用 8 Wallet Service → 钱包服务，国内用户几乎不需要 9 Windows Mail → 邮件客户端，如果你不使用自带邮件，可删 更具自己的情况选择需要删除的选项 我选择的是1,2,3,5,6,8,9 选择好后回车 检查一下，确定前面有-的选项是我们需要删除的，不要误删了 输入X回车返回 Privacy 菜单 输入4进入Privacy菜单 可以看到总的有11项可以删除 1 Assigned Access → 限制账户使用单个应用，一般个人用户不用 2 Customer Experience Improvement Program (SQM) → 客户体验改进计划，收集使用数据 3 Face Recognition (Windows Hello Face) → 面部识别登录 4 Kernel Debugging → 内核调试工具，一般用户不用 5 Location Service → 位置服务，如果不使用定位功能可删 6 Picture Password → 图片密码登录，不用可删 7 Pin Sign-in Support → PIN 登录支持 8 Unified Telemetry Client → 遥测数据收集，可删 9 Wi-Fi Network Manager (Wi-Fi Sense) → 自动分享 Wi-Fi 密码，可删 10 Windows Error Reporting → 错误报告，可删 11 Windows Insider Program → 预览体验计划，删掉无大碍，但如果你想接收 Insider 预览版更新，可以保留 根据自己的需求选择要删除的东西 我选择的是1,2,4,5,8,9,10,11 确定好我们选中的是我们需要删除的后，输入x回车返回 Remoting 菜单 输入5进入Remoting 有7项可以删除 1 HomeGroup → 家庭组共享功能，Windows 10 之后几乎没人用 2 MultiPoint Connector → 教育/企业多点管理工具，普通用户不用 3 OneDrive Desktop Client → 云同步客户端，如果你还用 OneDrive 就保留；不用可删 4 Remote Assistance → 远程协助功能，不需要可以删 5 Remote Desktop Server → 远程桌面服务，如果你不需要通过 RDS 或 Hyper-V 做远程连接，可以删除 6 Remote Registry → 允许远程修改注册表，安全风险，删掉没影响 7 Work Folders Client → 企业数据同步功能，普通用户不用 一样的，根据自己需求选择，输入序号，然后回车，我选的是1，2，3，7 确定选项无误后，输入x回车返回 System 菜单 输入6进入System菜单 这个选项就多了 1 Accessibility Tools (Ease of Access) → 可访问性核心组件，建议保留 3 Device Lockdown (Embedded Experience) → 特殊定制系统用，普通用户可删 4913 Ease of Access Cursors / Themes / Magnifier / Narrator / On-Screen Keyboard → 依赖 Accessibility Tools，可删但删了后无法使用辅助功能 6 Easy Transfer → 迁移工具，不用可以删 7 File History → 文件历史备份，不用可以删 10 Manual Setup (Windows In-Place Upgrade) → 升级安装依赖，可删但升级环境需谨慎 12 Notepad → 简单文本编辑器，如果你用第三方编辑器，可删 14 Paint → 简单画图工具，可删 15 Projected File System (ProjFS) → 开发或特殊虚拟文件系统用，不用可删 16 Security Center → 依赖 Defender，删除会影响安全中心显示 17 Steps Recorder → 记录操作步骤工具，普通用户可以删 18 Storage Spaces → 磁盘池功能，不用可删 21 Windows Backup → 系统备份工具，可删 22 Windows Firewall → 建议保留，否则防火墙功能可能受影响 23 Windows Subsystem For Linux (WSL) → Linux 子系统，不用可删 24 Windows To Go → USB 便携式系统，不用可删 25 Windows Update → 系统更新核心，建议保留 26 Wordpad → 可删，如果用第三方 Office 或文本编辑器 可以发现这个编号跳过了一些，例如1就到3了，2没有，通常是因为某些组件在当前 Windows 版本中不存在，或者被自动隐藏（比如企业版才有的功能、教育版才有的特定模块） 老规矩，选择自己需要删除的，3,6,7,10,14,16,17,21,23,24,25 检查无误后输入X回车返回 System Apps 菜单 输入7进入System Apps菜单 1 Add Folder Suggestions Dialog → 建议库文件夹弹窗，不用可删 2 App Resolver → 快捷方式解析，不常用可删 3 Assigned Access Lock App → 单应用锁定，不用可删 4 Asynchronous Text Service → 内置应用文本通信，不用可删 5 Call → 系统通话功能，不用可删 6 Captive Portal Flow → OOBE Wi-Fi 登录，不用可删 7 Capture Picker → 截屏选择器，不用可删 9 Content Delivery Manager → 系统推荐内容和广告，不用可删 11 Credential Dialog → Windows Hello 身份验证弹窗，不用可删 12 Desktop App Web Viewer → 系统内网页显示，不用可删 13 Email and Accounts → 系统账户管理，不用可删 14 Eye Control → 眼控功能，不用可删 15 File Explorer (Legacy) → 旧版文件管理器，不用可删 16 File Picker → 文件选择对话框，不用可删 17 Map Control → 地图应用核心服务，不用可删 18 Microsoft Edge (Legacy) → 旧 Edge 浏览器，可删 19 Microsoft Edge Dev Tools Client → Edge 开发者工具，不用可删 20 Microsoft Family Features → 家长控制，不用可删 21 Narrator → 屏幕朗读工具，不用可删 22 Network Connection Flow → OOBE 网络设置，不用可删 23 Network Connectivity Status Indicator (NCSI) → 网络状态监测，不用可删 24 Out-of-box Experience (OOBE) → 系统安装引导界面，仅无人值守可删 25 Pinning Confirmation Dialog → 固定应用确认弹窗，不用可删 26 Quick Assist → 系统远程协助，不用可删 27 Retail Demo Content → 零售演示内容，不用可删 28 Safely Remove Device → 安全弹出 eGPU，不用可删 29 Setting Sync → 跨设备设置同步，不用可删 30 Shell Experience Host → Windows Shell 核心 UI，不建议删 32 Shell Services (Undocked Dev Kit) → 可拆卸设备开发服务，不用可删 33 Skype ORTC → 实时通信开发 API，不用可删 34 SmartScreen → 系统防钓鱼/恶意网址过滤，不建议删 35 Start Menu → 开始菜单管理，建议保留 36 Take a Test → 系统考试应用，不用可删 37 Webcam Experience → 摄像头体验应用，不用可删 38 WebView2 Runtime → WebView2 运行环境，不用可删 39 Windows Barcode Preview → 条码预览工具，不用可删 40 Windows Default Lock Screen → 默认锁屏，可删 41 Windows Defender → 系统防病毒，不建议删 42 Windows Feature Experience Pack → 功能包核心组件，不建议删 43 Windows Hello Setup → 生物识别管理，不用可删 44 Windows Mixed Reality → 混合现实平台，不用可删 45 Windows Print → 打印对话框，不用可删 46 Windows Reader (PDF) → PDF 阅读器，不用可删 47 Windows Search → 系统搜索核心，不建议删 48 Windows Shell Experience → People app 核心服务，不用可删 49 Work or School Account → 企业或学校账户支持，不用可删 50 Xbox Game Callable User Interface → Xbox 游戏 UI，不用可删 输入我们需要删除的选项，我选择的是5，7，9，17，20，21，27，29，32，33，36，39，41，49，50 确认无误后输入x回车返回 Windows Apps 菜单 输入8进入Windows Apps菜单 1 3D Viewer → 3D 模型查看器，不用可删 2 Alarms & Clock → 闹钟/世界时钟/秒表，不用可删 3 App Installer → Windows 应用安装器，删除后不能安装/更新 .appx/.msix 应用 4 Calculator → 计算器，如果有第三方替代可删 5 Camera → 简单相机应用，不用可删 7 Cortana → 数字助理，可删 9 Feedback Hub → 反馈中心，可删 10 Films & TV → 视频播放器，不用可删 11 Get Help → 系统帮助，可删 12 Groove Music → 音乐播放器，不用可删 13 HEIF Image Extensions → HEIF 图片扩展，不看这种格式图可删 15 Mail and Calendar → 邮件和日历，不用可删 16 Maps → 地图导航，不用可删 20 Microsoft .NET Native Framework → UWP 应用依赖，删除可能导致 UWP 应用无法运行 23 Microsoft .NET Native Runtime → UWP 应用依赖，同上 25 Microsoft Advertising SDK → 某些应用依赖，删除可能影响部分 UWP 应用 26 Microsoft Engagement Framework → 商店交互依赖，删除可能影响商店和提示功能 28 Microsoft Pay → 支付应用，早已停用，可删 29 Microsoft Solitaire Collection → 纸牌游戏，可删 30 Microsoft Store - Core → 商店核心，删除会破坏商店 31 Microsoft Store → 商店本体，删除后无法通过商店安装应用 33 Microsoft UI Xaml → UWP 界面框架，删除会导致大部分 UWP 应用崩溃 36 Microsoft Visual C++ 2015 UWP Runtime/Runtime Desktop → 大量 UWP 应用依赖，删除会导致应用运行失败 38 Mixed Reality Portal → 混合现实，不用可删 43 Office Hub → Office 集成入口，不用可删 44 OneNote → 笔记软件，不用可删 45 Paint 3D → 3D 绘图，不用可删 47 People → 联系人，不用可删 48 Photos → 系统自带相册，不用可删（可用第三方替代） 53 Skype → 通话聊天，不用可删 54 Snip & Sketch → 截图工具，不用可删（新版已集成到 Win+Shift+S） 56 Sticky Notes → 便签，不用可删 57 Store Experience Host → 商店购买/下载依赖，删除可能影响商店功能 58 Tips → 系统使用提示，不用可删 59 Voice Recorder → 录音机，不用可删 60 VP9 Video Extensions → 视频扩展，不看 VP9 可删 61 Weather → 天气，不用可删 62 Web Media Extensions → WebM 音视频扩展，不用可删 63 Webp Image Extensions → WebP 图片扩展，不用可删 66 Xbox - Core → Xbox 核心服务，不玩 Xbox 可删 67 Xbox App → Xbox 应用，不用可删 68 Xbox Game bar Plugin → Xbox 工具栏插件，不用可删 69 Xbox Game bar → 游戏工具栏，不用可删 70 Xbox Game Speech Window → 语音转文字工具，不用可删 71 Xbox Identity Provider → Xbox 登录，不用可删 72 Xbox Live → Xbox Live 相关，不用可删 73 Your Phone → 手机连接，不用可删 和之前一样，选择需要删除的，我这里选择1,5,7,9,10,11,12,16,26,28,29,30,43,45,47,48,53,54,56,57,59,60,66,67,68,69,70,71,72,73 确定无误后输入x回车返回 误删后怎么撤回 我们现在执行的是删除的第一步，选择删除的内容，如果这个期间我们选择失误，把不想删除的选中成为删除的了，这时候我们只需要重新进入误选中的地方，把误选中的项目在选一次，让项目前面变“+”即可。 如果自己乱选的，不知道删了什么东，哪些是误删的，那么直接退出工具重新进入重新加载镜像 正式删除文件 前面我们只是选中了要删除的，并还没有正式删除，那个是第一步，输入X返回 输入2开始删除刚刚选中的项目 接下来就是等待即可 删除完成，回车继续 应用修改 第三步执行完成后，一直输入x返回到主菜单 输入6进入“应用”选项 1 Cleanup Source Images using DISM Cleanup-Image 用 DISM /Cleanup-Image 清理挂载的 Windows 映像 (install.wim)。 作用：删除无用的文件、压缩资源、优化镜像大小。 建议：修改完之后，最后再做一次清理（可选，但推荐）。 2 Apply & Save Changes to Source Images 把你在 Remove / Integrate / Customize 中的所有改动，真正写入 install.wim。 相当于 “保存修改”。 必须执行，否则你前面删除/集成的东西不会生效。 这是最关键的一步，通常一定要选。 3 Discard Changes & Unmount Source Images 放弃你本次所有修改，退出并卸载映像。 相当于 “不保存，丢弃更改”。 如果你操作失误、删错了东西，可以选这个来放弃。 注意：之前的步骤会白做，需要重新加载源镜像再修改。 我们先执行第2选项，输入2，会询问在保存修改之前，要不要顺便清理 Image 文件夹里的临时文件，输入y 然后就是等待 完成后，回车继续 打包镜像 输入7 菜单说明 1 Make a DVD ISO Image ➝ 把你刚刚修改过的 Windows 安装源（含 install.wim）打包成一个 ISO 文件，以后可以刻录光盘、写入 U 盘，或者直接用虚拟机安装。 2 Burn an ISO Image to DVD ➝ 把现成的 ISO 文件刻录到 DVD 光盘（要求电脑有光驱，比较少用了）。 3 Copy Source to USB Flash Drive ➝ 直接把 Windows 安装文件复制到一个 USB 启动盘（但这个 U 盘可能还不是可启动的，需要额外处理引导）。 4 Sync Source Boot & Install Images to USB Flash Drive ➝ 如果你之前已经做了一个启动 U 盘，这里可以用最新修改的 boot.wim / install.wim 覆盖到 U 盘，而不用整个重新制作。 5 Burn an ISO Image to Bootable USB Flash Drive ➝ 把 ISO 直接写入 USB，使其成为 完整的可启动安装 U 盘（和 Rufus、Ventoy 类似的功能）。 6 Format a USB Flash Drive ➝ 格式化 U 盘，做准备用。 我们选择1，打包成ISO镜像 输入卷包名名，不需要输入后缀名，输入完成后回车继续 输入文件名，不需要输入后缀，输入完成后回车继续 等待即可 打包完成
简介 前几天发现frp穿透上传速度比较慢还不稳定，所以找了一些方法，但是都没有什么太大作用 目前发现修改 socket 缓冲区大小这个方法有点用，这里记录一下怎么操作 调大 rmem/wmem（socket 缓冲区大小）其实就是在 内核 TCP 缓冲机制上动手脚，对传输性能会有明显影响。 正面效果 首先说一下正面效果，也就是优点 提升长肥管道的吞吐 高延迟 + 高带宽 的链路（比如跨境、隧道、卫星链路）需要更大的 TCP 窗口才能“装下”足够多的数据包。 否则，RTT 期间的数据太少，带宽利用率不高 → 上传/下载速度被限制。 减少丢包导致的性能下降 较大的缓冲允许更多数据在内核中排队，能吸收突发的流量，降低因为瞬间溢出导致的丢包。 改善隧道/代理（frp、VPN 等）的上传表现 这类程序往往要处理多路复用/转发，如果缓冲太小，很容易成为瓶颈。 负面效果 既然有优点，那么肯定有缺点，如果盲目的调整，过大或者国小都是有影响的 增加延迟（bufferbloat） 缓冲过大时，数据积压在内核队列里，应用层以为“发出去了”，实际上还在等内核慢慢吐。 会导致交互类应用（SSH、游戏、VoIP）延迟变大。 内存占用增加 如果有成千上万个并发连接，每个都能申请几 MB 的缓冲，可能迅速吃掉系统内存。 不能解决带宽不足或物理丢包问题 它只是让 TCP 能“吃得下更多”，但如果线路本身抖动大、丢包多，依然会卡。 调整方法 首先我们可以使用临时调整的方法来测试，找到一个适合的大小，找到后在改成永久的 临时调整 临时调整重启后会失效 最大缓冲限制 sysctl -w net.core.rmem_max=16777216 sysctl -w net.core.wmem_max=16777216 TCP 读写缓冲（最小 / 默认 / 最大） sysctl -w net.ipv4.tcp_rmem="4096 87380 16777216" sysctl -w net.ipv4.tcp_wmem="4096 65536 16777216" 查看是否生效 sysctl net.core.rmem_max net.core.wmem_max sysctl net.ipv4.tcp_rmem net.ipv4.tcp_wmem 永久调整 永久调整重启后任然有效 方法一：直接写到 /etc/sysctl.conf 编辑配置文件： vi /etc/sysctl.conf 在文件末尾加上： # for frp upload speed net.core.rmem_max=16777216 net.core.wmem_max=16777216 net.ipv4.tcp_rmem=4096 87380 16777216 net.ipv4.tcp_wmem=4096 65536 16777216 保存退出后执行： sysctl -p 方法二：单独建一个配置文件（推荐） 更干净，方便管理。 vi /etc/sysctl.d/99-frp-tuning.conf 写入： # frp upload tuning net.core.rmem_max=16777216 net.core.wmem_max=16777216 net.ipv4.tcp_rmem=4096 87380 16777216 net.ipv4.tcp_wmem=4096 65536 16777216 应用配置： sysctl --system 验证是否生效 sysctl net.core.rmem_max net.core.wmem_max sysctl net.ipv4.tcp_rmem net.ipv4.tcp_wmem 应该能看到刚设置的值。
简介 时隔多日，Robot Framework系列再次更新 这次更新主要是搬朋友写了一个小脚本，里面用到的东西是之前没有说过的，所以更新一下，佛系更新 介绍 Robot Framework循环主要有两种 一种是FOR循环，经典传统风格 另外一种是FOR IN循环，现代风格，可以处理列表或者范围 Robot Framework 的循环写法与 Python 类似，但语法有自己的特点，尤其是在缩进和结束循环标记上。 FOR循环 这个循环主要用于重复执行一段测试步骤若干次 第一种用法 写法 FOR ${i} IN RANGE 5 Log Iteration ${i} END ${i}是循环变量，可以不用，但必须有 IN RANGE 5表示循环5次，从0开始，0是第一次，到4结束，4就是第五次了 Log是循环体中的关键字，每循环一次执行一次，可以替换成你需要循环执行的关键字或命令 END结束循环 下面是我帮朋友写的脚本里面的一段循环，经过简化后的，主要是用于讲解FOR循环 FOR ${I} IN RANGE 1000 点击促销管理 点击人员库 点击部门 Reload Page END 第一行，对照上面的解释，可以看到我需要循环1000次，也就是0-999 第一行后面到END中间就是我需要循环执行的 上面的这一段就是循环依次执行“点击促销管理”、“点击人员库”、“点击部门”和刷新页面，这几个操作依次循环执行1000次 第二种用法 写法1 FOR ${item} IN apple banana orange Log Fruit: ${item} END 这个用法我的脚本里面还没有用到，但是如果你理解了上面的用法，那么这个用法就很好理解了 首先是第一行FOR ${item} IN apple banana orange，可以看到IN后面又三个值，分别是apple、banana、orange 然后中间部分我们执行的是Log Fruit: ${item}，这个是打印输出${item}这个变量 最后是循环结束END 首先理解这个循环的操作，可以看出这个循环主要就是循环打印输出${item}这个变量 ${item}这个变量的值就会依次等于IN后面的值 也就是说第一次循环的时候，打印输出的内容是Fruit：apple 第二次循环则打印输出Fruit：banana 第三次循环打印输出Fruit：orange 这个是依次的，当IN后面的值都循环完成后停止循环 这个循环可以用来填写表单之类的，每次填写的值都不一样，只需要把每次需要填写的值写在IN后面即可 写法2 Robot Framework 4.0 之后推荐使用这种写法，语法更清晰，也可直接用于 Test Case 或 Keyword FOR ${item} IN @{fruits} Log Fruit: ${item} END 这个写法和第一种写法作用是一样的，只是变了一个写法而已 @{fruits}是列表变量，可以直接理解为是一个列表 循环会遍历列表中的每个元素，适合处理外部数据或变量列表。 示例 *** Variables *** @{fruits} apple banana orange *** Test Cases *** Loop Over List FOR ${fruit} IN @{fruits} Log Today I eat ${fruit} END 首先我们在*** Variables ***下面创建了一个列表变量 @{fruits}，它的值等于apple banana orange，也就是它有三个元素 然后我们在*** Test Cases ***下面创建了一个测试用例，名字为Loop Over List 这个测试用例就是执行 FOR ${fruit} IN @{fruits} Log Today I eat ${fruit} END 这个和上面一样，循环打印${fruit}这个变量，然后这个变量等于@{fruits}这个列表变量，@{fruits}这个列表变量里面有三个元素，所以会循环三次 执行后就会打印输出下面内容 Today I eat apple Today I eat banana Today I eat orange WHILE 循环 这个循环可以理解为判断加循环 WHILE 循环语法规则 WHILE <条件表达式> # 循环体（只要条件为真（满足），就一直执行） END 示例 ${BM}= 获取人员库部门 WHILE '${BM}' == '' 点击空白部门 修改班级 20240715期昌明工贸 修改考勤规则 固定班次1 点击保存 强制等待2秒 点击返回 ${BM}= 获取人员库部门 END 首先获取人员部门，并赋值到${BM}里面 然后使用WHILE 循环，当${BM}等于空的时候执行点击空白部门、修改班级、修改考勤规则、点击保存、强制等待2秒、点击返回、再次获取人员部门并赋值到${BM}，这样只要一直查询到人员部门为空就会一直修改，直到没有人员的部门是空的就会停止循环 循环中的控制语句 Exit For Loop：立即退出循环。 Continue For Loop：跳过本次循环，进入下一次。 嵌套循环 Robot Framework 支持嵌套循环，但需要注意缩进 例如下面这一段，我使用的就是嵌套循环 FOR ${I} IN RANGE 1000 点击促销管理 点击人员库 点击部门 ${BM}= 获取人员库部门 WHILE '${BM}' == '' 点击空白部门 修改班级 20240715期昌明工贸 修改考勤规则 固定班次1 点击保存 强制等待2秒 点击返回 ${BM}= 获取人员库部门 END Reload Page END 首先第一行，可以看出需要循环100次 然后中间部分就是需要循环执行的关键字 上面那一段的作用就是循环点击促销管理，点击人员库，点击部门，然后获取人员部门，如果人员部门为空则进入第二个循环，点击空白部门，修改班级，修改考勤规则，点击保存，强制等待2秒，点击返回，再次获取人员部门，到这里的时候${BM}变量的值已经改变更新了，如果这次获取到的人员部门还是空的那么就继续循环点击空白部门直到再次获取人员库部门，如果后面获取到的人员库部门不是空的了那么就会结束WHILE循环，但是还是处于FOR循环里面，会进行刷新操作，然后再次点击促销管理，到获取人员库部门，如果是空的那么进入WHILE循环，如果不是空的则执行刷新操作。
使用cloudflare代理后无法访问或者重定向过多解决方法
简介 这几天本地电信网络不知道怎么回事，走frp的线路一直拥堵，导致博客访问缓慢，所以想启用cloudflare的代理来解决 但是启用代理后出现几个问题 1、启用代理后访问博客出现重定向过多 2、启用代理后直接无法访问博客 下面是这两个问题的解决方法 重定向过多 这个是因为网页在不同地址之间不停跳转，形成了循环，打开代理后才出现的问题，关闭代理后就正常，说明是代理的问题 登录cloudflare，点击域名 点击右边的【SSL/TLS】 点击【配置】 在“自定义SSL/TLS”里面选择【完全】 最后点击【保存】即可 开启代理后不能访问 这个是因为cloudflare的免费套餐的代理是有端口限制的，我们只需要把服务的端口改到cloudflare支持代理的端口即可 下面是cloudflare免费套餐可以代理的端口 HTTPS (SSL) 代理支持： 443（标准 HTTPS） 2053, 2083, 2087, 2096, 8443 HTTP 代理支持： 80（标准 HTTP） 8080, 8880, 2052, 2082, 2086, 2095 最后结果 虽然启用了代理后，连接稳定了，但是延迟偏高，体验并不是很好，只能说是比以前好一点吧，看看后续本地网络运营商有没有改善或者是有没有其他解决方法吧