普通视图

发现新文章,点击刷新页面。
昨天以前有意

Openwrt的一些小折腾(5)

作者 痞子鱼
2023年12月19日 12:26

前言

距离上一次折腾 OpenWrt 已经 3 年了,这段时间里偶尔也会对家里网络环境做一些小改动,现在主路由只负责拨号、DDNS和 DHCP 服务,其他事情交给 PVE 上的 OpenWrt 来负责。所以,为了主路由的稳定,一些任务尽可能的避免安装插件,用脚本来代替。

更新 DnsPod 和 CloudFlare 并发送通知

根据 serverchan 这个插件,搞了个脚本来代替,主要就是路由重启或者网络重拨后发送一些系统状态和网络信息到 Telegram,然后再更新 ddns。

1、首先在 /etc/hotplug.d/iface 创建 30-ddns-go 给予 755 权限,会在 WAN 口 发生变化的时候实时运行 serverchan 脚本。

#!/bin/sh
# wan ifup
[ "$ACTION" = "ifup" -a "$INTERFACE" = "wan" ]

sh /usr/share/watchdog/serverchan 

2、在/usr/share/watchdog/ 创建 serverchan 给予 755 权限

设置了一个参数,在直接运行 /usr/share/watchdog/serverchan send,就会发送一次标题为路由运行状况通知,方便定时任务调用。

脚本运行顺序:

当 WAN 口发生变化,就运行 serverchan ,WAN 口运行时间是否小于 60,如果大于 60 就结束脚本;

否则就进行下一个判断,WAN 口距离上一次发生变化是否大于 60,如果小于 60 就结束脚本;

否则就更新 DDNS,并做一次判断系统运行时间是否小于 60,小于60 就发送标题为 路由器重新启动;

否则就发送标题为 IP 地址变动通知;

通知都包含系统状态和网络信息。

另外需要注意,脚本在获取 IPV6 时,只是截取了前缀,所以 $wan_ipv6::1 的 ::1 是代表 路由上的 IP,可以更改成其他设备固定后缀。

脚本需要提前获取 Telegram 的 token 和 chat_id。

#!/bin/bash

# 发送 Telegram 消息
send_telegram_message() {
    local message=$1
    curl -s -X POST https://api.telegram.org/bot<token>/sendMessage -d "chat_id=<chat_id>" --data-binary "chat_id=$CHAT_ID&text=$message"
}

# 获取系统状态信息
get_system_status_message() {
    load_average=$(cut -d ' ' -f 1-3 /proc/loadavg)
    cpu_usage=$(get_cpu_usage)
    memory_usage=$(free | awk '/Mem:/ {printf "%.2f%", $3/($3+$4)*100}')
    uptime=$(cat /proc/uptime | awk '{print int($1/3600/24) "天" int($1/3600%24) "时" int($1%3600/60) "分" int($1%60) "秒"}')
    wan_info=$(ifstatus wan | jq -r '.uptime' | awk '{print int($1/3600/24) "天" int($1/3600%24) "时" int($1%3600/60) "分" int($1%60) "秒"}')
    wan_ipv4=$(ip -4 addr show dev pppoe-wan | grep inet | awk '{print $2}' | cut -d '/' -f 1)
    wan_ipv6=$(ip addr show br-lan | grep inet6 | sed 's/\/.*//g' | awk '{print $2}' | grep 240e | head -n 1 | awk -F '::' '{print $1}')

    system_status_message="系统状态:
--------
平均负载:$load_average
CPU 占用:$cpu_usage
内存占用:$memory_usage
运行时间:$uptime
--------
网络信息:
外网 IPv4: $wan_ipv4
外网 IPv6: $wan_ipv6::1
在线时间:$wan_info"
}

# 获取 CPU 占用
get_cpu_usage() {
    local AT=$(cat /proc/stat | grep "^cpu " | awk '{print $2+$3+$4+$5+$6+$7+$8 " " $2+$3+$4+$7+$8}')
    sleep 3
    local BT=$(cat /proc/stat | grep "^cpu " | awk '{print $2+$3+$4+$5+$6+$7+$8 " " $2+$3+$4+$7+$8}')
    printf "%.01f%%" $(echo ${AT} ${BT} | awk '{print (($4-$2)/($3-$1))*100}')
}

# 发送通知的函数
send_notification() {
    local notification_message=$1
    get_system_status_message
    send_telegram_message "$notification_message
--------

$system_status_message"
}

# 获取系统运行时间,单位为秒
uptime_seconds=$(cut -d '.' -f 1 /proc/uptime)

# 获取 WAN 口运行时间,单位为秒
wan_uptime_seconds=$(ifstatus wan | jq -r '.uptime')

# 从临时文件中获取上一次 WAN 口变动的时间
last_wan_change_time_file="/tmp/last_wan_change_time.txt"

# 如果临时文件存在,则从文件中读取上一次 WAN 口变动的时间,否则设置为0
last_wan_change_time=$(test -f "$last_wan_change_time_file" && cat "$last_wan_change_time_file" || echo 0)

# 跟踪 WAN 口变动时间,并更新临时文件
track_wan_change_time() {
    date +%s > "$last_wan_change_time_file"
}

# 检查 WAN 口通知条件
check_wan_notification() {
    current_time=$(date +%s)
    time_since_last_wan_change=$((current_time - last_wan_change_time))
    if [ "$time_since_last_wan_change" -gt 60 ]; then
        if [ "$uptime_seconds" -lt 60 ]; then
            send_notification "路由器重新启动"
        else
            send_notification "IP 地址变动通知"
        fi
        #更新 DnsPod DDNS
        sh /usr/share/watchdog/dnspod-go
        #更新 CloudFlare DDNS
        sh /usr/share/watchdog/cloudflare-go
        #更新时间戳
        track_wan_change_time
    fi
}

# 判断 WAN 是否启动,并发送通知
if [ "$wan_uptime_seconds" -lt 60 ]; then
    check_wan_notification
elif [ "$1" = "send" ]; then
    send_notification "路由运行状况通知"
fi

3、在/usr/share/watchdog/ 创建 cloudflare-go 给予 755 权限

进入 CloudFlare 的主页 -> 左侧网站-> 点击需要设置的域名。在右侧下方看到 区域 ID (ZoneID),另外需要点击 API 令牌去获取 Token。

ZoneID

添加 A 记录和 AAAA 记录并获取域名ID

获取域名ID

#!/bin/bash

# 更新 DNS 记录
cf_update_dns() {
    local record_id="$1"
    local record_type="$2"
    local record_name="$3"
    local record_content="$4"
    wan_ipv4=$(ip -4 addr show dev pppoe-wan | grep inet | awk '{print $2}' | cut -d '/' -f 1)
    wan_ipv6=$(ip addr show br-lan | grep inet6 | sed 's/\/.*//g' | awk '{print $2}' | grep 240e | head -n 1 | awk -F '::' '{print $1}')

    curl -X PUT "https://api.cloudflare.com/client/v4/zones/区域 ID/dns_records/$record_id" \
        -H "X-Auth-Email: Cloudflare的邮箱" \
        -H "X-Auth-Key: API 令牌" \
        -H "Content-Type: application/json" \
        --data "{\"type\":\"$record_type\",\"name\":\"$record_name\",\"content\":\"$record_content\",\"proxied\":false}"
}

# 更新 IPv4 地址的 DNS 记录
cf_update_dns "域名ID" "A" "test1.xxxnas.top" "$wan_ipv4"


# 更新 IPv6 地址的 DNS 记录
cf_update_dns "域名ID" "AAAA" "test2.xxxnas.top" "$wan_ipv6::1"

4、在/usr/share/watchdog/ 创建 dnspod-go 给予 755 权限

进入 dnspod 控制台 -> 我的域名

获取域名ID

点击域名进去,获取记录 ID,

记录 ID

获取 DNSPod TOKEN,然后将 下面的 LOGIN_TOKEN 替换成 222222,111111*0222222

DNSPod Token

#!/bin/bash

