diff --git a/CUPS打印服务配置交接文档.md b/CUPS打印服务配置交接文档.md index c789777..516502d 100644 --- a/CUPS打印服务配置交接文档.md +++ b/CUPS打印服务配置交接文档.md @@ -29,6 +29,7 @@ wget -qO- https://git.workyai.cn/237899745/S905L3A/raw/branch/master/setup_cups. - 多种打印机驱动可选(通用/HP/爱普生/兄弟/奔图) - 自动配置远程访问权限 - 安装中文界面模板 +- 安装网络和打印服务守护脚本 --- @@ -39,6 +40,8 @@ wget -qO- https://git.workyai.cn/237899745/S905L3A/raw/branch/master/setup_cups. | CUPS | 631 | 打印服务/Web管理界面 | | Avahi | 5353 | mDNS/AirPrint 自动发现 | | 驱动管理器 | 632 | 内网上传安装打印机驱动(可选) | +| 网络守护 | systemd timer | 断网后自动切换网卡为 DHCP | +| 打印守护 | systemd timer | CUPS 卡死或异常后自动重启恢复 | --- @@ -87,6 +90,10 @@ https://服务器IP:631 | `/etc/cups/ssl/` | SSL 证书目录 | | `/usr/share/cups/templates-zh_CN/` | 中文界面模板 | | `/opt/cups-driver-manager/` | 驱动管理器安装目录(可选) | +| `/opt/cups-watchdog/` | 守护脚本安装目录 | +| `/etc/cups-watchdog/network-watchdog.conf` | 网络守护配置,可设置固定 IP、网关、DNS | +| `/etc/cups-watchdog/print-watchdog.conf` | 打印服务守护配置 | +| `/var/log/cups-watchdog/` | 守护脚本日志目录 | --- @@ -133,6 +140,19 @@ tail -f /var/log/cups/error_log # 检查端口监听 ss -tlnp | grep -E "631|632" + +# 查看守护状态 +systemctl status cups-network-watchdog.timer cups-print-watchdog.timer + +# 手动切 DHCP +/opt/cups-watchdog/network-watchdog.sh dhcp + +# 按配置文件手动切回固定 IP +/opt/cups-watchdog/network-watchdog.sh static + +# 查看守护日志 +tail -f /var/log/cups-watchdog/network.log +tail -f /var/log/cups-watchdog/print.log ``` --- @@ -168,6 +188,13 @@ ls /usr/share/cups/templates-zh_CN/ locale -a | grep zh_CN ``` +### 问题5:网络守护自动切 DHCP 后要切回固定 IP +**解决**: +```bash +nano /etc/cups-watchdog/network-watchdog.conf +/opt/cups-watchdog/network-watchdog.sh static +``` + --- ## 九、文件清单 @@ -175,6 +202,7 @@ locale -a | grep zh_CN ``` /root/yuyx/B863AV3.2M刷Armbian教程/ ├── setup_cups.sh # 一键安装脚本 +├── watchdog/ # 网络和打印服务守护脚本 ├── cups-templates-zh_CN/ # 中文界面模板(65个文件) ├── 刷机教程.md # Armbian 刷机教程 └── CUPS打印服务配置交接文档.md # 本文档 @@ -188,6 +216,8 @@ locale -a | grep zh_CN - [ ] 局域网 macOS/iOS AirPrint 自动发现 - [ ] 局域网 Android Mopria 打印 - [ ] 真实 USB 打印机连接测试 +- [ ] 断网后网络守护自动切 DHCP +- [ ] CUPS 异常后打印守护自动重启恢复 --- diff --git a/Debian12安装教程.md b/Debian12安装教程.md index c2649a1..c87e66d 100644 --- a/Debian12安装教程.md +++ b/Debian12安装教程.md @@ -355,6 +355,7 @@ df -h - [ ] `apt update` 正常工作 - [ ] 运行 CUPS 安装脚本成功 - [ ] 浏览器能打开 https://IP:631 +- [ ] `cups-network-watchdog.timer` 和 `cups-print-watchdog.timer` 已启用 --- diff --git a/README.md b/README.md index e91e0e1..2584958 100644 --- a/README.md +++ b/README.md @@ -11,6 +11,7 @@ - 虚拟 PDF 打印机(测试连接用) - 多种打印机驱动可选 - 驱动管理器(默认仅允许内网访问) +- 网络和打印服务守护(断网自动切 DHCP,CUPS 卡死自动恢复) - 支持一键卸载 ## 快速安装 @@ -76,6 +77,34 @@ chmod +x setup_cups.sh | Avahi | 5353 | mDNS/AirPrint 自动发现 | | 驱动管理器 | 632 | 内网上传安装打印机驱动(可选) | +## 自动守护 + +安装脚本会自动启用两个 systemd timer: + +| 守护 | 作用 | +|------|------| +| `cups-network-watchdog.timer` | 每分钟检测网络,连续失败后自动把网卡切回 DHCP | +| `cups-print-watchdog.timer` | 每分钟检测 CUPS/Avahi/驱动管理器,卡死或异常后自动重启 | + +配置文件: + +```bash +# 网络守护配置,可在里面设置固定 IP、网关、DNS +nano /etc/cups-watchdog/network-watchdog.conf + +# 手动切回配置里的固定 IP +/opt/cups-watchdog/network-watchdog.sh static + +# 手动切 DHCP +/opt/cups-watchdog/network-watchdog.sh dhcp + +# 打印服务守护配置 +nano /etc/cups-watchdog/print-watchdog.conf + +# 查看守护状态 +systemctl status cups-network-watchdog.timer cups-print-watchdog.timer +``` + ## 常用命令 ```bash @@ -88,6 +117,10 @@ systemctl restart cups # 查看 CUPS 日志 tail -f /var/log/cups/error_log +# 查看守护脚本日志 +tail -f /var/log/cups-watchdog/network.log +tail -f /var/log/cups-watchdog/print.log + # 检查 USB 打印机 lsusb | grep -i print lpinfo -v | grep usb @@ -103,6 +136,7 @@ lpinfo -v | grep usb ``` ├── setup_cups.sh # 一键安装/卸载脚本 +├── watchdog/ # 网络和打印服务守护脚本 ├── cups-templates-zh_CN/ # 中文界面模板(65个文件) ├── README.md # 本文档 └── 刷机教程.md # Armbian 刷机教程 diff --git a/setup_cups.sh b/setup_cups.sh index d4fac1f..8102e7f 100755 --- a/setup_cups.sh +++ b/setup_cups.sh @@ -1109,6 +1109,109 @@ EOF DRIVER_MANAGER_PASSWORD="$admin_pass" } +# 安装网络和打印服务守护脚本 +install_watchdogs() { + info "安装 CUPS 守护脚本..." + + apt install -y iproute2 iputils-ping curl 2>/dev/null || warn "守护脚本依赖安装失败,继续尝试使用系统已有命令" + + local install_dir="/opt/cups-watchdog" + local config_dir="/etc/cups-watchdog" + local log_dir="/var/log/cups-watchdog" + local source_dir="" + local tmp_dir="" + + mkdir -p "$install_dir" "$config_dir" "$log_dir" + + SCRIPT_DIR="$(cd "$(dirname "$0")" 2>/dev/null && pwd)" || SCRIPT_DIR="" + + if [ -n "$SCRIPT_DIR" ] && [ -d "$SCRIPT_DIR/watchdog" ]; then + source_dir="$SCRIPT_DIR/watchdog" + info "从本地复制守护脚本" + else + info "从仓库下载守护脚本..." + tmp_dir=$(mktemp -d) + if download_repo_archive "$tmp_dir/repo.zip"; then + unzip -q "$tmp_dir/repo.zip" -d "$tmp_dir" 2>/dev/null + source_dir=$(find "$tmp_dir" -type d -name "watchdog" 2>/dev/null | head -1) + fi + fi + + if [ -z "$source_dir" ] || [ ! -d "$source_dir" ]; then + [ -n "$tmp_dir" ] && rm -rf "$tmp_dir" + warn "未找到守护脚本目录,跳过安装" + return 1 + fi + + cp -f "$source_dir/network-watchdog.sh" "$install_dir/" + cp -f "$source_dir/print-watchdog.sh" "$install_dir/" + chmod +x "$install_dir/network-watchdog.sh" "$install_dir/print-watchdog.sh" + + cp -f "$source_dir/cups-network-watchdog.service" /etc/systemd/system/ + cp -f "$source_dir/cups-network-watchdog.timer" /etc/systemd/system/ + cp -f "$source_dir/cups-print-watchdog.service" /etc/systemd/system/ + cp -f "$source_dir/cups-print-watchdog.timer" /etc/systemd/system/ + + [ -n "$tmp_dir" ] && rm -rf "$tmp_dir" + + local current_ip=$(get_ip) + local current_gateway=$(get_gateway) + local current_interface=$(get_interface) + local current_netmask=$(get_netmask) + local current_dns=$(get_dns) + current_dns="${current_dns:-114.114.114.114 223.5.5.5}" + + local ping_targets="223.5.5.5 114.114.114.114" + if [ -n "$current_gateway" ]; then + ping_targets="$current_gateway $ping_targets" + fi + + if [ ! -f "$config_dir/network-watchdog.conf" ]; then + cat > "$config_dir/network-watchdog.conf" << EOF +# CUPS network watchdog config. +# Edit these values when you want to manually switch back to a fixed IP: +# /opt/cups-watchdog/network-watchdog.sh static +INTERFACE="$current_interface" +STATIC_IP="$current_ip" +STATIC_PREFIX="$current_netmask" +STATIC_GATEWAY="$current_gateway" +STATIC_DNS="$current_dns" +PING_TARGETS="$ping_targets" +FAIL_THRESHOLD=3 +DHCP_AFTER_FAILURE=1 +LOG_FILE="/var/log/cups-watchdog/network.log" +EOF + chmod 600 "$config_dir/network-watchdog.conf" + else + info "保留现有网络守护配置: $config_dir/network-watchdog.conf" + fi + + if [ ! -f "$config_dir/print-watchdog.conf" ]; then + cat > "$config_dir/print-watchdog.conf" << EOF +# CUPS print watchdog config. +SERVICES="cups avahi-daemon cups-driver-manager" +CUPS_URL="http://127.0.0.1:631/" +CHECK_CUPS_HTTP=1 +CHECK_LPSTAT=1 +COMMAND_TIMEOUT=8 +FAIL_THRESHOLD=2 +RESTART_COOLDOWN=60 +LOG_FILE="/var/log/cups-watchdog/print.log" +EOF + chmod 600 "$config_dir/print-watchdog.conf" + else + info "保留现有打印守护配置: $config_dir/print-watchdog.conf" + fi + + systemctl daemon-reload + systemctl enable --now cups-network-watchdog.timer + systemctl enable --now cups-print-watchdog.timer + + success "守护脚本安装完成" + info "网络守护配置: $config_dir/network-watchdog.conf" + info "打印守护配置: $config_dir/print-watchdog.conf" +} + # 安装虚拟PDF打印机(用于测试连接) install_pdf_printer() { info "安装虚拟 PDF 打印机..." @@ -1333,6 +1436,8 @@ main() { ((step++)) fi echo " $step. 启动并设置开机自启" + ((step++)) + echo " $step. 安装网络和打印服务守护脚本" echo "" read -p "是否继续? [Y/n]: " confirm < /dev/tty confirm=${confirm:-Y} @@ -1425,6 +1530,9 @@ main() { systemctl enable avahi-daemon success "Avahi 服务已启动并设置开机自启" + # 8. 安装守护脚本 + install_watchdogs + # 更新IP地址(如果配置了静态IP) LOCAL_IP=$(get_ip) @@ -1463,6 +1571,13 @@ main() { echo -e " ${GREEN} ${NC} PDF 输出目录: /var/spool/cups-pdf/" echo "" fi + if systemctl is-enabled --quiet cups-network-watchdog.timer 2>/dev/null && \ + systemctl is-enabled --quiet cups-print-watchdog.timer 2>/dev/null; then + echo -e " ${GREEN}[守护脚本]${NC} 已启用网络和打印服务自动恢复" + echo -e " ${GREEN} ${NC} 配置目录: /etc/cups-watchdog/" + echo -e " ${GREEN} ${NC} 日志目录: /var/log/cups-watchdog/" + echo "" + fi echo -e " ${YELLOW}下一步:${NC}" echo " 1. 用浏览器打开上面的地址" if lpstat -p PDF 2>/dev/null | grep -q "PDF"; then @@ -1508,6 +1623,7 @@ uninstall() { echo " - CUPS-PDF 虚拟打印机" echo " - 中文界面模板" echo " - 驱动管理器" + echo " - 网络和打印服务守护脚本" echo " - 所有打印任务和配置" echo "" read -p "确定要卸载吗? [y/N]: " confirm < /dev/tty @@ -1526,9 +1642,13 @@ uninstall() { systemctl stop cups 2>/dev/null || true systemctl stop avahi-daemon 2>/dev/null || true systemctl stop cups-driver-manager 2>/dev/null || true + systemctl stop cups-network-watchdog.timer cups-network-watchdog.service 2>/dev/null || true + systemctl stop cups-print-watchdog.timer cups-print-watchdog.service 2>/dev/null || true systemctl disable cups 2>/dev/null || true systemctl disable avahi-daemon 2>/dev/null || true systemctl disable cups-driver-manager 2>/dev/null || true + systemctl disable cups-network-watchdog.timer 2>/dev/null || true + systemctl disable cups-print-watchdog.timer 2>/dev/null || true # 卸载软件包 info "卸载软件包..." @@ -1546,7 +1666,14 @@ uninstall() { rm -rf /usr/share/cups/templates-zh rm -rf /usr/share/cups/templates-en-backup rm -rf /opt/cups-driver-manager + rm -rf /opt/cups-watchdog + rm -rf /etc/cups-watchdog + rm -rf /var/log/cups-watchdog rm -f /etc/systemd/system/cups-driver-manager.service + rm -f /etc/systemd/system/cups-network-watchdog.service + rm -f /etc/systemd/system/cups-network-watchdog.timer + rm -f /etc/systemd/system/cups-print-watchdog.service + rm -f /etc/systemd/system/cups-print-watchdog.timer systemctl daemon-reload 2>/dev/null || true # 清理依赖 diff --git a/watchdog/cups-network-watchdog.service b/watchdog/cups-network-watchdog.service new file mode 100644 index 0000000..64dd3aa --- /dev/null +++ b/watchdog/cups-network-watchdog.service @@ -0,0 +1,8 @@ +[Unit] +Description=CUPS network watchdog +After=network-online.target +Wants=network-online.target + +[Service] +Type=oneshot +ExecStart=/opt/cups-watchdog/network-watchdog.sh check diff --git a/watchdog/cups-network-watchdog.timer b/watchdog/cups-network-watchdog.timer new file mode 100644 index 0000000..ab54318 --- /dev/null +++ b/watchdog/cups-network-watchdog.timer @@ -0,0 +1,11 @@ +[Unit] +Description=Run CUPS network watchdog every minute + +[Timer] +OnBootSec=2min +OnUnitActiveSec=1min +AccuracySec=15s +Persistent=true + +[Install] +WantedBy=timers.target diff --git a/watchdog/cups-print-watchdog.service b/watchdog/cups-print-watchdog.service new file mode 100644 index 0000000..bc6adbb --- /dev/null +++ b/watchdog/cups-print-watchdog.service @@ -0,0 +1,8 @@ +[Unit] +Description=CUPS print service watchdog +After=cups.service +Wants=cups.service + +[Service] +Type=oneshot +ExecStart=/opt/cups-watchdog/print-watchdog.sh check diff --git a/watchdog/cups-print-watchdog.timer b/watchdog/cups-print-watchdog.timer new file mode 100644 index 0000000..f71c97e --- /dev/null +++ b/watchdog/cups-print-watchdog.timer @@ -0,0 +1,11 @@ +[Unit] +Description=Run CUPS print service watchdog every minute + +[Timer] +OnBootSec=2min +OnUnitActiveSec=1min +AccuracySec=15s +Persistent=true + +[Install] +WantedBy=timers.target diff --git a/watchdog/network-watchdog.sh b/watchdog/network-watchdog.sh new file mode 100644 index 0000000..9a4e35c --- /dev/null +++ b/watchdog/network-watchdog.sh @@ -0,0 +1,275 @@ +#!/bin/bash +# +# Network watchdog for the CUPS print server. +# Default behavior: when connectivity checks fail repeatedly, switch the +# configured interface back to DHCP so the box can regain network access. +# +# Edit /etc/cups-watchdog/network-watchdog.conf to set STATIC_IP, +# STATIC_PREFIX, STATIC_GATEWAY and STATIC_DNS. You can also run: +# /opt/cups-watchdog/network-watchdog.sh static +# /opt/cups-watchdog/network-watchdog.sh dhcp +# + +set -u + +CONFIG_FILE="${CUPS_NETWORK_WATCHDOG_CONFIG:-/etc/cups-watchdog/network-watchdog.conf}" +STATE_DIR="/run/cups-watchdog" + +INTERFACE="" +STATIC_IP="" +STATIC_PREFIX="24" +STATIC_GATEWAY="" +STATIC_DNS="114.114.114.114 223.5.5.5" +PING_TARGETS="223.5.5.5 114.114.114.114" +FAIL_THRESHOLD=3 +DHCP_AFTER_FAILURE=1 +LOG_FILE="/var/log/cups-watchdog/network.log" + +if [ -f "$CONFIG_FILE" ]; then + # shellcheck disable=SC1090 + . "$CONFIG_FILE" +fi + +mkdir -p "$STATE_DIR" +mkdir -p "$(dirname "$LOG_FILE")" 2>/dev/null || true + +log_msg() { + local msg="$1" + local line + line="$(date '+%Y-%m-%d %H:%M:%S') [network-watchdog] $msg" + echo "$line" + echo "$line" >> "$LOG_FILE" 2>/dev/null || true +} + +detect_interface() { + if [ -n "${INTERFACE:-}" ] && ip link show "$INTERFACE" >/dev/null 2>&1; then + echo "$INTERFACE" + return 0 + fi + + ip route show default 2>/dev/null | awk '{print $5; exit}' +} + +nm_connection_for_interface() { + local iface="$1" + nmcli -t -f NAME,DEVICE con show --active 2>/dev/null | awk -F: -v iface="$iface" '$2 == iface {print $1; exit}' +} + +configure_dhcp_nmcli() { + local iface="$1" + local conn + conn="$(nm_connection_for_interface "$iface")" + [ -n "$conn" ] || conn="$iface" + + nmcli con mod "$conn" ipv4.method auto ipv4.addresses "" ipv4.gateway "" ipv4.dns "" >/dev/null + nmcli con down "$conn" >/dev/null 2>&1 || true + nmcli con up "$conn" >/dev/null +} + +configure_dhcp_netplan() { + local iface="$1" + local target_file="/etc/netplan/99-cups-watchdog-dhcp.yaml" + + cat > "$target_file" << EOF +# DHCP recovery config generated by cups network watchdog. +network: + version: 2 + renderer: networkd + ethernets: + $iface: + dhcp4: yes +EOF + chmod 600 "$target_file" + rm -f /etc/netplan/01-static-ip.yaml /etc/netplan/99-cups-static-ip.yaml /etc/netplan/99-cups-watchdog-static.yaml 2>/dev/null || true + netplan apply +} + +configure_dhcp_interfaces() { + local iface="$1" + + if [ -f /etc/network/interfaces ]; then + cp /etc/network/interfaces /etc/network/interfaces.cups-watchdog.bak + fi + + cat > /etc/network/interfaces << EOF +# DHCP recovery config generated by cups network watchdog. +auto lo +iface lo inet loopback + +auto $iface +iface $iface inet dhcp +EOF + systemctl restart networking 2>/dev/null || /etc/init.d/networking restart 2>/dev/null || true +} + +configure_dhcp() { + local iface + iface="$(detect_interface)" + if [ -z "$iface" ]; then + log_msg "cannot switch to DHCP: network interface not found" + return 1 + fi + + log_msg "switching $iface to DHCP" + if command -v nmcli >/dev/null 2>&1 && systemctl is-active --quiet NetworkManager 2>/dev/null; then + configure_dhcp_nmcli "$iface" + elif [ -d /etc/netplan ] && command -v netplan >/dev/null 2>&1; then + configure_dhcp_netplan "$iface" + else + configure_dhcp_interfaces "$iface" + fi +} + +configure_static_nmcli() { + local iface="$1" + local conn + conn="$(nm_connection_for_interface "$iface")" + [ -n "$conn" ] || conn="$iface" + + nmcli con mod "$conn" ipv4.method manual ipv4.addresses "$STATIC_IP/$STATIC_PREFIX" ipv4.gateway "$STATIC_GATEWAY" ipv4.dns "$STATIC_DNS" >/dev/null + nmcli con down "$conn" >/dev/null 2>&1 || true + nmcli con up "$conn" >/dev/null +} + +configure_static_netplan() { + local iface="$1" + local target_file="/etc/netplan/99-cups-watchdog-static.yaml" + local dns_list="" + local d + + for d in $STATIC_DNS; do + dns_list="$dns_list, $d" + done + dns_list="${dns_list#, }" + + cat > "$target_file" << EOF +# Static network config generated by cups network watchdog. +network: + version: 2 + renderer: networkd + ethernets: + $iface: + dhcp4: no + addresses: + - $STATIC_IP/$STATIC_PREFIX + routes: + - to: default + via: $STATIC_GATEWAY + nameservers: + addresses: [$dns_list] +EOF + chmod 600 "$target_file" + rm -f /etc/netplan/01-dhcp.yaml /etc/netplan/99-cups-dhcp.yaml /etc/netplan/99-cups-watchdog-dhcp.yaml 2>/dev/null || true + netplan apply +} + +configure_static_interfaces() { + local iface="$1" + local netmask="255.255.255.0" + + case "$STATIC_PREFIX" in + 8) netmask="255.0.0.0" ;; + 16) netmask="255.255.0.0" ;; + 24) netmask="255.255.255.0" ;; + 25) netmask="255.255.255.128" ;; + 26) netmask="255.255.255.192" ;; + 27) netmask="255.255.255.224" ;; + 28) netmask="255.255.255.240" ;; + 29) netmask="255.255.255.248" ;; + 30) netmask="255.255.255.252" ;; + esac + + if [ -f /etc/network/interfaces ]; then + cp /etc/network/interfaces /etc/network/interfaces.cups-watchdog.bak + fi + + cat > /etc/network/interfaces << EOF +# Static network config generated by cups network watchdog. +auto lo +iface lo inet loopback + +auto $iface +iface $iface inet static + address $STATIC_IP + netmask $netmask + gateway $STATIC_GATEWAY + dns-nameservers $STATIC_DNS +EOF + systemctl restart networking 2>/dev/null || /etc/init.d/networking restart 2>/dev/null || true +} + +configure_static() { + local iface + iface="$(detect_interface)" + + if [ -z "$iface" ]; then + log_msg "cannot switch to static: network interface not found" + return 1 + fi + + if [ -z "${STATIC_IP:-}" ] || [ -z "${STATIC_GATEWAY:-}" ]; then + log_msg "cannot switch to static: STATIC_IP or STATIC_GATEWAY is empty in $CONFIG_FILE" + return 1 + fi + + log_msg "switching $iface to static $STATIC_IP/$STATIC_PREFIX" + if command -v nmcli >/dev/null 2>&1 && systemctl is-active --quiet NetworkManager 2>/dev/null; then + configure_static_nmcli "$iface" + elif [ -d /etc/netplan ] && command -v netplan >/dev/null 2>&1; then + configure_static_netplan "$iface" + else + configure_static_interfaces "$iface" + fi +} + +connectivity_ok() { + local target + + for target in $PING_TARGETS; do + [ -n "$target" ] || continue + if ping -c 1 -W 2 "$target" >/dev/null 2>&1; then + return 0 + fi + done + + return 1 +} + +check_network() { + local count_file="$STATE_DIR/network.fail_count" + local fail_count=0 + + if connectivity_ok; then + echo 0 > "$count_file" + log_msg "connectivity ok" + return 0 + fi + + if [ -f "$count_file" ]; then + fail_count="$(cat "$count_file" 2>/dev/null || echo 0)" + fi + fail_count=$((fail_count + 1)) + echo "$fail_count" > "$count_file" + + log_msg "connectivity failed ($fail_count/$FAIL_THRESHOLD)" + if [ "$fail_count" -ge "$FAIL_THRESHOLD" ] && [ "$DHCP_AFTER_FAILURE" = "1" ]; then + configure_dhcp + echo 0 > "$count_file" + fi +} + +case "${1:-check}" in + check) + check_network + ;; + dhcp) + configure_dhcp + ;; + static) + configure_static + ;; + *) + echo "Usage: $0 [check|dhcp|static]" + exit 2 + ;; +esac diff --git a/watchdog/print-watchdog.sh b/watchdog/print-watchdog.sh new file mode 100644 index 0000000..417a65b --- /dev/null +++ b/watchdog/print-watchdog.sh @@ -0,0 +1,162 @@ +#!/bin/bash +# +# Print service watchdog for the CUPS print server. +# It checks systemd service state plus quick CUPS command/HTTP probes. +# When checks fail repeatedly, it restarts CUPS and related services. +# + +set -u + +CONFIG_FILE="${CUPS_PRINT_WATCHDOG_CONFIG:-/etc/cups-watchdog/print-watchdog.conf}" +STATE_DIR="/run/cups-watchdog" + +SERVICES="cups avahi-daemon cups-driver-manager" +CUPS_URL="http://127.0.0.1:631/" +CHECK_CUPS_HTTP=1 +CHECK_LPSTAT=1 +COMMAND_TIMEOUT=8 +FAIL_THRESHOLD=2 +RESTART_COOLDOWN=60 +LOG_FILE="/var/log/cups-watchdog/print.log" + +if [ -f "$CONFIG_FILE" ]; then + # shellcheck disable=SC1090 + . "$CONFIG_FILE" +fi + +mkdir -p "$STATE_DIR" +mkdir -p "$(dirname "$LOG_FILE")" 2>/dev/null || true + +log_msg() { + local msg="$1" + local line + line="$(date '+%Y-%m-%d %H:%M:%S') [print-watchdog] $msg" + echo "$line" + echo "$line" >> "$LOG_FILE" 2>/dev/null || true +} + +unit_exists() { + local service="$1" + + systemctl list-unit-files --no-legend "$service.service" 2>/dev/null | awk '{print $1}' | grep -qx "$service.service" && return 0 + systemctl list-units --all --no-legend "$service.service" 2>/dev/null | awk '{print $1}' | grep -qx "$service.service" +} + +service_should_check() { + local service="$1" + + unit_exists "$service" || return 1 + if systemctl is-enabled --quiet "$service.service" 2>/dev/null; then + return 0 + fi + if systemctl is-active --quiet "$service.service" 2>/dev/null; then + return 0 + fi + + return 1 +} + +check_systemd_services() { + local service + local failed=0 + + for service in $SERVICES; do + service_should_check "$service" || continue + if ! systemctl is-active --quiet "$service.service" 2>/dev/null; then + log_msg "service not active: $service" + failed=1 + fi + done + + return "$failed" +} + +check_lpstat() { + [ "$CHECK_LPSTAT" = "1" ] || return 0 + command -v lpstat >/dev/null 2>&1 || return 0 + + timeout "$COMMAND_TIMEOUT" lpstat -r >/dev/null 2>&1 +} + +check_http() { + [ "$CHECK_CUPS_HTTP" = "1" ] || return 0 + command -v curl >/dev/null 2>&1 || return 0 + + curl -fsS --max-time "$COMMAND_TIMEOUT" "$CUPS_URL" >/dev/null 2>&1 +} + +restart_print_stack() { + local now + local last_file="$STATE_DIR/print.last_restart" + local last=0 + local service + + now="$(date +%s)" + if [ -f "$last_file" ]; then + last="$(cat "$last_file" 2>/dev/null || echo 0)" + fi + + if [ $((now - last)) -lt "$RESTART_COOLDOWN" ]; then + log_msg "restart skipped: cooldown active" + return 0 + fi + + log_msg "restarting print stack" + systemctl reset-failed cups.service >/dev/null 2>&1 || true + systemctl restart cups.service + + for service in avahi-daemon cups-driver-manager; do + service_should_check "$service" || continue + systemctl reset-failed "$service.service" >/dev/null 2>&1 || true + systemctl restart "$service.service" >/dev/null 2>&1 || true + done + + echo "$now" > "$last_file" +} + +check_print_stack() { + local count_file="$STATE_DIR/print.fail_count" + local fail_count=0 + local failed=0 + + check_systemd_services || failed=1 + if ! check_lpstat; then + log_msg "lpstat check failed or timed out" + failed=1 + fi + if ! check_http; then + log_msg "CUPS HTTP check failed or timed out" + failed=1 + fi + + if [ "$failed" = "0" ]; then + echo 0 > "$count_file" + log_msg "print stack ok" + return 0 + fi + + if [ -f "$count_file" ]; then + fail_count="$(cat "$count_file" 2>/dev/null || echo 0)" + fi + fail_count=$((fail_count + 1)) + echo "$fail_count" > "$count_file" + + log_msg "print stack failed ($fail_count/$FAIL_THRESHOLD)" + if [ "$fail_count" -ge "$FAIL_THRESHOLD" ]; then + restart_print_stack + echo 0 > "$count_file" + fi +} + +case "${1:-check}" in + check) + check_print_stack + ;; + restart) + restart_print_stack + ;; + *) + echo "Usage: $0 [check|restart]" + exit 2 + ;; +esac diff --git a/刷机教程.md b/刷机教程.md index cb0bc9f..46ea018 100644 --- a/刷机教程.md +++ b/刷机教程.md @@ -221,6 +221,7 @@ curl -fsSL https://git.workyai.cn/237899745/S905L3A/raw/branch/master/setup_cups - 交互式选择打印机驱动 - 自动配置局域网访问权限 - 自动启动服务并设置开机自启 +- 自动安装网络和打印服务守护脚本 - 检测 USB 打印机连接状态 > 如果想手动安装,请继续阅读以下步骤。