最近给手机刷的类原生待机耗电一直都很高，试了很多办法都无法解决。而且如果不刷谷歌框架的话，通过 aurora store 安装的 telegram 登录又提示要收费一美元。Microg 用来代替谷歌框架又很不优雅。还是刷回 MIUI 吧。刷机半生，归来仍是 MIUI。刷了 MIUI 后，待机暂时又正常了。但是又遇到一个问题：使用 adb install 命令安装 app 失败，给我提示 Failure [INSTALL_FAILED_USER_RESTRICTED: Install canceled by user]。然后今天摸索，只要打开 USB 调试 和 USB 安装，并且最重要的 关闭 MIUI 优化。就可以通过 adb 安装 app 了。不过居然要插入 sim 卡才能开启 USB 安装，和类原生相比限制多多......至于 MIUI优化 这个开关倒是有点陌生，关闭时会提示：多项系统应用可能无法使用，文字排版、账号、文档界面会发生重大变化。这个功能大概就是 MIUI 修改了 Android 的一些接口，让其更适合国内的应用环境。所以才会导致 adb install 命令失败。以下这篇文章介绍 miui 优化 比较详细。小米手机的系统优化（MIUI 优化）是什么？如何关闭？ | 部落驿站
Scoop 是在 Windows 中的一个包管理软件。优点环境纯净：不修改注册表，不污染 Windows 环境。删除应用时，直接删除文件夹即可，不留注册表垃圾。安装自动化：安装应用时无需手动“下一步”，Scoop 社区已经写好了安装脚本，一键执行。更新方便：可以方便地手动更新所有应用到最新版。在我看来，Windows 上的应用多更新利大于弊，能避免很多问题（比如我最近遇到 v2ray 旧版被 ufw 识别的风险，以及旧版 QQ 发文件对方看不到等问题）。数据持久化：使用 uninstall 命令卸载应用会保留数据，但是可以使用 scoop uninstall --purge <app_name> 命令完全删除。不用担心下载到盗版 steam。遇到的一些问题因为它不碰注册表，像“添加到右键菜单”这样的功能就需要手动操作。它没有安装页面，一些选项（如创建快捷方式、设为默认程序）就无法选择。比如我安装 Wireshark 时，它没有自动帮我装 npcap 驱动。一些写的不好的调用脚本不会调用 path 环境变量找程序，而是硬编码在 program files 目录下寻找。比如说我在安装 rime 输入法后，使用脚本安装雾凇拼音时，找不到 scoop 安装的 git。一些比较冷门的应用，比如说 picgo，就没有将脚本更新到最新。旧版 picgo 打不开 npm 插件仓库。解决办法但后来我发现，前两个问题其实都不是问题。Scoop 的维护者们早已考虑到了，并通过一种巧妙的方式解决了：答案就在 scoop info <应用名> 命令里。一般这样写：Name : 7zip Description : A multi-format file archiver with high compression ratios Version : 25.01 Source : main Website : https://www.7-zip.org License : LGPL-2.1-or-later Updated at : 2025/9/27 17:19:33 Updated by : Rafael Ledo Installed : 25.01 Binaries : 7z.exe | 7zFM.exe | 7zG.exe Shortcuts : 7-Zip Notes : Add 7-Zip as a context menu option by running: reg import "<root>\install-context.reg"就需要我们打开管理员，输入上面的 "reg import \"$dir\\install-context.reg\" 导入注册表了。对于第三个问题，一些老的或者写的不好的脚本用的硬编码解决不了，这时候只能手动调用程序解决了。第四个问题，只能手动安装新版的了，更优的方案是，在 GitHub 上找到对应的 Bucket 仓库，修改应用的 Manifest 文件（JSON格式），然后提交一个 Pull Request。这既解决了自己的问题，也帮助了整个社区。我用 bucket：dorado，主要是对国产软件适配。main，自带的。extra，主要安装的软件。game，Epic Games 或者 steam 在这里安装。参考Scoop——也许是Windows平台最好用的软件（包）管理器
以前我是一个保守派，认为系统和应用只要用旧的就好，新的都是堆了一些华而不实的功能，容易出 BUG ，并且为了新特性会消耗更多硬件资源。但是当我从最近的事情中改变了我的看法。WindowsWin 10 的睡眠问题困扰了我很久。Win 10 进入长时间睡眠后，大概率无法唤醒 (也就是睡死)，不得不强制关机。本来我是可以容忍的，因为我安装了 Linux 并打算大部分时间都使用 Linux。但是我为了解决 win 10 睡眠问题，打算用 s 3 睡眠，修改了注册表，关闭了虚拟机功能。最后也没成功开启 s 3 睡眠。恢复回去的时候，就遇到让我头疼的问题了。Linux 的睡眠功能也出现了异常：从睡眠中唤醒后反复进入睡眠两次。在 Linux 中改了一些设置还是无效。估计是 Windows 的异常睡眠影响到 Linux。而且 Windows 强制关机后，Linux 还会掉 Windows 所在固态的挂载，不得不使用启动 Windows 使用 chkdsk C: /f 修复才能重新挂载。将 Windows 的驱动更换成笔记本官方推荐的也无济于事。无奈重装一下系统，看看 Windows 11 怎么样，却发现 Windows 11 带来了意外之喜。睡眠问题终章更新 Windows 11 系统解决了睡眠问题。睡眠功能需要进入 cmd 键入 powercfg /hibernate on 打开睡眠功能。然后在 控制面板、硬件与声音、电源选项、系统设置 里面关闭快速启动。恢复 Windows 的右键菜单和磁贴磁贴通过 start 11 恢复 Windows 10 样式。右键菜单通过 zyperwin++ 恢复成 Windows 10 样式。（这个软件还可以激活 Windows 和下载 office 并激活的功能）Windows 11 升级体验然后是 Windows 从 10 升级到 11，带来了以下改进：休眠睡眠功能迎刃而解。有了平铺和工作区。文件资源管理器有了类似浏览器的标签页。声音设置可以单独控制多个应用的音量大小。文件压缩支持 rar、7 zip、tar。（我重装系统前的 7 zip 大概版本太久了，Win 11 的解压不能解压之前的 7 zip 压缩包）Win 11 也优化了开机自启文件的逻辑，现在是启动桌面后优先保证桌面的流畅度，然后依次打开自启动应用。以上的功能我都曾在 Windows 10 上浪费时间搜索过通过其他应用弥补。Windows 11 也不是十全十美，内存占用比 Win 10 更多。但这是为了人的体验带来的硬件消耗，如果这么想也不是不能接受。Win 11 当然也有在内存紧张的时候释放内存的策略，所以没必要有内存焦虑。自动平铺快捷键Win + 方向键 移动窗口。Win + m 隐藏。工作区快捷键Win + Ctrl + 左右 移动工作区。Win + Tab 移动打开任务视图。Win + Ctrl + D 创建工作区。手机系统升级体验手机从 HyperOS 2 升级到 HyperOS 3，有了岛的功能。这个感知最明显。还有一些细节上的优化，让我之前觉得特别丑陋的都重做了。大多数人说升级后系统流畅很多，我不是细节怪就感知不大了。并且功耗也稳住了。HyperOS 2 一天充多少次电，HyperOS 3 也差不多。一些新功能、新特性，只有大版本更新才会有。但是考虑到我朋友由于自动更新 Windows 11 导致蓝屏，和我遇到过更新显卡驱动导致打开 Steam 就系统崩溃，更新的风险也是不容忽视。更新策略思考那么该更新什么，不该更新什么？以下是我的思考：国内软件非必要不更新，如果一个软件功能完善，更新一般是为了增加广告和一些非必要的功能。国外软件如 Telegram，国际版 Bilibili 考虑可以更新。系统大版本更新看风评，是否有自己需要的功能。比如说 MIUI 13 到 HyperOS 1 就是掉进一个坑，但是 HyperOS 2 到 HyperOS 3 就是提升。电脑操作系统尽量更新安全补丁。结语Windows 10 将于 2025 年 10 月 14 日停止支持。所以，如果你像我一样之前对 Windows 11 有偏见，大可以趁这个机会换到 win 11。它带来了新的特性，持续的维护，还有解决 Windows 10 顽固 bug 的可能。至于好不好用，自己试了才知道。人生就像巧克力，你永远不知道下一块是什么味道。但是，尝试是一切的起点......
本笔记详细记录了使用 Redmi AC 2100 路由器刷入第三方固件，并通过脚本实现校园网网页认证的步骤和经验。Rm 2100选择这个型号的原因是 5 g 能通过刷老毛子固件开启 160 mhz。而且恩山讨论数挺多，感觉也许有很多刷机的方案。宿舍宽带就 500 m，rm 2100 的 5 G Wi-Fi 速率是 1733 Mbps，使用起来绰绰有余。为什么不用之前刷过的 r3g 呢？因为 r3g 散热弱于 rm 2100，5g 信号速率也才 800 mbps，宿舍使用还是追求信号好和稳定，就不打算折腾这么多插件了。固件和一些需要的软件老毛子 支持开启 160 mhz 的固件： padavan，搜索 RM 2100，下载 RM 2100_3.4.3.9-099. Trx。QB-BOOT: 适配RM2100的pb-boot正式版（大雕）-小米无线路由器及小米网络设备-恩山无线论坛 - Powered by Discuz!Breed：因为官方breed 这个网站挂掉了，然后自己找到了放自己网盘里：来自 123 云盘的分享：breed 链接：https://www.123684.com/s/rlO3jv-8s4nH 提取码：Kzg 5Openwrt 带过校园网检测插件：这个看情况选择，有多播。【2024-9-15】自编译Redmi AC2100固件，集成UA2F等，可用于校园网防检测等功能-小米无线路由器及小米网络设备-恩山无线论坛 - Powered by Discuz!官方降级包：来自 123 云盘的分享：miwifi_rm 2100_firmware_d 62... 链接：https://www.123684.com/s/rlO3jv-Ks4nH 提取码：d 8 sA降级首先需要将官方固件降级成 2.0.7 。因为旧版固件才有注入漏洞。进入路由器后台，上传上面的官方降级包。重启之后就降级成功了。注入刷入 breed从恩山中看到的注入刷入 breed 方案小米 红米【AC2100】一键刷BREED【30秒刷完】小白帅小伙专用 检查坏块 | 无需Telnet-小米无线路由器及小米网络设备-恩山无线论坛 - Powered by Discuz!核心步骤主要是因为官方breed 无法访问了，不能直接使用教程里面的注入 url，只能先下载 breed，然后开一个本地服务器，获取本地的 breed 刷入。（如果后面还是无法访问，只能使用我这个方法了）获取本机 ip 和路由器 ip。登录路由器后台，查看 url，将 stok 后面的值复制下来。在 breed 固件下载文件夹目录输入 cmd 进入命令行。开启一个本地服务器，python -m http.server 8080 --bind 0.0.0.0 。不要关闭这个窗口。然后是获取 breed 的 sha 256 值，certutil -hashfile breed.bin SHA256。一定要关闭 Windows 的防火墙和杀毒软件!!!然后就可以拼接成一个注入 url 了。http://【路由器的IP地址】/cgi-bin/luci/;stok=【路由器的Stok】/api/misystem/set_config_iotdev?bssid=Xiaomi&user_id=longdike&ssid=%0Acd%20%2Ftmp%0Acurl%20http%3A%2F%2F【您电脑的IP地址】%3A【HTTP服务器端口】%2F【固件文件名】%20-o%20B%0A%5B%20-z%20%22%24(sha256sum%20B%20%7C%20grep%20【固件的SHA256校验值】)%22%20%5D%20%7C%7C%20mtd%20-r%20write%20B%20Bootloader%0Ahttp://【路由器的IP地址】/cgi-bin/luci/;stok=【路由器的Stok】/api/misystem/set_config_iotdev?bssid=Xiaomi&user_id=longdike&ssid= cd /tmp curl http://【您电脑的IP地址】:【HTTP服务器端口】/【固件文件名】 -o B [ -z "$(sha256sum B | grep 【固件的SHA256校验值】)" ] || mtd -r write B Bootloader回车后看到路由器重启，灯会从蓝变橘，最终变蓝进入系统。接着断开电源，顶住 reset 键，接上电源，如果闪蓝灯那就是 BREED。如果是闪橘灯那就是原厂 UBOOT。闪蓝灯就可以松开 reset 键了。用网线将电脑连接路由器的 lan 口，将以太网中的 ip 改成固定 ip 192.168.1.100，子网掩码 255.255.255.0。浏览器使用无痕模式打开 192.168.1.1。此时进入 breed 后台。摸索过程一开始是直接使用注入 url，然后发现 url 中获取 breed 的网址不能访问了，理所当然虽然返回是 code 0，但刷入失败。然后是刷的 22 年的 breed，sha 256 和原来注入代码中值的不一样，无法通过验证。刷入 padavan刷入 breed 后，我尝试刷入了老毛子和 openwrt 固件，都是等了几分钟 wifi 列表中都没出现新的 wifi。大概率是刷入失败。然后看到这个帖子红米AC2100(rm2100)breed刷入padavan老毛子无法进入、坏块 通过breed刷入pb-boot解决-小米无线路由器及小米网络设备-恩山无线论坛 - Powered by Discuz!刷入固件前需要备份大体意思是要在 breed 刷入 pb-boot，因为 breed 没有坏块检测功能。最后在 pb-boot 中刷入 padavan，这是正确的，路由器成功重启看到 PCDN 的 WiFi！进入到后台后需要双清。通过校园网认证我们学校对所有接入校园网的设备都需要通过网页验证，除此之外似乎没有其他检测限制手段了。路由器接入校园网后，如果未认证，所有连接路由器的设备都会提示未验证，验证后才能联网。如果让路由器通过验证就可以让宿舍所有设备无需验证了。有两个方法：第一个方法是让电脑通过验证后，路由器克隆电脑的 MAC，但是这个方法有点麻烦了，优点是官方固件自带 mac 克隆。另一个方法就是写一个脚本，让路由器开机执行，这也是我刷机的理由。F 12 抓包发现学校登录请求是 get，后面测试发现学校有线和无线是两套登录系统。（今年三月我拿着朋友的有线验证的脚本无线桥接一直失败，终于找到原因了）特性无线 Wi-Fi (eportal)有线网络 (Dr. Com）服务器 IP10.0.1.5 (801 端口)10.0.1.5 (80 端口)登录地址/eportal/portal/login/drcom/login密码格式Base 64 编码明文用户名格式,0, 学号学号@运营商#!/bin/ash # --- 运营商代码 --- # 中国联通: unicom # 中国移动: cmcc # 中国电信: telecom -------------------- # ccount Information --- USERNAME="" PASSWORD="" OPERATOR_CODE="" # --- End of Configuration --- COOKIE_FILE="/tmp/drcom_cookies.txt" FULL_USERNAME="${USERNAME}@${OPERATOR_CODE}" ACTIVATE_URL="http://10.0.1.5/drcom/auth_msg.php?callback=dr1002" # Define the activation URL globally echo "Dr.COM Ultimate auto-login script started (with keep-alive and delays)..." # --- Main Loop --- while true; do # Step 1: Use the ultimate detection method by checking web content. if curl -s --connect-timeout 4 http://www.baidu.com/robots.txt | grep -q "User-agent"; then # Network is online -> send keep-alive packet. current_time=$(date "+%Y-%m-%d %H:%M:%S") echo "[${current_time}] Network is online. Sending keep-alive packet..." curl -s -b "$COOKIE_FILE" "$ACTIVATE_URL" -H "User-agent: Mozilla/5.0" > /dev/null else # Network is down -> execute login procedure. echo "[WARN] Network connection is down or abnormal. Attempting to re-login..." echo " - Login account: $FULL_USERNAME" rm -f "$COOKIE_FILE" LOGIN_URL="http://10.0.1.5/drcom/login?callback=dr1003&DDDDD=${FULL_USERNAME}&upass=${PASSWORD}&0MKKey=123456" LOGIN_RESPONSE=$(curl --connect-timeout 5 -s -c "$COOKIE_FILE" "$LOGIN_URL" -H "User-Agent: Mozilla/5.0") if printf "%s" "$LOGIN_RESPONSE" | grep -q '"result":1'; then echo "[SUCCESS] Login authentication successful!" # Add a delay to wait for the authentication system to respond. echo " - Waiting 2 seconds before activation..." sleep 2 # Send activation request. curl -s -b "$COOKIE_FILE" "$ACTIVATE_URL" -H "User-agent: Mozilla/5.0" > /dev/null # Add a delay to wait for the network gateway to apply the new rules. echo " - Activation request sent. Waiting 5 seconds for network to stabilize..." sleep 5 if curl -s --connect-timeout 4 http://www.baidu.com/robots.txt | grep -q "User-agent"; then echo "[SUCCESS] Network has been activated, and internet access is restored." else echo "[FAIL] Network activation failed. Login was accepted, but the internet is still unreachable." fi else echo "[FAIL] Login authentication failed!" MSG=$(printf "%s" "$LOGIN_RESPONSE" | sed -n 's/.*"msg":"\([^"]*\)".*/\1/p') if [ -n "$MSG" ]; then echo " - Server response: $MSG" else echo " - Failed to connect to the login server or received an unexpected response." fi fi fi # Loop interval: 10 seconds. sleep 10 done ) &red Network Auto-Login Script # Version optimized for router environments like Padavan. # --- 请在这里填入您的账号信息 --- USERNAME="" PASSWORD="" OPERATOR_CODE="" # 运营商选项: unicom (联通), cmcc (移动), telecom (电信) # --- 配置结束 --- # 使用一个固定的Cookie文件路径，因为mktemp命令不可用 COOKIE_FILE="/tmp/drcom_cookies.txt" # 构造带运营商后缀的完整用户名 FULL_USERNAME="${USERNAME}@${OPERATOR_CODE}" # 脚本开始时先尝试清理可能存在的旧Cookie文件 rm -f "$COOKIE_FILE" echo "[*] 开始登录 Dr.com 有线网络 (10.0.1.5)..." echo " - 正在使用账号: $FULL_USERNAME" # --- 步骤1: 核心登录请求 --- # -c "$COOKIE_FILE" 会将服务器的会话Cookie保存到我们的文件中 LOGIN_URL="http://10.0.1.5/drcom/login?callback=dr1003&DDDDD=${FULL_USERNAME}&upass=${PASSWORD}&0MKKey=123456" LOGIN_RESPONSE=$(curl -s -c "$COOKIE_FILE" "$LOGIN_URL" -H "User-Agent: Mozilla/5.0") # --- 检查登录结果 --- if echo "$LOGIN_RESPONSE" | grep -q '"result":1'; then echo "[+] 登录成功! 服务器已确认身份。" sleep 1 # --- 步骤2 & 3: 开始无限循环保活 --- # -b "$COOKIE_FILE" 会将Cookie发送回服务器 KEEPALIVE_URL="http://10.0.1.5/drcom/keepalive?callback=dr1002&DDDDD=${FULL_USERNAME}&upass=${PASSWORD}&0MKKey=123456" echo "[*] 正在发送首次保活请求以激活网络..." FIRST_KEEPALIVE_RESPONSE=$(curl -s -b "$COOKIE_FILE" "$KEEPALIVE_URL" -H "User-Agent: Mozilla/5.0") if echo "$FIRST_KEEPALIVE_RESPONSE" | grep -q '"result":1'; then echo "[+] 网络已激活！现在开始周期性保活..." else echo "[-] 网络激活失败！请检查脚本或网络环境。" echo " - 激活请求URL: $KEEPALIVE_URL" echo " - 服务器响应: $FIRST_KEEPALIVE_RESPONSE" # 失败时清理Cookie文件 rm -f "$COOKIE_FILE" exit 1 fi while true; do sleep 30 # 周期性保活，发送现有Cookie(-b)并保存可能更新的Cookie(-c) KEEPALIVE_RESPONSE=$(curl -s -b "$COOKIE_FILE" -c "$COOKIE_FILE" "$KEEPALIVE_URL" -H "User-Agent: Mozilla/5.0") if echo "$KEEPALIVE_RESPONSE" | grep -q '"result":1'; then current_time=$(date "+%H:%M:%S") printf "[+] 保活成功, 网络在线 [${current_time}]。下次检测在30秒后... \r" else echo "\n[-] 保活失败! 可能已掉线，脚本将退出。" # 失败时清理Cookie文件 rm -f "$COOKIE_FILE" exit 1 fi done else echo "[-] 登录失败!" MSG=$(echo "$LOGIN_RESPONSE" | sed -n 's/.*"msg":"\([^"]*\)".*/\1/p') echo " - 服务器响应: $MSG" fi chmod +x <脚本名> 赋予执行权限，然后执行就行了。偶遇学校断网正用着 Wi-Fi，舍友突然断网了。还以为是路由器的 DNS 出现了问题。推测应该是学校网络强制劫持所有 DNS，然后学校的 DNS 服务故障了。为什么这样呢，因为此时我还是能用 Wi-Fi 正常上网的，同时我也开了代理。代理会将 DNS 请求加密让代理服务器发起 DNS 解析。搜了下是 DoH （DNS on HTTPS）相关的知识。如果想让宿舍在学校 DNS 服务故障的时候正常使用，有一个解决办法就是安装 AdGuardhome，在我刚刚安装好后，学校网络又恢复正常了。下次再测试吧。参考红米AC2100(rm2100)breed刷入padavan老毛子无法进入、坏块 通过breed刷入pb-boot解决-小米无线路由器及小米网络设备-恩山无线论坛 - Powered by Discuz!小米 红米【AC2100】一键刷BREED【30秒刷完】小白帅小伙专用 检查坏块 | 无需Telnet-小米无线路由器及小米网络设备-恩山无线论坛 - Powered by Discuz!
自建图片 api，压缩图片优化网站加载速度
之前一直是用第三方图片 API 当作博客文章封面，但是有一些图片并不符合我的审美。API 的图片挺大的，用来当作壁纸合适，但是用来当小小的文章封面未免大材小用。一页博客，加载一张 API 的图片还好，加载多张就算是懒加载也有点力不从心了。尝试过给 API 后面加上参数，限制长宽，似乎无效。那还不如自己搞一个图片 API，里面放上我喜欢的图片。于是就有了下面的折腾。还有就是用上了 picgo cli，好像还有个压缩插件，就研究了下。用到了 FFmpeg，Cloudflare worker，picgo compress 插件，还有几个图片在线处理网站。图片获取用了几张原来的 API 的图片，其他的是 B 站一个 up 的视频封面。用了获取B站(bilibili)视频封面图 – 下载 🦊 Firefox 扩展（zh-CN） 这个拓展获取。油猴脚本都过期无效了，功能也正常。图片处理抠图在线抠图软件\_图片去除背景 | remove.bg – remove.bg，用了这个网站抠图，效果还不错。在线处理Photopea | Online Photo Editor，本来想左侧左下角任务占比百分之五十的，想了想没必要，不过这个网站还是比较直观的。切割指定大小，转化 webp 格式用到了 FFmpeg，这个真是个强大的软件。用 F12 查看到封面图片的宽度，不过一般要留大一点，可能有写屏幕大一点避免模糊。#!/bin/bash # --- 配置 --- # 输入文件夹名 (仅在批量模式下生效) INPUT_DIR="半成品" # 输出文件夹名 OUTPUT_DIR="output_webp" # 目标宽度 (高度会按比例自动缩放) TARGET_WIDTH=570 # WebP 图片质量 (0-100, 推荐 80) QUALITY=80 # --- 脚本开始 --- # 创建输出文件夹 (这是一个通用操作，提前执行) mkdir -p "$OUTPUT_DIR" # 检查脚本运行时是否带有参数（文件名） if [ "$#" -gt 0 ]; then # 如果参数数量大于0，则进入“单独处理模式” echo "--- 单独处理模式 ---" echo "准备处理 $# 个指定文件..." echo "" # 遍历所有传入的参数（也就是文件名） for file in "$@"; do # 检查一下文件是否存在，避免报错 if [ -f "$file" ]; then # 获取不带路径和扩展名的文件名 filename=$(basename -- "$file") name_no_ext="${filename%.*}" echo "正在处理: $filename ..." # 使用 ffmpeg 进行转换 (核心逻辑和原来一样) ffmpeg -i "$file" -vf "scale=$TARGET_WIDTH:-1" -q:v "$QUALITY" -y "$OUTPUT_DIR/$name_no_ext.webp" else # 如果文件不存在，给个提示 echo "警告: 文件 '$file' 不存在或不是一个文件，已跳过。" fi done else # 如果参数数量为0（即没有传入任何文件名），则进入原有的“批量模式” echo "--- 批量处理模式 (处理 '$INPUT_DIR' 文件夹) ---" echo "" # 查找所有图片文件并进行转换 (这里的代码和原来完全一样) find "$INPUT_DIR" -maxdepth 1 -iname "*.jpg" -o -iname "*.jpeg" -o -iname "*.png" -o -iname "*.bmp" -o -iname "*.tiff" | while read -r file; do # 获取不带路径和扩展名的文件名 filename=$(basename -- "$file") name_no_ext="${filename%.*}" echo "正在处理: $filename ..." # 使用 ffmpeg 进行转换 ffmpeg -i "$file" -vf "scale=$TARGET_WIDTH:-1" -q:v "$QUALITY" -y "$OUTPUT_DIR/$name_no_ext.webp" done fi echo "" echo "--- 所有图片处理完成！---"chmod +x convert.sh # 赋予执行权限批量重命名下载下来后图片名都是乱码难以分辨，可以用以下命令将文件夹种的所有图片命名为 1. WebP 2. WebP，方便后续增加图片分辨。$i = 1; Get-ChildItem | Where-Object { $_.PSIsContainer -eq $false } | ForEach-Object { Rename-Item -Path $_.FullName -NewName "$($i++)$($_.Extension)" }图片压缩GitHub - juzisang/picgo-plugin-compress: Image compression plugin for PicGo 这个好久没更新了，用不了 TinyPNG。然后我在 GitHub issue 区域找到了这个 GitHub - supine0703/picgo-plugin-compress-next: Image compression plugin for PicGo(\>=^2.3.0). Update, adapt and optimize. Better support and richer features，但是也有一年更新了，有个 bug，配置页面没有弹出配置 TinyPNG 的 API 选项。这个 bug 已经被人提交了，但作者应该好久没上线了。用不了就不用了，最后用了本地压缩。好处就是处理速度快不需要联网。图片 API因为我已经有图床了，随机调用图床图片的链接就行了。只需要将链接汇聚起来，做一个随机选择，重定向输出。同时还考虑到防盗链的问题（也许不需要）。综上考虑做一个 serverless 服务最好，就想到了 Cloudflare，赛博大善人，用上了它的 worker 服务。// --- 配置区 --- // 注意：末尾不要加斜杠 / const allowedReferer = "https://chifan.de"; // --- API 核心代码 --- export default { async fetch(request, env, ctx) { // 1. 获取请求头中的 'Referer' 信息 const referer = request.headers.get('Referer'); // 2. 防盗链逻辑判断 // (我们允许 referer 为空的情况，这样方便直接在浏览器地址栏测试) if (referer && !referer.startsWith(allowedReferer)) { // 返回 403 Forbidden 错误 return new Response(`Hotlinking not allowed. Access denied for referer: ${referer}`, { status: 403, statusText: 'Forbidden' }); } // 3. 如果通过了防盗链检查，就执行原来的随机图片逻辑 const imageUrls = [ // 在这里粘贴你的图片链接 // 例如: // "https://example.com/image1.jpg", // "https://example.com/image2.png" ]; // 从列表中随机选择一个图片链接 const randomIndex = Math.floor(Math.random() * imageUrls.length); const randomImageUrl = imageUrls[randomIndex]; // 如果图片列表为空或出现意外，返回一个提示 if (!randomImageUrl) { return new Response('Image URL list is empty or an error occurred.', { status: 500, statusText: 'Internal Server Error' }); } // 重定向到被选中的图片 return Response.redirect(randomImageUrl, 302); }, };
GUI一样是在 obisidian 里使用 telegram 图床，之前写过一篇配置教程，大差不差。就不赘述。cloudfare+telegram图床的使用 - chifan的blogsudo pacman -S wl-clipboard # 安装 Wayland 剪贴板工具yay -S picgo # 安装picgosudo pacman -S nodejs npm # 安装Node.js和npm，否则插件无法导入配置好后如果能手动添加图片上传，obisidian 使用 image auto upload 插件无法上传，那就是无法读取剪切板内的照片，要在软件设置里面，打开 调用内置剪切板 这个功能。由于用了 electron，后台内存占用达到了夸张的 800m，考虑使用下 CLI。CLIsudo npm install picgo -g # 安装picgo—cli picgo install web-uploader-byzh # 安装使用cf图床需要的插件picgo set uploader # 设置插件，选择web-uploader设置好了后，发现 obisidian 的插件 auto upload 无法调用，原因是 CLI 并不是一个服务，没有运行在本机的某个端口。如果只是单独使用 CLI 的话，需要我在终端输入 picgo upload，然后复制一串返回图片的 URL，在 obisidian 粘贴，最后修改成 markdown 格式，这太不优雅了。想到搞个脚本，绑定一个快捷键。当按下快捷键的时候，调用 picgo upload 这个命令上传剪切板的照片，然后通过管道命令得到 picgo upload 的包括 URL 的输出，然后将其转化为 markdown 格式，保存到剪切板。但还未结束，有时候因为网络问题，这个过程并不会马上完成。如果需要我一直点开剪切板看看有没有得到输出，或者一直按粘贴键还是不优雅。这需要一个反馈，过程已完成，然后我粘贴。或者是完成后自动帮我粘贴。一开始我是想让脚本自动帮我粘贴的，但是因为我是 Wayland，由于安全性考虑，Wayland不允许任何程序（wtype）以编程方式模拟键盘输入，这条路行不通。干脆让脚本运行结束的时候来一个通知吧，通知用到了 linotify 这个工具。sudo pacman -S libnotify # 安装linotify#!/bin/bash # 确保脚本能在正确的环境下找到所有命令 export PATH=/usr/bin:$PATH # 创建临时文件 TMP_FILE="/tmp/picgo-clipboard-upload-$$.png" wl-paste > "$TMP_FILE" # 检查文件是否创建成功 if [ -s "$TMP_FILE" ]; then # 运行 picgo upload 并提取最后一行（URL） URL=$(picgo upload "$TMP_FILE" | tail -n 1) EXIT_CODE=${PIPESTATUS[0]} rm "$TMP_FILE" # 检查是否成功 if [ $EXIT_CODE -eq 0 ] && "$URL" == http* ; then MARKDOWN_LINK="![]($URL)" echo -n "$MARKDOWN_LINK" | wl-copy # -u normal: 设置通知级别为“普通” # "PicGo 上传成功": 通知的标题 # "Markdown 链接已复制到剪贴板": 通知的内容 notify-send -u normal "PicGo 上传成功" "Markdown 链接已复制到剪贴板" # -------------------------------- else # --- 失败时也发送通知 --- notify-send -u critical "PicGo 上传失败" "未能从 PicGo 获取有效 URL" # ------------------------------ exit 1 fi else # 剪贴板没图片时也发个通知 notify-send -u low "PicGo 操作取消" "剪贴板中没有图片" exit 1 fi将 . sh 的绝对路径绑上一个快捷键 A。使用前先截图，然后使用快捷键 A 上传，通知出来（大概一秒钟），就可以粘贴了。虽然不比 image auto upload 这个插件优雅，回报是我不用用庞大的 GUI。而且 GUI 开机启动有一个图标弹出来，需要手动隐藏... 这个设计太蠢了。
我有两个硬盘，一个安装了 Windows，另一个是空硬盘，但里面有 efi 分区。没写到的基本都是照抄教程的和一些安装后的配置，就懒得写了。Linux 启动流程主板固件（UEFI）启动，并读取其内部存储（NVRAM）中的启动顺序列表。如果 ARCH 启动项位于第一位，UEFI 会根据该条目记录的物理地址，找到并执行 GRUB 的 EFI 文件。GRUB 启动后，读取其配置文件 /boot/grub/grub.cfg。配置文件告诉 GRUB 内核位于 /boot 目录，随后 GRUB 将内核加载到内存中。内核启动，系统开始运行。Arch Linux 目录结构概览/ ├── boot/ (启动目录) │ ├── efi/ <-- EFI 分区挂载点，存放 GRUB 和 Windows 的引导文件 │ ├── grub/ <-- GRUB 的配置文件 (grub.cfg) │ ├── initramfs-linux.img <-- 内核的内存镜像文件 │ └── vmlinuz-linux <-- Linux 内核本身 │ ├── etc/ (配置目录) -> 存放所有系统级软件的配置文件，如 pacman.conf, environment 等 │ ├── home/ (用户家目录) │ └── kkk/ <-- 普通用户 kkk 的家目录，所有个人文件和桌面设置都在这里 │ ├── root/ (root 用户的家目录) -> 与普通用户完全分开的专属目录 │ ├── usr/ (用户程序目录) -> 安装的绝大部分软件、库、文档都在这里，是系统最庞大的部分 │ ├── bin/ -> 用户可执行程序 │ └── lib/ -> 程序的库文件 │ ├── var/ (可变文件目录) -> 存放经常变化的文件，比如日志(log)、缓存(cache)等 │ ├── bin/ (二进制文件) -> 存放最基础的、系统启动时就需要用到的命令 (如 ls, cp) ├── sbin/ (系统二进制) -> 存放只有 root 才能使用的基础管理命令 ├── dev/ (设备文件) -> 将硬件设备（硬盘、鼠标、键盘）抽象成文件，供系统读写 ├── lib/ (库文件) -> 存放最基础的、系统启动就需要用到的库 ├── mnt/ (挂载点) -> 临时挂载其他设备的目录 └── tmp/ (临时目录) -> 存放临时文件，重启后通常会清空第一部分：安装前准备1. Windows 环境准备下载镜像：从官网下载最新的 Arch Linux 镜像。archlinux.org/download/制作启动盘：推荐：使用 Ventoy 制作，一个 U 盘可以放入多个启动镜像，非常方便。备选：使用 balenaEtcher 将镜像烧录到 U 盘。准备硬盘：在 Windows 的磁盘管理中，删除目标硬盘上的所有分区，仅保留 EFI 系统分区（这个分区将与 Arch Linux 共享）。2. BIOS 设置设置启动项：重启电脑进入 BIOS，在 Boot 页面将 U 盘（如 USB_EFI）设置为第一启动项。关闭安全启动：务必关闭 Secure Boot 选项。第二部分：在 Arch Live 环境中进行安装这一步是将 Arch Linux 临时加载到内存中，以便我们对硬盘进行分区、格式化和安装核心系统。1. 检查启动模式确认系统是以 UEFI 模式启动的。如果以下命令成功执行且没有报错，则说明是 UEFI 模式。ls /sys/firmware/efi/efivars2. 连接网络使用 iwd 工具连接到 Wi-Fi：# 1. 进入 iwd 交互工具 iwctl # 2. 查看网卡设备名 (通常是 wlan0) [iwd]# device list # 3. 扫描 Wi-Fi 网络 [iwd]# station wlan0 scan # 4. 列出扫描到的网络 [iwd]# station wlan0 get-networks # 5. 连接到你的 Wi-Fi (将 SSID 替换为你的 Wi-Fi 名称) [iwd]# station wlan0 connect "SSID" # 6. 退出 iwd [iwd]# exit # 7. 测试网络连通性 ping www.baidu.com3. 更新系统时钟timedatectl set-ntp true4. 硬盘分区首先，使用 lsblk 确认目标硬盘的名称（例如 /dev/nvme0n1）。lsblk使用 cfdisk 工具进行分区，请务必选择正确的硬盘！cfdisk /dev/nvme0n1在 cfdisk 界面中操作：删除旧分区：使用方向键 ↑ ↓ 选中目标硬盘上已有的分区（除了 EFI 分区），然后在下方菜单选择 Delete 并回车，直到它们合并成一块 Free space。创建 Swap 分区：选中 Free space，在菜单中选择 New 回车。输入分区大小，建议不小于内存的 60%（例如 8G）。创建后，默认类型为 Linux filesystem。在菜单中选择 Type，然后找到并选择 Linux swap。创建根 (/) 分区：选中剩下的 Free space，选择 New 回车。直接回车，使用所有剩余空间。分区类型保持默认的 Linux filesystem 即可。写入分区表：检查分区表，确认有一个 Linux swap 分区和一个大的 Linux filesystem 分区。确认无误后，在菜单中选择 Write，输入 yes 并回车。选择 Quit 退出。5. 格式化并挂载分区再次使用 lsblk 确认各个分区的确切名称（例如 swap 是 p4，根是 p5）。格式化分区：格式化 Swap 分区：mkswap /dev/nvme0n1p4格式化根分区为 ext 4：mkfs.ext4 /dev/nvme0n1p5激活并挂载分区：激活 Swap：swapon /dev/nvme0n1p4挂载根 (/) 分区到 /mnt：mount /dev/nvme0n1p5 /mnt挂载 EFI 分区到 /mnt/boot（假设你的 EFI 分区是 /dev/nvme0n1p2）：mkdir /mnt/boot mount /dev/nvme0n1p2 /mnt/boot检查挂载结果：运行 lsblk，应看到 nvme0n1p5 挂载在 /mnt，nvme0n1p2 挂载在 /mnt/boot。6. 安装 Arch 核心系统更换镜像源：为了提高下载速度，编辑镜像源列表，将国内镜像源置顶。nano /etc/pacman.d/mirrorlist在文件最上方添加中科大的镜像源：Server = https://mirrors.ustc.edu.cn/archlinux/$repo/os/$arch安装基础包：使用 pacstrap 将核心系统安装到 /mnt。pacstrap /mnt base linux linux-firmware vim nano第三部分：配置新系统1. 进入新系统 (chroot)arch-chroot /mnt2. 配置时区和语言设置时区 (上海)：ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime同步硬件时钟：hwclock --systohc设置语言：编辑 locale.gen 文件：nano /etc/locale.gen找到并取消以下两行的注释（删除前面的 #）：en_US.UTF-8 UTF-8 zh_CN.UTF-8 UTF-8生成 locale 信息：locale-gen设置默认语言为英文（避免 TTY 乱码）：echo "LANG=en_US.UTF-8" > /etc/locale.conf3. 配置网络和主机设置主机名 (将 your-hostname 替换为你想要的名字)：echo "your-hostname" > /etc/hostname配置 hosts 文件：nano /etc/hosts在文件末尾添加以下内容（同样，替换 your-hostname）：127.0.0.1 localhost ::1 localhost 127.0.1.1 your-hostname.localdomain your-hostname4. 设置 Root 密码passwd第四部分：安装和配置 GRUB 引导1. 安装必要软件包os-prober 用于扫描并识别硬盘上已有的其他操作系统（如 Windows）。pacman -S grub efibootmgr os-prober2. 部署 GRUB将 GRUB 引导程序安装到 EFI 分区。grub-install --target=x86_64-efi --efi-directory=/boot --bootloader-id=ARCH--target=x86_64-efi: 指定为 64 位 UEFI 系统。--efi-directory=/boot: 告诉 GRUB，EFI 分区被挂载在了 /boot 目录。--bootloader-id=ARCH: 在 UEFI 启动菜单里创建一个名为 "ARCH" 的启动项。3. 生成 GRUB 配置文件启用 Windows 识别：编辑 GRUB 默认配置文件。nano /etc/default/grub找到 #GRUB_DISABLE_OS_PROBER=false 这一行，删除前面的 #。生成最终配置：grub-mkconfig -o /boot/grub/grub.cfg如果一切顺利，你应该能看到类似 Found Windows Boot Manager on ... 的输出信息。第五部分：安装后配置字体配置安装中文字体（思源黑体）：sudo pacman -S noto-fonts-cjk更新字体缓存：fc-cache -fv创建字体配置文件：在 ~/.config/fontconfig/ 目录下创建一个 fonts.conf 文件，优化字体渲染顺序，解决浏览器等应用字体显示问题。<?xml version="1.0"?> <fontconfig> <alias> <family>sans-serif</family> <prefer> <family>Noto Sans</family> <family>Noto Sans CJK SC</family> <family>Noto Sans CJK TC</family> <family>Noto Color Emoji</family> </prefer> </alias> <alias> <family>monospace</family> <prefer> <family>Fira Code</family> <family>JetBrains Mono</family> <family>Noto Sans Mono CJK SC</family> <family>Noto Color Emoji</family> </prefer> </alias> <match target="font"> <edit name="antialias" mode="assign"> <bool>true</bool> </edit> <edit name="hinting" mode="assign"> <bool>true</bool> </edit> <edit name="hintstyle" mode="assign"> <const>hintslight</const> </edit> <edit name="rgba" mode="assign"> <const>rgb</const> </edit> </match> </fontconfig>终端配置由于 Oh My Zsh 太过“大”，目前并未使用到其中过多的插件，就没有选择使用了。完全照着这个文档配置了：ShorinArchExperience Guide使用体验NVIDIA 独显：有一些问题，混合模式下桌面锁死 60 Hz 刷新率。浏览器：google-chrome 使用极其糟糕，无法调用独显，无法硬解视频。转到 firefox 后问题迎刃而解，发现 Firefox 除了插件生态稍弱一点，其他方面都很好用。窗口管理：自动平铺（Tiling）体验很好，比 Windows 自带的分屏功能强大。多个工作区也避免了桌面混乱。效率：配合快捷键，工作效率提高了很多。遇到的问题与解决方案问题 1：grub-install 报错 failed to make directory /boot/grub/locale原因分析：EFI 分区过小（仅 100 MB），而我错误地将整个 /boot 目录（包含内核文件）都放在了 EFI 分区中，导致空间被占满，GRUB 无法写入自己的文件。解决方案：（失败的尝试）尝试删除 Linux 内核文件，但没有成功。意识到 EFI 分区可能被 Windows 文件占满，于是删除了 Windows 的字体文件，腾出了约 4 MB 空间。正确做法：将 Linux 的 /boot 目录从 EFI 分区移回根分区下，然后仅将 EFI 分区挂载到 /boot/efi（或 /boot）。这样，只有 EFI 引导文件（如 GRUB 的 efi 文件）会存放在 EFI 分区，而内核等大文件则存放在根分区下的 /boot 目录里，解决了空间不足的问题。问题 2：重启后直接进入 Windows，没有 GRUB 菜单原因分析：主板固件 (UEFI) 的 NVRAM 启动顺序中，Windows Boot Manager 的优先级高于新安装的 ARCH。解决方案：进入 BIOS/UEFI 设置界面，在 Boot Priorities 菜单中，将 ARCH 的启动顺序手动提升至第一位，保存并退出。问题 3：GRUB 界面有 Windows，但没有 Arch Linux 选项原因分析：由于之前对 /boot 目录的错误操作，导致根分区下缺少了 Linux 内核文件 (vmlinuz-linux)。因此在 chroot 环境里运行 grub-mkconfig 时，它找不到可引导的 Linux 系统，无法为其创建菜单项。解决方案：使用 Arch 安装 U 盘启动，挂载好分区后 arch-chroot 进入已安装的系统。重新安装 Linux 内核，以在正确的位置生成内核文件。pacman -S linux最后重新生成 GRUB 配置文件。grub-mkconfig -o /boot/grub/grub.cfg这次成功找到了内核并生成了完整的启动菜单。参考Arch Linux Wiki (中文)Archlinux-Gnome-FullGuide-ShorinArchExperiencearchlinux 简明指南
添加 acls 规则进入后台的 ACL 页面，添加一条规则，明确允许 VPS 访问 NAS 的 SMB 服务端口 (445)。// 规则: 允许 VPS 访问 NAS 的 SMB 445 端口 { "action": "accept", "src": ["tag:vps"], "dst": ["tag:nas:445"] },Vps 上挂载 nas 共享文件夹此步骤的目的是让 VPS 可以像读写本地文件夹一样操作 NAS 上的共享目录。安装 SMB/CIFS 工具 (在 VPS 上执行):sudo apt update sudo apt install cifs-utils创建本地挂载点 (在 VPS 上执行):sudo mkdir -p /mnt/nas_backup创建凭证文件 (在 VPS 上执行，推荐): 为了安全，我们将 NAS 的用户名和密码存放在一个受保护的文件中。# 创建并编辑文件 sudo nano /etc/nas-credentials # 在文件中写入以下内容并保存 # username=您NAS的用户名 # password=您NAS的密码 # 锁定文件权限，确保只有 root 能读取 sudo chmod 600 /etc/nas-credentials**执行挂载 (在 VPS 上执行):通过 tailscale status 命令获取您 NAS 的 Tailscale IP (例如 100.x.x.x)。确认您 NAS 上的共享文件夹名称 (例如 vps_ryzen)。sudo mount -t cifs //100.x.x.x/vps_ryzen /mnt/nas_backup -o credentials=/etc/nas-credentials验证挂载: 运行 df -h，如果看到 /mnt/nas_backup 的条目，说明挂载成功。部署备份脚本这是执行备份任务的核心。最终备份脚本 (backup_to_nas.sh):#!/bin/bash # ================================================================= # Docker 数据卷与指定文件夹备份脚本 - 备份至 NAS (全功能版) # # 功能: # 1. 为每一次备份任务创建一个带时间戳的独立文件夹。 # 2. 同时支持备份 Docker 数据卷和服务器上的任意文件夹。 # 3. 将所有备份文件 (.tar.gz) 存入该次任务的独立文件夹中。 # 4. 自动清理指定天数前的旧备份文件夹。 # 5. 提供详细的日志输出和错误检查。 # ================================================================= # --- 可配置部分 --- # 1. 备份文件存放的根目录 (请确保这是您挂载的 NAS 目录) BACKUP_ROOT_DIR="/mnt/nas_backup" # 2. 需要备份的 Docker 卷名称列表 (用空格隔开) # 留空则跳过: VOLUMES_TO_BACKUP="" VOLUMES_TO_BACKUP="typecho_mariadb_data typecho_caddy_data" # 3. 【新增】需要备份的文件夹绝对路径列表 (用空格隔开) # - 请确保路径是绝对路径 (以 / 开头)。 # - 留空则跳过: DIRS_TO_BACKUP="" # - 示例: DIRS_TO_BACKUP="/etc/nginx /var/www/my_website" DIRS_TO_BACKUP="/root/typecho" # 4. 备份文件夹保留天数 (例如，保留最近7天的备份) RETENTION_DAYS=7 # --- 脚本核心逻辑 (一般无需修改) --- # 设置时区 export TZ='Asia/Shanghai' # 本次备份任务的唯一时间戳 DATE=$(date +%Y%m%d_%H%M%S) # 为本次备份创建一个独立的、带时间戳的子目录 CURRENT_BACKUP_DIR="${BACKUP_ROOT_DIR}/${DATE}" echo "=====================================" echo "备份任务开始于: $(date)" echo "=====================================" echo "本次所有备份文件将保存至: ${CURRENT_BACKUP_DIR}" # 确保本次备份的独立目录存在 mkdir -p ${CURRENT_BACKUP_DIR} # --- 1. 备份 Docker 数据卷 --- if [ -n "${VOLUMES_TO_BACKUP}" ]; then echo "" echo "--- 开始处理 Docker 数据卷 ---" for VOLUME in ${VOLUMES_TO_BACKUP}; do echo "-------------------------------------" echo ">> 正在处理卷: ${VOLUME}" if ! docker volume inspect ${VOLUME} > /dev/null 2>&1; then echo " [错误] 卷 '${VOLUME}' 不存在，已跳过。" continue fi BACKUP_FILENAME="${VOLUME}.tar.gz" BACKUP_FULL_PATH="${CURRENT_BACKUP_DIR}/${BACKUP_FILENAME}" echo " 备份文件将保存为: ${BACKUP_FULL_PATH}" docker run --rm \ -v "${VOLUME}:/source_data:ro" \ -v "${CURRENT_BACKUP_DIR}:/backup_target" \ alpine \ tar -czf "/backup_target/${BACKUP_FILENAME}" -C /source_data . if [ $? -eq 0 ]; then echo " [成功] 卷 '${VOLUME}' 已成功备份。" else echo " [错误] 备份卷 '${VOLUME}' 失败！" fi done else echo "未配置 Docker 数据卷备份，跳过此步骤。" fi # --- 2. 【新增】备份指定文件夹 --- if [ -n "${DIRS_TO_BACKUP}" ]; then echo "" echo "--- 开始处理指定文件夹 ---" for DIR_PATH in ${DIRS_TO_BACKUP}; do echo "-------------------------------------" echo ">> 正在处理文件夹: ${DIR_PATH}" # 检查文件夹是否存在且可读 if [ ! -d "${DIR_PATH}" ]; then echo " [错误] 文件夹 '${DIR_PATH}' 不存在，已跳过。" continue fi if [ ! -r "${DIR_PATH}" ]; then echo " [错误] 文件夹 '${DIR_PATH}' 没有读取权限，已跳过。" continue fi # 从完整路径中提取基本名称作为文件名 (例如 /etc/nginx -> nginx) # 并替换路径中的斜杠'/'为下划线'_'，以创建更唯一的文件名 (例如 /home/user/app -> home_user_app) DIR_BASENAME=$(echo "${DIR_PATH}" | sed 's|^/||; s|/$||; s|/|_|g') BACKUP_FILENAME="${DIR_BASENAME}.tar.gz" BACKUP_FULL_PATH="${CURRENT_BACKUP_DIR}/${BACKUP_FILENAME}" echo " 备份文件将保存为: ${BACKUP_FULL_PATH}" # 使用 tar 命令直接打包文件夹 # -C 选项可以在打包前切换到父目录，从而避免在压缩包中包含完整的绝对路径 # 例如，打包 /var/www/html，我们切换到 /var/www 然后打包 html 文件夹 PARENT_DIR=$(dirname "${DIR_PATH}") TARGET_DIR=$(basename "${DIR_PATH}") tar -czf "${BACKUP_FULL_PATH}" -C "${PARENT_DIR}" "${TARGET_DIR}" if [ $? -eq 0 ]; then echo " [成功] 文件夹 '${DIR_PATH}' 已成功备份。" else echo " [错误] 备份文件夹 '${DIR_PATH}' 失败！" fi done else echo "未配置文件夹备份，跳过此步骤。" fi # --- 3. 清理旧备份 --- echo "" echo "-------------------------------------" echo ">> 开始清理旧的备份 (保留最近 ${RETENTION_DAYS} 天的备份文件夹)..." # 查找并删除整个旧的备份文件夹 find "${BACKUP_ROOT_DIR}" -mindepth 1 -maxdepth 1 -type d -mtime +${RETENTION_DAYS} -print -exec rm -rf {} + echo " 旧备份清理完毕。" echo "" echo "所有备份任务完成于: $(date)" echo "====================================="部署操作:将上述代码保存到 VPS 的 /root/backup_to_nas.sh 文件中。根据您自己的情况，修改 BACKUP_DIR 和 VOLUMES_TO_BACKUP 变量。授予执行权限：chmod +x /root/backup_to_nas.sh。手动测试：运行 /root/backup_to_nas.sh，并去 NAS 上检查是否生成了备份文件。设置定时任务 (Cron)编辑 Crontab:crontab -e添加任务: 在文件末尾添加以下一行，设置每天凌晨2点执行备份。0 2 * * * /root/backup_to_nas.sh > /var/log/docker_backup.log 2>&1保存并退出。系统会自动加载新任务。在配置过程中，遇到并解决了一系列典型问题，记录如下：问题： 运行脚本时报错 $: \r: command not found。原因： 脚本文件是在 Windows 系统下编辑后上传到 Linux 的，包含了 Windows 风格的换行符 (\r\n)。解决方案： 在 VPS 上使用 dos2unix 或 sed 命令转换文件格式。# 方法一 (推荐) dos2unix /root/backup_to_nas.sh # 方法二 (通用) sed -i 's/\r$//' /root/backup_to_nas.sh问题： 脚本提示 [错误] 卷 'mariadb_data' 不存在。原因： 使用 docker-compose 时，它会自动为卷名加上项目名（即文件夹名）作为前缀。例如，项目文件夹叫 typecho，卷名叫 mariadb_data，那么实际的卷名是 typecho_mariadb_data。解决方案： 运行 docker volume ls 命令查看确切的卷名，并更新到脚本的 VOLUMES_TO_BACKUP 变量中。问题： 挂载 SMB 共享时报错 mount error(115): Operation now in progress。原因： 连接超时。这通常是由于防火墙阻止了连接。在本次实践中，是 Tailscale 的 ACL 策略默认禁止了设备间的端口访问。解决方案： 登录 Tailscale 后台，修改 ACL 规则，明确添上一条允许 VPS (tag:vps) 访问 NAS (tag:nas) 的 445 端口的规则。问题： 备份成功，但在 NAS 上看不到文件。原因： 脚本中的 BACKUP_DIR 路径填写错误。填写的是 NAS 上的路径 (/mnt/Storage1/vps_ryzen)，但脚本是在 VPS 上运行，它应该写入到 VPS 上的挂载点 (/mnt/nas_backup)。解决方案： 将脚本中的 BACKUP_DIR 修改为 VPS 上的正确挂载点路径。
一、需要的容器Radarr: 电影管理程序。负责维护电影列表、搜索缺失的资源、下达下载指令以及整理已完成的文件。Prowlarr: 索引器管理程序。集中配置并向 Radarr 等应用提供所有索引器的搜索接口。qBittorrent: BitTorrent 客户端。负责执行具体的下载任务。FlareSolverr: Cloudflare 解决方案。作为一个中间服务，用于绕过网站的 Cloudflare 防护，使其他应用能正常访问。Jellyfin / Plex: 媒体服务器程序。负责扫描媒体库、刮削元数据（海报、简介等），并提供跨设备的播放界面。数据交互流程: Radarr -> Prowlarr -> [FlareSolverr] -> qBittorrent -> Radarr (整理) -> Jellyfin (刮削与呈现)二、自动化系统的价值质量升级: 自动监控并下载更高质量的资源来替换旧版本。文件整理: 自动完成重命名和归档，保持库结构统一。规模化管理: 无需人工干预即可高效管理大量媒体资源。三、核心技术概念PUID / PGID默认状态：Docker 容器内的程序默认以 root 用户（ID 为 0）运行。引发冲突：当这个以 root 身份运行的容器在您的硬盘上创建文件时（通过卷映射），这些文件的所有者在宿主机上也是 root。如果涉及到卷映射的一般可以设置 PUID 和 PGID 为 1000（普通用户权限），避免任何可能破坏容器环境的“越权”行为。文件权限 (File Permissions)问题：当容器日志报告对某个目录“不可写 (not writable)”或“权限被拒绝 (Permission Denied)”时，问题根源在宿主机的文件系统。解决方案：在宿主机终端，对相应目录执行 chown 和 chmod 命令，以修正目录的所有权和读写权限。sudo chown -R 1000:1000 /path/to/directorysudo chmod -R 775 /path/to/directory三、组件设置照着以下视频操作：用四款套件搭建NAS观影全自动化,实现真正的NAS观影自由教程\_哔哩哔哩\_bilibili四、故障排查流程当在 Prowlarr 中添加索引器失败或测试超时，应按以下顺序进行检查。诊断网络状态使用 itdog.cn 等第三方网络检测工具，测试目标索引器网站的域名。此步骤用于判断问题是网站本身服务中断，还是由本地网络到目标服务器之间的连接被阻断。解决网络访问问题网络阻断：若网站本身可用但无法直连，则必须使用代理。在 Prowlarr 添加索引器的设置窗口中，找到“代理(Proxy)”选项并填入代理服务器信息。Cloudflare 阻断：若错误信息明确为 Blocked by Cloudflare，则需部署 FlareSolverr 容器，并在 Prowlarr 的设置中配置 FlareSolverr 的服务地址 (http://<主机IP>:8191)。解决请求超时问题当代理和 FlareSolverr 均已配置但请求依然超时，按以下次序检查：a) 延长应用超时：在 Prowlarr 的 设置 -> 通用 中，增大 索引器超时 (Indexer Timeout) 的秒数（如 120）。b) 为 FlareSolverr 配置代理：FlareSolverr 访问目标网站同样需要通过代理。在 FlareSolverr 容器的环境变量中，必须设置 HTTP_PROXY 和 HTTPS_PROXY。c) 验证代理节点：在代理客户端中，切换并测试不同代理节点的实际可用性和速度。五、系统高级配置下载文件大小控制在 Radarr 的 设置 -> 配置文件 中，可以创建或编辑质量配置文件。选择质量等级：仅勾选所需的分辨率和编码类型（如 WEBDL-1080p）。设置文件大小：点击质量等级旁边的齿轮图标，可以设定该质量等级可接受的最小和最大文件大小（GB），Radarr 将仅下载符合此范围的资源。后面发现下使用的硬盘大小是预估的两倍排查出以下解决办法：Radarr 的 设置 - 媒体管理 - 导入中，开启使用硬链接代替复制。软链接与硬链接 检查默认 Radarr 是打开的话，那基本可以确定是文件权限不匹配的问题：ls -ln 查看输出，一般是因为 radarr 以用户 1000 运行，但是文件夹权限是 root，写入被拒绝。使用 sudo chown -R 1000:1000 /mnt/Storage1/Media 将文件夹权限交给用户。修改前 drwxr-xr-x 4 0 0 4096 Aug 1 10:06 Media。意味 4 个文件夹，UID 和 GID 都是 0。修改后 drwxr-xr-x 4 1000 1000 4.0K Aug 1 10:06 Media。# 春节观影必备！手把手教你，如何打造全自动化搜索下载的影音库GitHub - XIU2/TrackersListCollection: 🎈 Updated daily! A list of popular BitTorrent Trackers! / 每天更新！全网热门 BT Tracker 列表！# 为什么国内 BT 环境如此恶劣？下载速度如此糟糕？我总结了六点原因...
ocet刷armbian本笔记记录了 OCET 设备刷入 Armbian 系统、配置 CasaOS、硬盘挂载、Docker 目录迁移、网络代理设置、二次刷机以及系统优化等步骤。Armbian 系统自带的两个重要配置命令：armbian-config # 系统设置工具，用于配置网络、用户、软件等 armbian-software # 软件管理工具，用于安装和管理软件包1. 原系统刷机请参考以下文章进行刷机操作：post.smzdm.com/p/agwx06lm/固件下载地址：GitHub - ophub/amlogic-s9xxx-armbian: Support for Armbian in Amlogic, Rockchip and Allwinner boxes. Support a311d, s922x, s905x3, s905x2, s912, s905d, s905x, s905w, s905, s905l, rk3588, rk3568, rk3399, rk3328, h6, etc.下载文件名为 Armbian_25.08.0_rockchip_wxy-oect 的固件。2. 设置静态 IP通过 armbian-config 工具设置静态 IP：在终端输入 armbian-config。选择 network（网络）。选择 bns 001- basic network setup（基本网络设置）。选择 eth0 网口（通常是第一个有线网口），然后回车确认。选择 static set ip manually（手动设置静态 IP）。首先会弹出设置 MAC 地址的选项，直接回车保持不变。然后输入你想要设置的静态 IP 地址，删除掉原来的默认输入。重要： 务必输入正确的网关地址，然后一直回车，后面的设置通常保持默认即可。返回到主页面，一直返回退出 armbian-config。建议： 最好不要直接在 Armbian 系统内设置静态 IP。我设置后曾遇到 ping 百度失败的问题，原因不明。更推荐的做法是，将光猫改为桥接模式后，在路由器后台为 OCET 设备设置静态 IP，这样风险更低，操作也更方便。3. 安装 CasaOS执行以下命令安装 CasaOS：curl -fsSL https://get.casaos.io | sudo bash4. 添加第三方应用商店源进入 CasaOS 界面，点击“应用商店”——“更多”，然后将以下链接粘贴进去：https://play.cuse.eu.org/Cp0204-AppStore-Play.zip5. 挂载硬盘查看硬盘挂载位置并记录 UUID：lsblk # 列出所有块设备，查看硬盘分区信息获取指定分区的 UUID：sudo blkid /dev/sda1 # 假设 /dev/sda1 是你的目标分区，获取其唯一标识符 UUID编辑 /etc/fstab 文件以实现开机自动挂载：将以下内容添加到 /etc/fstab 文件中，请将 UUID 修改为你的目标硬盘的实际 UUID。UUID=b89f4261-e017-49fe-85f0-04b441da17b7 /mnt/Storage1 ext4 defaults,noatime,nodiratime 0 2卸载临时挂载（如果之前手动挂载过）：sudo umount /mnt/Storage1重新加载所有 fstab 中定义的挂载点：sudo mount -a注意： 如果有程序正在占用硬盘，可能需要 kill 掉相关进程。如果仍然遇到问题，可以尝试 cd ~ 返回主目录，或者直接重启系统。加载 systemd 配置：sudo systemctl daemon-reload6. 更改 Docker 挂载目录此操作旨在将 Docker 的数据目录从默认位置（通常是 /var/lib/docker）迁移到挂载的硬盘上，以节省系统盘空间。在进行此操作前，建议参考 Bilibili 上的教程：只要70元轻nas——矿渣oec刷casaos保姆级教程\_哔哩哔哩\_bilibili。6.1 暂停 CasaOS 服务systemctl stop casaos*.service # 暂停所有CasaOS相关服务 systemctl status casaos.service # 查看CasaOS服务状态，确认已停止按 CTRL+C 退出状态查看命令。6.2 暂停 Docker 服务systemctl stop docker.service # 暂停Docker守护进程 systemctl status docker.service # 查看Docker服务状态，确认已停止按 CTRL+C 退出状态查看命令。6.3 创建新的镜像和卷目录在目标挂载点上创建 Docker 数据目录：mkdir -p /mnt/Storage1/dockerdata编辑 Docker 服务配置文件以指定新的数据根目录：nano /lib/systemd/system/docker.service找到 ExecStart 行，将其从：ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock修改为（添加 --data-root 参数）：ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock --data-root /mnt/Storage1/dockerdata6.4 复制原有 Docker 数据到新路径将 /var/lib/docker 下的所有数据复制到新创建的目录：rsync -avxP /var/lib/docker/ /mnt/Storage1/dockerdata6.5 重启服务或系统加载 systemd 配置并启动 Docker 和 CasaOS 服务：systemctl daemon-reload systemctl start docker.service systemctl start casaos.service或者，直接重启系统以确保所有更改生效：reboot6.6 验证 Docker 数据目录重启后，验证 Docker 的数据根目录是否已更改为新路径：docker info | grep "Docker Root Dir"如果成功，将显示类似 Docker Root Dir: /mnt/Storage1/dockerdata 的结果。6.7 遇到的问题及解决方案问题： 打开 CasaOS 提示安装失败，并显示类似下图的错误。原因： 这通常是由于父目录权限问题。rsync -a 命令会保留原始文件的权限，确保 /mnt/Storage1/dockerdata/containers 目录权限正确。但新目录 /mnt/Storage1/dockerdata 本身的权限，以及外接硬盘文件系统的类型，可能会导致 Docker 在进行某些特定操作（如下载镜像层到 /tmp 目录）时权限不足。解决方案： 调整新 Docker 数据目录的权限和所有者，然后重启。sudo chmod -R 755 /mnt/Storage1/dockerdata # 赋予目录及其内容读写执行权限 sudo chown -R root:root /mnt/Storage1/dockerdata # 将目录及其内容的所有者设为root sudo reboot # 重启系统7. 换源为了避免网络问题和提高下载速度，建议更换 Linux 和 Docker 的软件源。手动逐个设置容易出错，且可能导致网络配置混乱（我曾因此重装系统）。推荐使用现成的脚本。7.1 Linux 换源执行以下命令一键更换 Linux 系统的软件源：bash <(curl -sSL https://linuxmirrors.cn/main.sh)7.2 Docker 换源执行以下命令一键更换 Docker 的软件源：bash <(curl -sSL https://linuxmirrors.cn/docker.sh)提示： 如果你安装了 CasaOS 的第三方应用商店源，可以尝试安装 dkturbo 这个 Docker 应用。它能自动检测并更换 Docker 源，并在还原后自动暂停。参考：GitHub - Cp0204/CasaOS-AppStore-Play: A Docker Compose Hub, Making Docker Your Productivity Tool - 一个 Docker Compose 仓库，让 Docker 成为你的生产力工具8. 代理设置在国内主机上 git clone 或下载一些被墙的网站文件时，可能需要设置代理。8.1 临时代理（当前终端会话有效）在当前终端会话中设置 HTTP/HTTPS 代理：export https_proxy=http://127.0.0.1:7890 # 在当前终端启动HTTPS代理 export http_proxy=http://127.0.0.1:7890 # 在当前终端启动HTTP代理注意： 关闭当前终端或重启系统后，代理设置将失效。8.2 永久系统代理编辑 /etc/profile 文件，使其在每次用户登录时自动设置代理：vim /etc/profile在文件最下方添加以下两行代码：export http_proxy=http://127.0.0.1:7890 export https_proxy=http://127.0.0.1:7890保存文件后，重启系统使设置生效。8.3 Docker 代理设置系统环境的代理设置不会影响 Docker 流量，因为 Docker 容器有独立的网络环境。以下是为 Docker 设置代理的方法：8.3.1 配置 Docker 服务（全局代理）这种方法会使整个 Docker 守护进程通过代理访问网络。创建 Docker 服务配置目录：sudo mkdir -p /etc/systemd/system/docker.service.d创建并编辑代理配置文件：sudo nano /etc/systemd/system/docker.service.d/http-proxy.conf粘贴以下内容（请将 <宿主机IP> 替换为实际的宿主机 IP 地址）：[Service] Environment="HTTP_PROXY=http://<宿主机IP>:7890" Environment="HTTPS_PROXY=http://<宿主机IP>:7890" Environment="NO_PROXY=localhost,127.0.0.1,*.example.com" # 配置不走代理的地址重新加载 systemd 配置并重启 Docker 服务：sudo systemctl daemon-reload sudo systemctl restart docker提示： 如果你只想在拉取镜像时临时使用代理，可以在拉取完成后删除此配置文件：sudo rm /etc/systemd/system/docker.service.d/http-proxy.conf sudo systemctl daemon-reload sudo systemctl restart docker更优雅的办法：通过 Docker 客户端配置代理编辑或创建 ~/.docker/config.json 文件：vim ~/.docker/config.json添加以下内容（请将 <宿主机内网IP> 替换为实际的宿主机内网 IP 地址）：{ "proxies": { "default": { "httpProxy": "http://<宿主机内网IP>:7890", "httpsProxy": "http://<宿主机内网IP>:7890", "noProxy": "localhost,127.0.0.1" } } }当不需要拉取镜像时，可以将 config.json 文件改名（例如 config.json.bak）来禁用代理。8.3.2 为指定的容器配置代理如果你只想让某个特定的 Docker 容器走代理，可以在启动容器时通过环境变量设置：使用 docker run 命令：docker run -e http_proxy=http://<宿主机IP>:7890 -e https_proxy=http://<宿主机IP>:7890 your-image-name使用 docker-compose.yml 文件：version: '3' services: myservice: image: your-image environment: - http_proxy=http://<宿主机IP>:7890 - https_proxy=http://<宿主机IP>:7890 - NO_PROXY=localhost,127.0.0.1,192.168.0.0/16,10.0.0.0/8,172.16.0.0/12 # 避免内网访问时走代理9. 刷机后刷其他系统（二次刷机）如果你想在 Armbian 系统之后刷入其他系统，可以使用瑞芯微（Rockchip）刷写工具。安装瑞芯微驱动： 确保你的电脑已安装瑞芯微设备的驱动。打开 RK 刷写工具。连接设备进入刷机模式：用卡针按住 OCET 设备的 Reset 键，然后 用手机数据线 Type-A 接口连接电脑，Type-C 接口连接图片下方所示的 C 口（非 USB 3.0 接口），此时无需连接电源。注意： 之前我曾尝试用双公头线连接 OCET 的 USB 3.0 接口，指示灯不亮，排查了很久。请务必连接正确的 Type-C 接口。刷写新系统：连接成功后，RK 刷写工具会显示“发现一个 Loader 设备”。取消勾选第一个 Loader 分区。点击第二个 System 分区旁边的三个点 ...，选择你想要刷入的其他系统镜像文件。点击“执行”开始刷写。10. 测速10.1 局域网传输速度测试（也适用于 Tailscale 内网穿透速度）使用 iperf3 工具测试局域网或内网穿透的传输速度。在 NAS（服务端）上操作：安装 iperf3：sudo apt-get install iperf3 -y启动 iperf3 服务端：iperf3 -s # 启动iperf3，默认端口是5201。请确保NAS防火墙已开启5201端口。在电脑或 VPS（客户端）上操作：下载并安装 iperf3。打开命令行工具（如 CMD）。进入 iperf3 解压后的文件夹。执行测试命令（请将 192.168.1.1 替换为你的 NAS 的实际 IP 地址）：.\iperf3.exe -c 192.168.1.1 # Windows客户端 iperf3 -c 192.168.1.1 # Linux/macOS客户端高级测试选项：使用多线程测试（例如 8 个线程）：iperf3 -c 192.168.200.108 -P 8 # 在客户端运行，测试从客户端到服务端的上传速度测试从服务端到客户端的速度（下载速度）：iperf3 -c 192.168.200.108 -P 8 -R # 在客户端运行，测试从服务端到客户端的下载速度11. 关闭 LED 灯为了减少光污染或节省微弱的功耗，可以创建一个脚本来关闭 OCET 设备的 LED 指示灯。11.1 创建关灯脚本创建脚本文件：sudo nano /usr/local/bin/led-off.sh粘贴以下内容到文件中：#!/bin/bash # 关闭所有 LED echo 0 | sudo tee /sys/class/leds/blue:/brightness /sys/class/leds/green:/brightness /sys/class/leds/red:/brightness /sys/class/leds/mmc0::/brightness >/dev/null赋予脚本执行权限：sudo chmod +x /usr/local/bin/led-off.sh11.2 创建 systemd 服务实现开机自启动创建 systemd 服务文件：sudo nano /etc/systemd/system/led-off.service粘贴以下内容到文件中：[Unit] Description=Turn off all LEDs after system boot After=multi-user.target # 确保在系统完全启动后执行 [Service] Type=oneshot ExecStart=/usr/local/bin/led-off.sh [Install] WantedBy=multi-user.target重新加载 systemd 配置：sudo systemctl daemon-reload设置服务开机自启动：sudo systemctl enable led-off.service立即启动服务以关闭当前 LED 灯：sudo systemctl start led-off.service参考资料莫老师的附件表不到100块拥有全能NAS，保姆级低功耗家庭服务器搭建指南\_哔哩哔哩\_bilibilipost.smzdm.com/p/agwx06lm/一文讲透如何给Docker设置代理 | 飞行的蜗牛只要70元轻nas——矿渣oec刷casaos保姆级教程\_哔哩哔哩\_bilibili话ophub大佬的OEC-Turbo armbian改灯光，关灯。-京东云、网心云、玩客云等PCDN云设备-恩山无线论坛 - Powered by Discuz!