# 更新 DNS 记录函数
dp_update_dns() {
    local record_type=$1
    local sub_domain=$2
    local record_id=$3
    local value=$4
    wan_ipv4=$(ip -4 addr show dev pppoe-wan | grep inet | awk '{print $2}' | cut -d '/' -f 1)
    wan_ipv6=$(ip addr show br-lan | grep inet6 | sed 's/\/.*//g' | awk '{print $2}' | grep 240e | head -n 1 | awk -F '::' '{print $1}')

    local record_url="https://dnsapi.cn/Record.Modify"
    local record_params="login_token=LOGIN_TOKEN&format=json&domain_id=domain_id&record_id=$record_id&value=$value&record_type=$record_type&sub_domain=$sub_domain&record_line_id=0"

    curl -k -X POST "$record_url" -d "$record_params"
}


# 更新 IPv4 DNS 记录
dp_update_dns A "test1" "记录ID" $wan_ipv4


# 更新 IPv6 DNS 记录
dp_update_dns AAAA "test2" "记录ID" "$wan_ipv6::1"

网络故障重启网络和重启路由

另外还对上次的监控网络状态脚本做了一点小调整,连续重启 wan 口和路由两次还网络故障的话,更改检测间隔时间为 600 秒。不过根据最近的观察,觉得应该不是网络问题,而是弱电箱的电源功率不够导致的路由死机,所以也得考虑是否更换个电源来测试下。

#!/bin/sh

# 日志默认目录
LOG_DIR="/usr/share/watchdog"
# 连续计数
NETWORK_CHECK_COUNTER_FILE="${LOG_DIR}/network-counter.log"
# 执行日志
NETWORK_CHECK_LOG_FILE="${LOG_DIR}/network-check.log"
# 默认计数为0
COUNTER=0

# 连续失败计数大于该数值,则进行 RESTART_INTERVAL 秒等待,再执行重新检测
COUNTER_THRESHOLD=4
# 持续失败,后默认等待时间(秒),然后再重启
RESTART_INTERVAL=600

# 检查目录是否存在,不存在则创建
if [ ! -d "$LOG_DIR" ]; then
    echo "Creating directory $LOG_DIR"
    mkdir -p "$LOG_DIR"
fi

# 检查文件是否存在,如果不存在则创建文件
touch "$NETWORK_CHECK_LOG_FILE"

if [ ! -e "$NETWORK_CHECK_COUNTER_FILE" ]; then
    touch "$NETWORK_CHECK_COUNTER_FILE"
    echo "0" > "$NETWORK_CHECK_COUNTER_FILE"
fi
COUNTER=$(cat "$NETWORK_CHECK_COUNTER_FILE")

# 检测网络是否畅通
ping_domain() {
    # ping的域名或者DNS
    local domain="223.5.5.5"
    # ping的次数
    local tries=6
    # 请求成功次数
    local packets_responded=0

    for i in $(seq 1 "$tries"); do
        if ping -c 1 "$domain" >/dev/null; then
            packets_responded=$((packets_responded + 1))
            sleep 1
        fi
    done

    # 如果请求成功总次数大于等于2,则表示成功
    if [ "$packets_responded" -ge 2 ]; then
        echo "true"
    else
        echo "false"
    fi
}

# 检测网络连接函数
check_network() {
    # 如果ping 6次至少有2次包未响应,则执行以下代码
    if [ "$(ping_domain)" = "false" ]; then
        # 如果无法连接网络,则重启网络
        echo "$(date '+%Y-%m-%d %H:%M:%S') 网络连接失败"
        echo "$(date '+%Y-%m-%d %H:%M:%S') 网络连接失败" >> "$NETWORK_CHECK_LOG_FILE"

        /etc/init.d/network restart

        echo "$(date '+%Y-%m-%d %H:%M:%S') 网络服务已重启"
        echo "$(date '+%Y-%m-%d %H:%M:%S') 网络服务已重启" >> "$NETWORK_CHECK_LOG_FILE"
        echo "$(( $(cat "$NETWORK_CHECK_COUNTER_FILE") + 1 ))" > "$NETWORK_CHECK_COUNTER_FILE"

        sleep 60

        if [ "$(ping_domain)" = "false" ]; then
            # 如果仍无法连接网络,则重启路由服务
            echo "$(date '+%Y-%m-%d %H:%M:%S') 重启网络后,联网失败,准备重启路由"
            echo "$(date '+%Y-%m-%d %H:%M:%S') 重启网络后,联网失败,准备重启路由" >> "$NETWORK_CHECK_LOG_FILE"
            echo "$(( $(cat "$NETWORK_CHECK_COUNTER_FILE") + 1 ))" > "$NETWORK_CHECK_COUNTER_FILE"

            /sbin/reboot

        else
            echo "$(date '+%Y-%m-%d %H:%M:%S') 重启路由后,连接已恢复"
            echo "$(date '+%Y-%m-%d %H:%M:%S') 重启路由后,连接已恢复" >> "$NETWORK_CHECK_LOG_FILE"
        fi
    else
        echo "$(date '+%Y-%m-%d %H:%M:%S') 网络连接正常"
        echo "$(date '+%Y-%m-%d %H:%M:%S') 网络连接正常" >> "$NETWORK_CHECK_LOG_FILE"
        echo "0" > "$NETWORK_CHECK_COUNTER_FILE"
    fi
}

# 计数器检查函数
check_counter() {
    COUNTER=$(cat "$NETWORK_CHECK_COUNTER_FILE")
    if [ "$COUNTER" -ge "$COUNTER_THRESHOLD" ]; then
        echo "$(date '+%Y-%m-%d %H:%M:%S') 计数器值大于等于 $COUNTER_THRESHOLD ,等待 $RESTART_INTERVAL 秒后重新检测网络连接"
        echo "$(date '+%Y-%m-%d %H:%M:%S') 计数器值大于等于 $COUNTER_THRESHOLD ,等待 $RESTART_INTERVAL 秒后重新检测网络连接" >> "$NETWORK_CHECK_LOG_FILE"
        sleep "$RESTART_INTERVAL" # 等待
        echo "$(date '+%Y-%m-%d %H:%M:%S') 等待 $RESTART_INTERVAL 秒后,开始重新检测网络" >> "$NETWORK_CHECK_LOG_FILE"
        check_network
    else
        check_network
    fi
}

check_counter

echo "$(date '+%Y-%m-%d %H:%M:%S') 网络检查完毕"

基于 PVE 的折腾之路(4)之 影音库云盘自动化

作者 痞子鱼
2023年8月1日 17:06

前言

前文【基于 PVE 的折腾之路(3)之 影音库自动化】实现了本地自动化追剧。但现在阿里云盘的热门以及搭配各种项目也能实现自动化转存追剧,并且通过 nginx 的 njs 模块将 emby 视频播放地址劫持到 alist 直链。

本文需要在群晖 Docker 安装 emby 、alist、aliyundrive-subscribe、nginx、rclone

完成后基本流程:电视剧有更新 -> aliyundrive-subscribe 自动转存到指定目录 -> 通知 emby 有新视频 -> emby 刮削 -> emby 通过 nginx 直接播放阿里云盘上的视频。

为什么改用 Emby?

之前一直都是用 jellyfin,因为开源免费。但不知为何对于现在的 4k 视频很多无法正常播放,都强制服务端转码。一开始以为是电视型号太旧不支持解码,所以以前下载视频都只能找特定编码的。

偶然一次心血来潮换成 emby 测试一下,竟然除了音频是 TrueHD 7.1 或 Dolby Atmos 7.1 会导致服务器转码,其他 4K HEVC HDR10 或 4K HEVC HDR10+ 都播放很流畅,所以就改用 emby 做服务端。

1、安装 emby

docker run -d \
    --name emby \
    -e PUID=1026 \
    -e PGID=100 \
    -e TZ=Asia/Shanghai \
    -p 8096:8096 \
    -v /volume1/docker/emby:/config \
    -v /volume1/video:/video \
    --restart unless-stopped \
lovechen/embyserver:latest

2、安装 alist (alist 配置教程请看 wiki)

docker run -d \
    --name=alist \
    --restart=unless-stopped \
    -e PUID=1026 \
    -e PGID=100 \
    -e UMASK=022 \
    -p 5244:5244 \
    -v /volume1/video:/video \
    -v /volume1/docker/alist:/opt/alist/data \
xhofe/alist:latest

3、安装 aliyundrive-subscribe

docker run -d \
    --restart=unless-stopped \
    --name=subscribe \
    -e PUID=1026 \
    -e PGID=100 \
    -e TZ=Asia/Shanghai \
    -p 19035:19035 \
    -v /volume1/docker/subscribe:/app/conf \
looby/aliyundrive-subscribe:latest

4、安装 nginx (映射文件请在 Wiki 中提前下载)

docker run -d \
    --name=nginx \
    -e PUID=1026 \
    -e PGID=100 \
    -e TZ=Asia/Shanghai \
    -p 8095:80 \
    -v /volume1/docker/nginx/nginx.conf:/etc/nginx/nginx.conf \
    -v /volume1/docker/nginx/conf.d:/etc/nginx/conf.d \
    -v /volume1/docker/nginx/cache:/var/cache/nginx/emby \
nginx:alpine

配置 alist

默认用户名admin,密码需要在 控制台日志查看,通过群晖 IP:5244 端口登录进入后台,找到存储这里,点击添加

2023-08-04T00:35:45.png

选择阿里云盘Open

2023-08-04T00:36:29.png

主要配置挂载路径,即在 NAS 本地的路径;还有刷新令牌。

具体配置教程可以看 Wiki

配置 aliyundrive-subscribe

通过群晖 IP:8002 端口登录 subscribe,/volume1/docker/subscribe/config/app.ini 设置好账号密码以及阿里云盘的 token。

2023-08-04T00:36:44.png

具体配置教程可以看 Wiki

2023-08-04T00:36:51.png

roclone 挂载 alist 到本地

通过 ssh 登录到群晖,获取 root

# 安装 rclone
curl https://rclone.org/install.sh | sudo bash
# 创建 rclone 配置文件文件夹
mkdir /volume1/docker/rclone

# 创建 rclone 配置文件,注意用户名和密码,建议 alist 创建一个只读的用户用于挂载用途
cat <<EOF >> /volume1/docker/rclone/rclone.conf
[aliyunpan]
type = webdav
url = http://10.0.0.5:5244/dav
vendor = other
user = admin
pass = Hg8GURjFFspmY0UJKImq5NnzhpW5
EOF
# 创建 rclone 挂载文件,注意修改下面挂载参数
cat <<EOF >> /volume1/docker/rclone/rcloned
#!/bin/bash

PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
NAME_BIN="rclone"

NAME="aliyunpan" #和上面的 rclone 文件一致
REMOTE=''  #远程文件夹,网盘里的挂载的一个文件夹,留空为整个网盘
LOCAL='/volume1/video/aliyunpan'  #挂载地址,VPS本地挂载目录
LOG="/volume1/docker/rclone/log.txt"

Green_font_prefix="\033[32m" && Red_font_prefix="\033[31m" && Green_background_prefix="\033[42;37m" && Red_background_prefix="\033[41;37m" && Font_color_suffix="\033[0m"
Info="${Green_font_prefix}[信息]${Font_color_suffix}"
Error="${Red_font_prefix}[错误]${Font_color_suffix}"
RETVAL=0

check_running(){
    PID="$(ps -C $NAME_BIN -o pid= |head -n1 |grep -o '[0-9]\{1,\}')"
    if [[ ! -z ${PID} ]]; then
        return 0
    else
        return 1
    fi
}
do_start(){
    check_running
    if [[ $? -eq 0 ]]; then
        echo -e "${Info} $NAME_BIN (PID ${PID}) 正在运行..." && exit 0
    else
        fusermount -zuq $LOCAL >/dev/null 2>&1
        mkdir -p $LOCAL
        mkdir -p ${LOG%/*}
        sudo /usr/bin/rclone mount --config /volume1/docker/rclone/rclone.conf $NAME:$REMOTE $LOCAL --umask 000 --default-permissions --allow-non-empty --allow-other --buffer-size 32M --vfs-read-chunk-size 64M --vfs-read-chunk-size-limit 1G > "${LOG}" 2>&1 &
        sleep 2s
        check_running
        if [[ $? -eq 0 ]]; then
            echo -e "${Info} $NAME_BIN 启动成功 !"
        else
            echo -e "${Error} $NAME_BIN 启动失败 !"
        fi
    fi
}
do_stop(){
    check_running
    if [[ $? -eq 0 ]]; then
        kill -9 ${PID}
        RETVAL=$?
        if [[ $RETVAL -eq 0 ]]; then
            echo -e "${Info} $NAME_BIN 停止成功 !"
        else
            echo -e "${Error} $NAME_BIN 停止失败 !"
        fi
    else
        echo -e "${Info} $NAME_BIN 未运行"
        RETVAL=1
    fi
    fusermount -zuq $LOCAL >/dev/null 2>&1
}
do_status(){
    check_running
    if [[ $? -eq 0 ]]; then
        echo -e "${Info} $NAME_BIN (PID $(echo ${PID})) 正在运行..."
    else
        echo -e "${Info} $NAME_BIN 未运行 !"
        RETVAL=1
    fi
}
do_restart(){
    do_stop
    sleep 2s
    do_start
}
case "$1" in
    start|stop|restart|status)
    do_$1
    ;;
    *)
    echo "使用方法: $0 { start | stop | restart | status }"
    RETVAL=1
    ;;
esac
exit $RETVAL
EOF

最后运行 rclone 挂载到本地

# 使用方法: { start | stop | restart | status }
bash /volume1/docker/rclone/rcloned strat

配置 nginx

主要还是配置 emby.js

const embyHost = 'http://172.17.0.1:8096'; //默认emby的地址是宿主机ip
const embyMountPath = '/video';  // rclone 的挂载目录, 例如将阿里云盘挂载到/volume1目录下:  /volume1/video/aliyun,就填写 /video
const alistToken = 'alist-1c14e05d-b222-4307-9db7····'; //alist token, 在alist后台查看
const alistAddr= 'http://172.17.0.1:5244'; //访问宿主机上5244端口的alist地址
const embyApiKey = 'ab5bbc1f4233saedg2252e95fb53cbc4';  //emb api key, 在后台设置
const alistPublicAddr = 'http://10.0.0.5:5244'; // alist公网地址

具体配置教程可以看 Wiki

总结

至此,可以访问群晖IP:8095 端口访问 emby 服务,emby 媒体库也和添加普通本地文件一样步骤,刮削的文件和图片建议放本地,不要放到媒体所在文件夹,以免访问 api 过于频繁。播放速度也不再受制于家里宽带的上传速度,直接在客户端播放阿里云盘上的视频。

结合上篇本地自动化和本文云盘自动化,总存储空间达到了 42 T 左右,不过收藏的还是建议存储在本地,云盘上的只用于追剧,免得哪天又倒闭了。

2023-08-04T00:37:07.png

基于 PVE 的折腾之路(3)之 影音库自动化

作者 痞子鱼
2023年1月3日 12:33

前言

本文需要在群晖 Docker 安装 qBittorrent 、nastool、、ChineseSubFinder、aliyundrive-web、jellyfin

需要套件 Docker、 Cloud Sync

完成后基本流程有两种:

1、保存视频到 阿里云盘 -> 群晖 docker aliyundrive-web 挂载 -> cloud sync 同步 -> video/downloads 文件夹 -> nastool 识别刮削,硬连接转移 video/(movie 或 tv 文件夹) -> 通知 ChineseSubFinder 下载字幕 -> 通知 jellyfin 有新视频

2、PT 站搜索种子 -> qBittorrent 下载 -> video/downloads 文件夹-> nastool 识别刮削,硬连接转移 video/(movie 或 tv 文件夹) -> 通知 ChineseSubFinder 下载字幕 -> 通知 jellyfin 有新视频

File Station

安装 Docker 所需容器

先新建两个共享文件夹 docker、video,然后在 docker 文件夹下新建目录 qbittorrent、aliyun、ChineseSubFinder(新建 config、cache 两个目录)、jellyfin(新建 config、cache 两个目录) ,video 文件夹下新建目录 downloads、movie、tv、unknow。

群晖安装好 Docker 套件,后面步骤通过 SSH 登录到群晖,然后获取 root 权限来操作。

注意:下面操作中的 volume1 或 volume2 需要根据自己存储空间位置来确定。

1、安装 qBittorrent

docker run -d \
    --name=qbittorrent \
    -e PUID=1026 \
    -e PGID=100 \
    -e WEBUIPORT=8080  \
    -e TZ=Asia/Shanghai \
    -v /volume1/docker/qbittorrent:/config \
    -v /volume2/video/downloads:/downloads \
    --restart unless-stopped \
linuxserver/qbittorrent:latest

2、安装 aliyundrive-web

docker run -d \
    --name=aliyun \
    --restart=unless-stopped \
    -e PUID=1026 \
    -e PGID=100 \
    -p 9900:8080 \
    -e REFRESH_TOKEN='获取自己阿里云盘的TOKEN' \
    -e WEBDAV_AUTH_USER=admin \
    -e WEBDAV_AUTH_PASSWORD=admin \
    -v /volume1/docker/aliyun/:/etc/aliyundrive-webdav/ \
messense/aliyundrive-webdav:latest

3、安装 ChineseSubFinder

docker run -d \
    --restart=unless-stopped \
    --name=ChineseSubFinder \
    -e PUID=1026 \
    -e PGID=100 \
    -e TZ=Asia/Shanghai \
    -p 19035:19035 \
    -v /volume1/docker/ChineseSubFinder/config:/config \
    -v /volume1/docker/ChineseSubFinder/cache:/app/cache \
    -v /volume2/video:/media \
allanpk716/chinesesubfinder:latest

4、安装 nastool

docker run -d \
    --name nastools \
    --hostname nastools \
    -p 3400:3000 \
    -v /volume1/docker/nastool:/config \
    -v /volume2/video:/video \
    -e PUID=1026 \
    -e PGID=100 \
    -e UMASK=000 \
    -e NASTOOL_AUTO_UPDATE=false \
jxxghp/nas-tools:latest

5、安装 jellyfin

docker run -d \
    --name=jellyfin \
    -e PUID=1026 \
    -e PGID=100 \
    -e TZ=Asia/Shanghai \
    -p 8096:8096 \
    -v /volume1/docker/jellyfin/config:/config \
    -v /volume1/docker/jellyfin/cache:/cache \
    -v /volume2/video:/video \
nyanmisaka/jellyfin:latest

配置 nastool

通过群晖 IP:3400 端口登录 nastool,默认账号 admin,密码 Password。

1、设置 -> 基础设置,需要在 themoviedb 注册账号,获取 API key(必须步骤)。

themoviedb api key

2、设置媒体目录,就是刮削好后硬连接的目录,提供给 jellyfin 或 ChineseSubFinder 挂载使用,unknow 目录是用于未识别成功的文件。

设置媒体目录

3、目录同步,设置好源目录 downloads 就行,在监测到 downloads 有新文件,就会自动识别是电影还是电视剧,然后硬连接到上面的媒体目录中。

目录同步

4、下载器设置 -> 下载目录配置,让 qBittorrent 自动分类下载的文件类型。

下载器设置

5、媒体服务器配置,先登录 群晖 IP:8096,控制台 -> API 密钥新建一个 nastool。

媒体服务器 api

然后在 nastool 填入 媒体服务器 IP:8096 和 API 密钥。

设置字幕下载

6、字幕下载,先登录 群晖 IP:19035,配置中心-> 实验室,最下面 API key 生成。

设置字幕下载 api

然后在 nastool 选择 ChineseSubFinder 填入,IP:19035 和 API key。

设置字幕下载 api

6、群晖安装 Cloud Sync 套件,设置 Cloud Sync 同步 阿里云盘。

选择 webDav

选择 webDav

填入安装 Docker 所需容器时设置的地址端口、账户、密码

设置 webDav

本地路径设置成 下载目录,远程路径设置成 阿里云盘放视频的目录,同步方向为仅下载,并删除源文件时不删除本地的。

设置 webDav

后记

至此,下载电影自动刮削、硬连接、下载字幕一系列都可以自动化完成,当然 nastool 还有通知、订阅电视剧后自动下载等功能可以自行摸索。

感谢这些大神开发的各类插件,非常方便追剧。

电视剧订阅

基于 PVE 的折腾之路(2)之 安装群晖

作者 痞子鱼
2022年6月1日 12:00

前言

前文【基于 PVE 的折腾之路(1)之 Proxmox VE 的安装配置】已经搭建好基础环境,那么第二步就是安装这台 nas 最主要的功能:照片和文件的管理。之前一直都是用 Nextcloud,但一直只用于自动备份照片,浏览实在很不方便,而且最近几个版本,App 也无法在后台自动备份了。所以趁着现在换了底层系统,也眼馋群晖新版 Photos 的人脸识别,所以就黑一个吧。

版本选择

群晖最新的是 7.1 版本,不过看了网上教程是不推荐的。HEIC 格式的相片或者 hevc 编码的视频,需要通过 Advanced Media Extensions 来获得授权才可以正常观看。

但想获得这个授权,就的彻底洗白:sn、mac1、mac2、netif_num、DiskIdxMap、SataPortMap、SasIdxMap 这些参数都必须是真实的,然后登录 Synology 帐户。

所以放弃,选择了 7.0.1.

安装记录

注意:不管做什么操作,一定要提前备份好重要数据

是的,我在转移数据的时候操作失误丢过一些文件,幸好不是重要的。

黑群晖的安装教程特别容易找到,特别是 VM 和 PVE 平台下的。结合下自己配置过程中的情况,略微更改了一下。再次说明本文不是图文教程,只是个人安装的一些步骤记录。需要图文教程可以参考 GXNAS 博客的文章:Proxmox VE(PVE)安装黑群晖DS918-7.01教程

引导文件

安装的型号选择了 3615xs,因为 GEN 8 屏蔽了核显,所以 918+ 不适合,虽然有脚本可以改成 CPU 来人脸识别。(6.15 更正:网卡原因 GEN8 无法实体机安装 918+,虚拟机不影响)

先下载好 3615xs 的引导文件和安装包,因为人脸识别需要半洗白才能使用,所以使用 DiskGenius 复制出 grub.cfg 文件修改 mac 和 sn,可以使用这个序列号计算器,修改完成后把 grub.cfg 文件放回去替换掉,然后把引导文件重命名位 3615.img 上传到在之前创建好的 ssd 目录下的 iso 镜像里面。

创建虚拟机

  • VM ID 100,名称自取(例如 synology);
  • 磁盘全部默认,一会要删掉;
  • CPU 给个 4 核心;
  • 内存给了 8 G,反正也不会常开几个虚拟机;
  • 网络默认即可,不过确认下载的引导包含驱动就好;
  • 完成虚拟机创建后,先不启动,在虚拟机 硬件选项里分离刚创建的硬盘,然后删除。

进入 pve 节点,选择 Shell

# 输入以下命令转换群晖引导盘成 PVE 虚拟机的格式
qm importdisk 100 /mnt/ssd/template/iso/3615.img ssd

在虚拟机 - 硬件里,双击"未使用的磁盘0",在"总线/设备"点下拉列表,选 SATA 后添加。

再给虚拟机添加一块虚拟硬盘,"存储"选 ssd 的存储盘,磁盘大小根据实际需要设置,"SSD 仿真"打勾,格式选择"原始磁盘映像 Raw"添加;(之前一直是默认的"QEMU 映像格式"导致一直无法找到硬盘,这是小坑)

创建虚拟机

在虚拟机 - 选项里编辑引导顺序,只勾上 sata0,然后启动虚拟机,后面就和大部分教程一样安装群晖系统了。

挂载硬盘

进入 pve 节点,选择 Shell

# 查询物理硬盘标号
ls /dev/disk/by-id/

# 假设查询到硬盘ID为
ata-TOSHIBA_DT01ACA050

qm set 100 --sata2 /dev/disk/by-id/ata-TOSHIBA_DT01ACA050

我是直接把三块硬盘都挂载给群晖管理,然后 smb 共享给其他虚拟机使用,另外可以一个盘一个盘操作,比如先挂载一个空盘,进去群晖建立存储空间后,把其他盘的数据传到上面去,再挂载其他盘来建立新的存储空间。

挂载硬盘

后记

安装好群晖前前后后重复了七八次,搜索了很多文章来参考,最总都是因为那个小坑而失败,最后看别人最后配置和自己的有点差别才设置成 Raw 后才成功。

现在还在转移数据和整理照片,群晖的相册比起之前安装 6.0 的时候好用多了,也比 Nextcloud 查看照片方便,不过人脸识别很吃 CPU 资源,最近几天服务器的功率基本都是在 80 w 上下浮动,温度没低过 60 ℃,风扇转速也一直在 50% 以上。

平时功耗大概在 48 w,比起之前 windows server 2016 高出 6 w 左右。

之前老婆和我的照片都很多重复的,现在差不多十年的照片,5万多张,预计整理过后只剩下4万多张吧,任道而重远了。

用电量

基于 PVE 的折腾之路(1)之 Proxmox VE 的安装配置

作者 痞子鱼
2022年5月27日 16:47

前言

家里那台 GEN 8 一直都是跑的 Windows 系统开启 Hyper-v 虚拟化 openwrt 和 CentOS。最近在测试一些东西的时候,觉得 8 G 的内存实在不够用,淘宝上的 8 G*2 也已经降到 320 而已,就买回来给换了。

最近发现 Nextcloud 备份照片无法后台进行,而且翻看照片也不方便,干脆全部推到重新规划一下,换个宿主系统,虚拟黑群晖 7 .0 和 openwrt,想干就干吧,毕竟生命在于折腾。

在经过几天的 Google 资料初步学习后,最后定下来使用 Proxmox VE。

介绍

Proxmox VE 是一个开源的服务器虚拟化环境 Linux 发行版。用户可通过网页的方式来管理服务器上使用 kvm 以及 lxc 技术运行的虚拟机。同时提供了一些先进功能的支持,如集群、HA 等,对普通用户而言,PVE 是可以免费使用的

安装

安装的 Windows 系统是安装在光驱位的 SATA 5 接口的固态硬盘上,然后使用 B120i RAID 对各个磁盘做了 RAID 0,所以引导没问题。这次安装 PVE 就更改成 AHCI 模式下,但产生的一个问题就是在 AHCI 模式下无法从 SATA 5 接口引导。

常见应对方法:

  1. 放弃 AHCI,继续使用 B120i 配置 RAID,和原来一样从 SATA 5 所在的 RAID 阵列引导;
  2. 系统安装在 SATA 5 的硬盘,用 GRUB 二次引导。
  3. 将系统装在 U 盘或 TF 卡里(主板上有一个 USB 和一个 TF 卡接口),然后在 BIOS 里选择从 USB 引导。

方法1 直接放弃了,因为发现哪怕用 B120i 做 RAID,也会出现无法成功引导启动的问题,而且风扇也和在 AHCI 模式下一直维持在 20%~25%(如果有解决方案,麻烦大神指教下);

方法 2 正常启动,但由于对 PVE 也是在熟悉过程中,不小心折腾崩溃了系统,尝试了多种办法无法修复,最后重新安装 PVE 格式化整盘,导致之前配置的虚拟机全部得重新安装和配置。

方法 3 就是我现在采用的安装方法,PVE 安装在 TF 卡上,虚拟机全部丢到 SATA 5 的固态硬盘上,提前备份好 qemu-server 目录的文件,哪怕系统崩溃直接重装后,然后把 qemu-server 目录的文件放回去,虚拟机就可以直接开机使用。

首先去 Proxmox 官网下载安装包,目前最新版本是 7.2。PVE 的安装过程跟 Esxi 或者 Windows 类似,GEN 8 可以通过 iLo 挂载镜像远程安装,这样省去了把 ISO 文件刻录进 U 盘再进行安装的麻烦,就是速度上会有点慢。

安装过程就懒得截图什么的了,网上已经很多大神分享了,本文也不是教程,主要记录个人的一些基础配置信息。建议去小破站或者油管看下司波图关于 PVE 的系列教程,对于入门而言还是很有参考价值。

初始配置

换源

# 删掉企业源
rm -rf /etc/apt/sources.list.d/pve-install-repo.list

echo "#deb https://enterprise.proxmox.com/debian/pve Bullseye pve-enterprise" > /etc/apt/sources.list.d/pve-enterprise.list
# 换源(中国科学技术大学)
wget https://mirrors.ustc.edu.cn/proxmox/debian/proxmox-release-bullseye.gpg -O /etc/apt/trusted.gpg.d/proxmox-release-bullseye.gpg

echo "deb https://mirrors.ustc.edu.cn/proxmox/debian/pve bullseye pve-no-subscription" > /etc/apt/sources.list.d/pve-no-subscription.list

echo "deb https://mirrors.ustc.edu.cn/proxmox/debian/ceph-pacific bullseye main" > /etc/apt/sources.list.d/ceph.list

sed -i.bak "s#http://download.proxmox.com/debian#https://mirrors.ustc.edu.cn/proxmox/debian#g" /usr/share/perl5/PVE/CLI/pveceph.pm

sed -i.bak "s#ftp.debian.org/debian#mirrors.aliyun.com/debian#g" /etc/apt/sources.list

sed -i "s#security.debian.org#mirrors.aliyun.com/debian-security#g" /etc/apt/sources.list
echo "deb http://download.proxmox.com/debian/pve bullseye pve-no-subscription" >>  /etc/apt/sources.list
# 更新系统
apt update && apt dist-upgrade -y

Local、Local-LVM 合并

安装了PVE,系统默认把 TF 卡空间分成了 Local、Local-LVM 两部分,不过以后也基本不会在这里面做什么操作,所以就把它们合并在一起,免得碍眼。

# 删除 local-lvm
lvremove pve/data

# 把删除的 Local-LVM 给Local
lvextend -l +100%FREE -r pve/root

然后选择 数据中心 ,存储 ,删除 Local-LVM。

编辑 Local,有需要的话就打上勾。个人建议是只选择 IOS,免得后面创建虚拟机的时候选错磁盘位置。毕竟TF 卡也主要运行系统,而且读写速度不够快,基本也不会去用。

编辑Local

添加 SSD 目录

硬盘分区、格式化

先确认硬盘的设备名称,例如 /dev/sdd,也可以在命令里用 fdisk -l 去确认。

# 分区
fdisk /dev/sdd

# 格式化
mkfs -t ext4 /dev/sdd1

# 创建 /mnt/ssd 目录:
mkdir -p /mnt/ssd

# 挂载分区:
mount -t ext4 /dev/sdd1 /mnt/ssd

# 开机挂载
echo /dev/sdd1 /mnt/ssd ext4 defaults 1 2 >> /etc/fstab

PVE 挂载硬盘

选择 数据中心 ,存储 - 添加 - 目录

ID 可以随便填,方便自己确认,目录就是刚挂载的 /mnt/ssd,内容全选,其它默认,点击添加;

几秒钟后就可以看到硬盘

添加 SSD目录

上传镜像文件

选择对应硬盘目录,选择内容 - 上传,选择准备好的ISO文件,上传即可,上传后建立虚拟机时便可以选择。

关联UPS

# 安装 apcupsd
apt-get install apcupsd -y
# 编辑配置文件 /etc/apcupsd/apcupsd.conf

# UPSNAME改成
UPSNAME XXX(起个名字)
 
# 设置为30表示,切换到ups电源30S后开始关闭虚拟机,然后关闭宿主机,0为不启用
TIMEOUT 30
 
# 每隔15s输出ups状态到日志中
STATTIME 15
 
# 开启日志,日志文件为/var/log/apcupsd.status
LOGSTATS on
 
# 线缆类型为usb
UPSCABLE usb
 
# usb接口,自动识别
UPSTYPE usb
 
# 还要注意把下面这行注释掉,不然不会自动发现usb
# DEVICE /dev/ttyS0
 
# 断电6s后才识别为正在使用电池,防止短时间断电导致错误+1
ONBATTERYDELAY 6
 
# 电池电量低于5%时关闭主机
BATTERYLEVEL 5
 
# 预计电量剩余时间小于3分钟时关闭主机
MINUTES 3

apcupsd 的命令

# 启动apcupsd
systemctl start apcupsd

# 查看apcupsd进程状态
systemctl status apcupsd

# 开机启动
systemctl enable apcupsd

# 重启apcupsd,更改配置文件后使用
systemctl restart apcupsd

# 查看ups状态
apcaccess

查看ups状态

总结

总得来说 PVE 的初始化配置都是命令为主,网上教程也很多,这些基础配置也属于比较简单,遇到什么问题 Google 一下都能找到答案,以后也基本上不会对宿主机做什么大改动。

后续是基于 PVE 上搭建 群晖 7.0.1、openwrt,为了一些操作需要还会安装一个 win10 系统的虚拟机吧。之前在 CentOS 上的那些 Docker 容器就交给群晖负责。

折腾nas ——TimeMachine(修改)

作者 痞子鱼
2022年5月11日 14:29

前言

5月 11 日发布的第一个版本经过两天测试已经失败无效:容易备份中断,而且因为权限问题而出现无法再次备份。

本文会不定时更新更稳定的方法,现在您看到是重新试验过后于 5 月 16 日 更新的第二个版本。

还是有个小瑕疵:如果服务器重启,TimeMachine 容器无法正常启动,需要删除后重新部署,但不会影响到之前的备份,继续找解决办法。
暂时解决,在描述文件中增加一项配置 tty: true

TimeMachine

手里的笔记本还是 2015 年的 Macbook Air,多年前通过淘宝购买的转接卡更换成 512G 的硬盘使用至今,前几天因为升级到 Monterey,各种卡顿导致不得不降级回之前使用习惯的 Catalina。

由于之前一直都没备份过,降级后除了存在 iCloud 上的文件和照片,大部分软件都得重新安装、配置。所以觉得平时还是需要做一下备份,免得再出现意外的时候又的重复这痛苦而漫长的过程。

Docker TimeMachine

家里的 NAS 一直都是使用 Windows Server 2016,然后 Hyper-V 安装 RockyLinux(之前安装 Centos 8,用脚本迁移到 Rocky Linux)挂载 Windows 系统上的硬盘来跑各种 Docker 服务,所以这次的 TimeMachine 也是找了 Docker 镜像来运行。

试过多个镜像后,在 reddit 上给我找一个配置最简单的.

准备服务描述文件:

version: "3.7"
services:
  timemachine:
    image: msjpq/time-machine
    container_name: timemachine
    tty: true # 增加解决无法正常启动问题
    network_mode: "host"
    environment:
      - SMB_NAME=TimeMachine
      - SMB_USER=timemachine # 帐户
      - SMB_PASSWORD=timemachine # 密码
      - PGID=0
      - PUID=0
    volumes:
      - /home/TimeMachine:/share # 备份路径
    restart: always

Hyper-V 添加磁盘

新建一个 TimeMaChine 磁盘

Jietu20220513-195910.jpg

虚拟机里添加磁盘

Jietu20220514-114250.jpg

Rocky Linux

挂载磁盘

[root@Rocky /]# fdisk -l
# 新的硬盘 分区是 /dev/vdb
Disk /dev/vdb:320 GiB,343597383680 字节,671088640 个扇区
单元:扇区 / 1 * 512 = 512 字节
扇区大小(逻辑/物理):512 字节 / 4096 字节
I/O 大小(最小/最佳):4096 字节 / 4096 字节
  
[root@Rocky /]# fdisk /dev/vdb
欢迎使用 fdisk (util-linux 2.32.1)。
更改将停留在内存中,直到您决定将更改写入磁盘。
使用写入命令前请三思。
设备不包含可识别的分区表。
创建了一个磁盘标识符为 0x0b161e1d 的新 DOS 磁盘标签。
命令(输入 m 获取帮助):n
分区类型
   # 输入p分为主分区
   p   主分区 (0个主分区,0个扩展分区,4空闲)
   # 输入e分为逻辑分区
   e   扩展分区 (逻辑分区容器)
选择 (默认 p):
将使用默认回应 p。
# 输入该主分区为第几个主分区,由于是新盘我们输入1来分第一个主分区
分区号 (1-4, 默认  1): 1
# First sector 是选择该分区的起始扇区,直接回车
第一个扇区 (2048-671088639, 默认 2048): 
# 使用全部可用存储额,直接回车
上个扇区,+sectors 或 +size{K,M,G,T,P} (2048-671088639, 默认 671088639): 
创建了一个新分区 1,类型为“Linux”,大小为 320 GiB。
# 输入 w 保存
命令(输入 m 获取帮助):w
分区表已调整。
将调用 ioctl() 来重新读分区表。
正在同步磁盘。

格式化并且挂载

# mkfs.xfs命令带-f强制格式化
[root@Rocky /]# mkfs.xfs -f /dev/vdb
Disk /dev/sdb:320 GiB,343597383680 字节,671088640 个扇区
单元:扇区 / 1 * 512 = 512 字节
扇区大小(逻辑/物理):512 字节 / 4096 字节
I/O 大小(最小/最佳):4096 字节 / 4096 字节
磁盘标签类型:dos
磁盘标识符:0x0b161e1d

设备       启动  起点      末尾      扇区  大小 Id 类型
/dev/vdb1        2048 671088639 671086592  320G 83 Linux

# 用命令blkid 查看一下已是xfs格式
[root@Rocky /]# blkid /dev/vdb
/dev/sdb: UUID="905d8713-4f37-411f-936d-42a7b9e4537a" BLOCK_SIZE="4096" TYPE="xfs"

# 创建挂载目录(/home 已经存在 直接挂载)
# mount直接挂载硬盘至data
[root@Rocky /]# mount /dev/vdb /home

# 查看一下挂载的硬盘home
[root@Rocky /]# df -h

devtmpfs             841M     0  841M    0% /dev
tmpfs                870M  4.0K  870M    1% /dev/shm
tmpfs                870M   19M  851M    3% /run
tmpfs                870M     0  870M    0% /sys/fs/cgroup
/dev/mapper/cl-root   57G   36G   21G   63% /
/dev/sda1           1014M  436M  579M   43% /boot
tmpfs                174M   24K  174M    1% /run/user/976
tmpfs                174M     0  174M    0% /run/user/0
/dev/vdb             320G  2.3G  318G    1% /home

# 系统重启自动挂载该分区对fstab进行编辑
[root@Rocky /]# vi /etc/fstab
#
# /etc/fstab
# Created by anaconda on Wed Dec  1 14:33:09 2021
#
# Accessible filesystems, by reference, are maintained under '/dev/disk/'.
# See man pages fstab(5), findfs(8), mount(8) and/or blkid(8) for more info.
#
# After editing this file, run 'systemctl daemon-reload' to update systemd
# units generated from this file.
#
/dev/mapper/cl-root     /                       xfs     defaults        0 0
UUID=c6133267-fb84-4315-829c-a2deaffb00bf /boot                   xfs     defaults        0 0
/dev/mapper/cl-swap     none                    swap    defaults        0 0
UUID=905d8713-4f37-411f-936d-42a7b9e4537a /home                   xfs     defaults        0 0

启动 TimeMachine 容器:

docker-compose up -d

远程访问 :打开 Finder,使用快捷键 ⌘Command+K 来连接到服务器,填入 NAS 对应的 SMB 地址,并输入 TimeMachine 的用户名和密码;

Jietu20220514-130833.jpg

因为之前第一版教程里已经有备份到 Windows 上,在 RockyLinux 将 Windows 上之前的备份过的 TimeMachine 文件夹整个移动到 home 目录下;

打开 TimeMachine 备份磁盘中选择刚刚建立连接的磁盘 TimeMachine,如果之前是加密备份的话,此时会提示包含了一个加密备份,选择使用现在备份,然后验证密码即可。(如果是全新备份则无此提示)

Jietu20220513-194401.jpg

又开始愉快的继续之前的备份了。

Jietu20220515-192950.jpg

日常吐槽(1)

作者 痞子鱼
2022年3月22日 15:16

莞要钱和惠一刀

因为日常是莞惠跨境通勤,而东莞回惠州一直要 48 小时核酸证明才能回。所以年后开工直至 3 月 13 日截止,一直保持两天一检的频率。当然为了家人和朋友的安全着想,除了麻烦一点,觉得还能接受,毕竟一次混检才 8 元。

然而东莞从 3 月开始,就取消了 8 元混检选项,只能选单检,一次 32.5 元。去东莞的问政网看到也有网友提出疑问,然而官方的回复还是一如既往的打官腔。

2022-03-22T06:07:54.png

  1. 对于当时很多地方而言,没 48 小时核酸根本不给进出,这样如何自愿?
  2. 混检效率低,那大规模核酸干嘛不单检?还是为了减少你们工作量,增加百姓经济负担?
  3. 在医院提出混检,根本没人会理会。

然而根据一些东莞医疗行业的人透露:整个东莞的检测外包给了某些机构,单检才有钱赚,所以不可能会有混检。

看到莞深疫情有爆发的趋势,也做好随时被困在东莞的准备。提前在东莞安排好住的地方,车里也放着行李。

3 月 13 日,惠州那边突然更改政策为 24 小时核酸才能通过关卡。
3 月 14 日,下午的时候接到惠州家所在的街道办和派出所的流调电话,也察觉到不妥。17 点左右突然听到有镇区封闭,禁止出入,这个时候已经无法返回惠州了。
3 月 15 日,早上 10 点,宣布马上停工,东莞这边小区也发通知凭业主卡和 48 小时核酸进入。

开始了为期 6 天的居家隔离,每天重复同样的流程:早上起床吃早餐 —— 楼下散步 —— 排队核酸检测 —— 吃中午饭 —— 睡午觉 —— 起床散步 —— 吃晚饭 —— 散步 —— 睡觉。

3 月 21 日 0 点宣布解封,可以正常上班。

因为当时忘记把笔记本电脑带上,导致隔离那几天没电脑工作,只能每天趁侄女上完网课,借电脑处理下紧急的事。听到解封后,马上开车回惠州拿电脑,也知道不可能给莞深行程码的人过去,就让家人送到关卡那里。

结果关卡的某个人说,东西也不给出去。顿时火气就冒起来了:你们为了防疫不给我们过去,我可以理解,也会配合;但惠州哪条政策说东西不可以离惠?本来车辆和行人都可以离惠,你他妈的给我扯东西不可以离惠?拿鸡毛当令箭上瘾了啊。

然后赶紧改口,不是东西不给离惠,因为关卡分两部分(就如同朝韩停火线中间还空着一段路),如果我家人从第一道卡口出来就不能回去了,他们也不会帮忙拿。最后家人拜托过莞的一辆车帮忙带了过来,虽然就相隔不到一百米的距离。一直以来对惠州防疫的一刀切态度就很看不过眼,防疫政策从上到下层层加码,也不透明,随便发个不带公章的文件就开始给百姓添麻烦保自己乌纱帽。

不经他人苦,莫劝他人善。希望本地论坛的某些傻逼,别叽歪那么多,别给惠州丢脸了。你们安静的享受这些政策下的安宁就好,别盲目的发表一些引起地域矛盾的言论。

盲目跟风

抖音上很多看到一则新闻火了,就盲目去跟风的。

例如:让小孩去给执勤中的军警敬礼的、向防疫人员表达感谢跳舞的等等。

觉得如果军警或防疫人员因为任务原因没回礼,肯定会引出一堆键盘侠。

本来一大堆想吐槽的,但想想,还是算了。人吃饱了,总是事多。

三年的疫情,照出了多少作妖的事和人?

初次自己全责的交通事故

作者 痞子鱼
2021年11月9日 12:10

追尾

上周接到兼职公司的经理通知去公司开会,中午就请好假出发。才上高速不到半个小时,前车的前车不知为何突然急啥车,前车兰酷泽很快刹停了,但我反应不及,感觉才踩紧刹车不到一秒就撞上了。

因为之前车流大,车速不算特别快,原本以为不算很严重的损伤,结果兰酷泽装了个拖车钩,所以我车损伤最大。也没多说什么,打电话给交警、保险公司报案,警示牌摆好,然后赶紧前后拍照,撞击处拍照。原本交警是让我们去最近高速出口交警大队那里处理的,但兰酷泽车主有急事要先走,就互加微信说晚点看怎么处理。只好自己先行去交警大队,但对方车主不在,交警没办法出责任单。

IMG_20210.jpg

IMG_20211.jpg

我也嫌麻烦不愿意等对方车主回来,问了兰酷泽车主大概能回来的时间和保险公司定损员商量过后,既然己方全责,去保险公司定点维修厂的话,不用交警出单都能搞定。于是询问过对方也同意全权委托给保险公司办理,我直接去维修厂开了代步车就回家。

小纠纷

第二天定损的时候,因为兰酷泽装了拖车钩,所以也改装了后包围,他想直接换新的,但保险公司定损认为不严重可以维修。于是就一直打电话想让我个人赔偿,但当时说双方不去交警大队定责,全权交给保险公司的时候,对方也是同意的。现在又不依不饶,破口大骂。

我原本也打算说看保险公司定损后,另外看后包围价格给折旧费的,听到对方这样态度就直接让对方找保险公司,当初双方都答应全权委托保险公司处理的,然后挂电话。

后面也没再打电话来说事。

后续

从出事故到去维修厂拿回自己的车,足足花了一个星期。如果个人有时间,还是建议由交警定责,拿到责任单后再去自己熟悉的维修厂或者 4S 店定损维修的。毕竟保险公司指定的维修厂多少都会有猫腻,例如配件更换成副厂的,该换不换直接维修的,甚至说换件却只维修了等等。

但我也提前跟定损员说过,怎么操作不我管,但该换的一定得换,质量要有保证,后续我会开去其他熟悉的维修厂保养检查的。所以拿回来去检查过后,也只是一些外围配件不算原厂,质量也不算差的,就算完结。

后面导出记录仪的视频回顾了整个事故的过程,应该是自己在车流开始顺畅,提速的过程,看了下导航走神了,另外也没足够的休息时间,大中午太阳最刺眼的时间出发,精神不够集中,导致反应不够及时刹车引起的追尾事故。

所以,开车出门一定要保证自己精神足够清醒,开车过程中集中注意力在前方,尽量减少非必要的左顾右盼。虽然以前也出过一些小刮蹭事故,但都是对方理亏赔三四百就各回各家的,自己全责的还是首次。

Docker 部署 macvlan 网络下的 qBittorrent

作者 痞子鱼
2021年11月8日 11:03

前言

之前 nas 里的 qBittorrent 都是直接部署在 Host 网络模式下,因为可以直接分配到 ipv6,下载很多资源也能看到有 ipv6 用户连接。

不过不知是不是一直使用的“机场”更改了审查规则,还是路由上的 passwall 有问题(passwall一直都是设置成只转发常用端口),导致一些流量被“机场”审查为 BT,账户隔半个小时左右就被中断半个小时。但看“机场”的流量使用情况,也基本符合自己日常看视频的使用量,应该不会有 BT 流量走了代理,猜测是 Tracker 列表问题或者近期更新了 passwall 的原因。

所以干脆把重新部署 qBittorrent 为 macvlan 网络模式,有独立的 mac 地址和 IP,然后 passwall 设置成全部直连。

安装部署

macvlan 网络模式

使用 macvlan 网络模式的好处是容器相当于是一个独立的设备,可以拥有一个独立且固定的 IP 和 MAC 地址,不需要理会任何端口的状态,所有端口都可以使用默认的,兼容性更好。

创建 macvlan 网络(根据实际情况替换参数,并删除注释)

docker network create \
    -d macvlan \ # 使用 macvlan 网络驱动
    --subnet=10.0.0.0/24 \ # 指定网段
    --gateway=10.0.0.1 \ # 指定网关 IP
    -o parent=eth0 \ # 指定网卡
macvlan # 网络名称,随意,自己记得就行

准备服务描述文件 docker-compose.yml:

version: "2.0"
services:
    qbittorrent:
    image: superng6/qbittorrent:latest
    container_name: qbittorrent
    restart: always
    tty: true
    networks: 
        macvlan: #上 面创建的 macvlan 网络名称
    ipv4_address: 10.0.0.99 # 你想设置的ip
    aliases:
        - qbittorrent
    dns:
        - 223.5.5.5
        - 119.29.29.29
    hostname: qbitorrent
    environment:
        - TZ=Asia/Shanghai
        - WEBUI_PORT=8080 # 将此处修改成你欲使用的 WEB 管理平台端口
    volumes:
    - ./data:/data
    restart: unless-stopped 

networks: 
    macvlan: #上 面创建的 macvlan 网络名称
    external: true

与宿主机互通

在 macvlan 网络模式下同网段的其他机器可以和容器互通,但宿主不能和容器互通,这是在macvlan模式设计的时候为了安全而禁止了宿主机和容器直接通信。

如果想要实现互通,有个曲线救国的方法,就是macvlan与macvlan之间可以互通,只需要在宿主机再创建一个 macvlan 网络,然后修改路由,让数据经过这个 macvlan 达到互通的目的。

Hyper-V 设置

nas 主系统是 windows server 2016, Hyper-V 安装 centos,最后 docker 容器都是运行在 centos 下,所以需要在 Hyper-V 把网络适配器的 MAC 地址欺骗打开。

假设现有网段为 10.0.0.0/24 的网络:

名字ip接口
宿主机10.0.0.88eth0
容器10.0.0.99macvlan

建立一个名为 macvlan2 的 macvlan 接口,并分配一个ip:

名字ip接口
macvlan210.0.0.77eth0
ip link add macvlan2 link eth0 type macvlan mode bridge
ip addr add 10.0.0.77 dev macvlan2 
ip link set macvlan2 up

修改路由,让宿主机到容器的数据经过 macvlan2:

ip route add 10.0.0.99 dev macvlan2

访问 ip

宿主机 访问 qBittorrent 容器的 ip:10.0.0.99

qBittorrent 容器访问宿主机ip:10.0.0.77

启动 qBittorrent

docker-compose up -d

重启失效问题

# step1 首先切换到/etc/init.d目录下
cd /etc/init.d

# step 2 vi macvlan.sh 输入要运行的脚本

#!/bin/bash
#chkconfig:  2345 81 96
#description: Starttomcat

ip link add macvlan2 link eth0 type macvlan mode bridge
ip addr add 10.0.0.77 dev macvlan2
ip link set macvlan2 up
ip route add 10.0.0.99 dev macvlan2

# step 3 可执行权限
chmod +x macvlan.sh

# step 4 加入 chkconfig 命令进行管理
chkconfig --add macvlan.sh

# step 5 设置为开机自运行
chkconfig macvlan.sh on

总结

设置完成后,passwall 也设置了 qBittorrent 容器直连,但最后还是在“机场”的审查记录那里查看到偶尔会有 BT 的记录,不过隔很久才会出现一次,对账户也不会中断连接,所以就先忽视吧。

微信推送天气预报

作者 痞子鱼
2021年4月27日 14:34

只是对 GitHub 上的 Weather_Push_PushBear 项目简单的修改为 pushplus 推送和增加推送内容。

pushplus 是什么

pushplus(推送加)集成了微信、企业微信、钉钉、短信、邮件等实时信息推送平台
你只需要调用简单的API,即可帮助你迅速完成消息的推送,使用简单方便
我们的所做的一切只是为了让推送变的更简单

家里路由器的 IP 变化,NAS 的运行情况等等一些小玩意都是用它来推送。不过感觉涉及到一些隐私,以后打算自建 chanify 来推送应该更安全。

简单教程

1、注册 pushplus,扫码登录后进入一对多推送,获取 token

pushplus.jpg

2、创建群组,如果群组编码不是 tianqi,需要替换 push_data.py 里的 topic。

qunzu.jpg

3、注册心知天气网,进入控制台免费版获取私钥,

seniverse.jpg

4、新建四个 python 文档

get_data.py (当前私钥可以试用到5月11日,请及时替换成自己的)

# -*- coding:utf-8 -*-
import requests

class GetData:
    def get_data(self):
        '获取天气原始信息'
        # 获取指定城市未来最多15天每天的白天和夜间预报,以及昨日的历史天气。
        url = "https://api.seniverse.com/v3/weather/daily.json"
        payload = {'key': 'SqMHNTA_SHxE1MR7-', 'location': '',
                   'language': 'zh-Hans', 'unit': 'c', 'start': '0', 'days': ''}
        # 地区参数
        location = "dongguan"
        payload['location'] = location
        #天气预报天数参数
        days = '2'
        payload['days'] = days
        response = requests.get(url, params=payload)
        weather_dict = response.json()
        return weather_dict

extraction_data.py

# -*- coding:utf-8 -*-

class ExtractionData:
    def extraction_data(self, weather_json):
        '从原始Json中抽取有用信息'
        if(weather_json == None):
            return None
        else:
            results_dict = weather_json['results']
            location_dict = results_dict[0]['location']
            daily_dict = results_dict[0]['daily']
            return location_dict, daily_dict

push_data.py (self.token 替换成在 pushplus 的 token)

# -*- coding:utf-8 -*-
import requests


class PushData:
    def push_data(self, location_dict, daily_dict):
        #向微信推送天气消息
        self.url = 'https://www.pushplus.plus/send?'
        self.payload = {'token': '', 'title': '', 'content ': '', 'template ': 'markdown', 'topic': 'tianqi'}
        # 消息推送Key
        self.token = 'f34yy7415gwagtftw312r129f7c'
        self.payload['token'] = self.token
        # 推送消息Title
        self.title = '%s 天气预报' % location_dict['name']
        self.payload['title'] = self.title
        # 推送消息Description
        self.content = '<b># 今日天气</b>\n* 日间最高温度:%s℃,%s\n* 夜间最高温度:%s℃,%s\n* 相对湿度:%s %%  \n* 风向:%s\n* 风力:%s 级\n* 风速:%s KM/H\n\n<b># 明日天气</b>\n* 日间最高温度:%s℃,%s\n* 夜间最高温度:%s℃,%s\n* 相对湿度:%s %% \n* 风向:%s\n* 风力:%s 级\n* 风速:%s KM/H' % (
            daily_dict[0]['high'], daily_dict[0]['text_day'], daily_dict[0]['low'], daily_dict[0]['text_night'], daily_dict[0]['humidity'], daily_dict[0]['wind_direction'], daily_dict[0]['wind_scale'], daily_dict[0]['wind_speed'], daily_dict[1]['high'], daily_dict[1]['text_day'], daily_dict[1]['low'], daily_dict[1]['text_night'], daily_dict[1]['humidity'], daily_dict[1]['wind_direction'], daily_dict[1]['wind_scale'], daily_dict[1]['wind_speed'])
        self.payload['content'] = self.content
        requests.get(self.url, params=self.payload)

main.py

# -*- coding:utf-8 -*-
from get_data import GetData
from extraction_data import ExtractionData
from push_data import PushData

class Main:
    def __init__(self):
        '初始化程序各模块'
        self.get_data = GetData()
        self.extraction_data = ExtractionData()
        self.push_data = PushData()

    def push(self):
        weather_json = self.get_data.get_data()
        location_dict, daily_dict = self.extraction_data.extraction_data(
            weather_json)
        self.push_data.push_data(location_dict, daily_dict)

if __name__ == '__main__':
    main = Main()
    #while True:
    main.push()

5、最后根据心知天气网的更新频率,每天3~4次,那么就在服务器定时每隔6个小时运行 main.py 就可以啦。

tianqi.jpg

tianqi1.jpg

断更的日子

原本刚建立博客的时候,雄心壮志的计划最少都要月更,结果去年至今变成了季更,或者再变成年更了,哈哈。其实主要也是工作时间工作忙,周末时间陪孩子忙,所以近期也没什么好折腾的。

晚上回来要陪他写作业,练轮滑,周末小孩又有画画课,乐高课。现在自己最快乐的时间应该就是小孩睡觉后的那一两个小时的自由时间了。

农村里的幼儿园就是麻烦,才大班已经开始学20以内的加减法,然后写拼音,写汉字,读英语。小孩每天回来最痛苦的时候就是写作业吧。我们夫妻除了数学,其他都没让他一定要按照老师要求写完,也跟老师沟通过,小孩太小不想他写太多字。

跟园长聊天的时候,园长也说过,其实也不想小孩一下学那么多,不过如果不教多点,某些家长就觉得这家幼儿园不好,下一年招生就很难,学生不够就很难维持下去。

❌
❌