首页
留言板
统计
推荐
百度一下
Search
1
关于
56 阅读
2
飞牛NAS的ping命令脚本,自动检查网络是否通断来关机,一般配合UPS使用
55 阅读
3
Windows 10 22H2官方原版 + LTSC_2021_集成25年7月最新补丁
24 阅读
4
Windows 7 旗舰版 专业版 企业版 + Server2008R2DataCenter 7合1 最终收藏版
23 阅读
5
win7系统无法更新,报错80072EFE,解决办法
21 阅读
默认分类
资源分享
技能分享
登录
Search
Zrest's Blog
累计撰写
9
篇文章
累计收到
0
条评论
首页
栏目
默认分类
资源分享
技能分享
页面
留言板
统计
推荐
百度一下
搜索到
2
篇与
的结果
2025-08-06
飞牛NAS的ping命令脚本,自动检查网络是否通断来关机,一般配合UPS使用
飞牛NAS Ping命令监控关机脚本部署指南 步骤1:创建脚本文件 登录飞牛NAS的SSH(确保已启用SSH访问) 飞牛的系统设置里,设置SSH开启。 在 Windows 上连接飞牛 NAS 的 SSH 详细指南 使用 Windows PowerShell(内置工具,无需安装) 打开 PowerShell(或者CMD): 按 Win + R 输入 powershell(或者CMD) 回车 或者在开始菜单搜索 "PowerShell" 并打开 连接 SSH: powershell ssh 用户名@NAS的IP地址 例如: powershell ssh admin@192.168.1.100 (其中admin改成你自己的飞牛NAS账号) 首次连接确认: 输入 yes 接受主机密钥 输入密码: 输入您在飞牛NAS上设置的密码(输入时不会显示字符) 成功连接: 看到类似 admin@freenas:~ $ 的提示符表示连接成功 接下来的命令都在powershell(或者CMD)中链接飞牛SSH后输入: 1.创建脚本目录(默认创建在飞牛文件管理中的app文件夹里): CMD: sudo mkdir -p /vol1/1000/app/ping_monitor sudo chown -R $(whoami) /vol1/1000/app/ping_monitor 2.创建脚本文件: CMD: nano /vol1/1000/app/ping_monitor/ping_monitor.sh 3.将脚本完整内容粘贴到文件中(或者可以直接在飞牛的文件里搜索ping_monitor.sh,找到它写入代码,代码在本文章最下面) 4.保存文件(Ctrl+O,回车,Ctrl+X) 步骤2:设置脚本权限 CMD: chmod +x /vol1/1000/app/ping_monitor/ping_monitor.sh 步骤3:安装必要依赖(可以跳过不装) CMD: sudo apt update sudo apt install jq -y # 安装JSON处理工具 步骤4:配置脚本参数(可选) 编辑脚本文件修改以下参数: CMD: nano /vol1/1000/app/ping_monitor/ping_monitor.sh 需要关注的配置项(最下面代码的内容): ping_monitor.sh: TARGET_IP="192.168.0.1" # 修改为您的路由器IP MAX_FAILURES=10 # 连续失败次数阈值(默认10次) MIN_UPTIME=300 # 最小运行时间(默认300秒=5分钟) SHUTDOWN_DELAY=15 # 关机前等待时间(默认15秒) 步骤5:设置定时任务 编辑crontab: CMD: crontab -e 添加以下行(意思是每分钟运行一次ping_monitor.sh): CMD: * * * * * /vol1/1000/app/ping_monitor/ping_monitor.sh 保存退出(Ctrl+O,回车,Ctrl+X) 步骤6:测试脚本 手动运行脚本: CMD: /vol1/1000/app/ping_monitor/ping_monitor.sh 检查日志: CMD: tail -f /vol1/1000/app/ping_monitor/logs/ping_monitor.log 正常输出应类似: text 2025-07-02 10:30:45 - INFO - ===== Ping监控启动 ===== 2025-07-02 10:30:45 - INFO - 系统运行时间: 12345s 2025-07-02 10:30:45 - INFO - 目标IP: 192.168.0.1, 最大失败次数: 10 2025-07-02 10:30:45 - INFO - 当前失败计数: 0 2025-07-02 10:30:45 - INFO - 状态更新完成。下次检查在1分钟后。 这个代码里的通知功能没有用,无法通知,运行的具体的信息都能在LOG日志里面找到。 ping_monitor.sh:# Ping监控关机脚本 for 飞牛NAS(防止开机死循环) - 优化版 # 配置参数 TARGET_IP="192.168.0.1" # 监控的目标IP(修改为您的路由器IP) MAX_FAILURES=10 # 连续失败次数阈值 MIN_UPTIME=300 # 最小运行时间(秒)300秒=5分钟 SHUTDOWN_DELAY=15 # 关机前等待时间(秒) LOG_DIR="/vol1/1000/app/ping_monitor/logs" DATA_FILE="/vol1/1000/app/ping_monitor/ping_failure_count.json" LOCK_FILE="/vol1/1000/app/ping_monitor/.shutdown_lock" LOG_FILE="$LOG_DIR/ping_monitor.log" MAX_LOG_SIZE=2048576 # 最大日志大小(1MB) MAX_LOG_FILES=5 # 保留的历史日志文件数量 # 确保目录存在 mkdir -p "$LOG_DIR" || { echo "无法创建日志目录: $LOG_DIR" >&2 exit 1 } # 日志轮转函数 rotate_logs() { [ -f "$LOG_FILE" ] || return 0 # 检查日志大小 local log_size=$(wc -c < "$LOG_FILE" 2>/dev/null) [ -z "$log_size" ] && log_size=0 if [ "$log_size" -ge "$MAX_LOG_SIZE" ]; then # 删除最旧的日志文件 local oldest_log="${LOG_FILE}.${MAX_LOG_FILES}" [ -f "$oldest_log" ] && rm -f "$oldest_log" # 轮转日志文件 for i in $(seq $((MAX_LOG_FILES-1)) -1 1); do local src="${LOG_FILE}.${i}" local dest="${LOG_FILE}.$((i+1))" [ -f "$src" ] && mv -f "$src" "$dest" done # 移动当前日志 mv -f "$LOG_FILE" "${LOG_FILE}.1" # 创建新日志文件 echo "日志轮转完成于 $(date)" > "$LOG_FILE" fi } # 日志记录函数 log() { local level=$1 local message=$2 local timestamp=$(date "+%Y-%m-%d %H:%M:%S") # 安全地轮转日志 rotate_logs 2>/dev/null # 写入日志 echo -e "${timestamp} - ${level} - ${message}" >> "$LOG_FILE" 2>/dev/null } # 发送通知函数 send_notification() { local title=$1 local message=$2 # 方法1: 使用飞牛官方通知API if command -v fn_notify &>/dev/null; then fn_notify -t "$title" -m "$message" -p high >/dev/null 2>&1 && return 0 fi # 方法2: 使用DBus发送通知 if command -v dbus-send &>/dev/null; then dbus-send --session --dest=org.freedesktop.Notifications \ --type=method_call /org/freedesktop/Notifications \ org.freedesktop.Notifications.Notify \ string:"Ping Monitor" uint32:0 string:"" \ string:"$title" string:"$message" \ array:string:"" dict:string:string:"" int32:5000 >/dev/null 2>&1 && return 0 fi # 方法3: 尝试使用curl发送通知(如果API可用) if command -v curl &>/dev/null; then curl -s -X POST -H "Content-Type: application/json" \ -d "{\"title\":\"$title\", \"message\":\"$message\", \"priority\":\"high\"}" \ http://localhost:3040/api/notification >/dev/null 2>&1 && return 0 fi log "WARNING" "无法发送通知: $title - $message" return 1 } # Ping检测函数 ping_ip() { # 使用不同的ping工具以适应不同环境 if command -v ping &>/dev/null; then ping -c 2 -W 5 "$TARGET_IP" > /dev/null 2>&1 elif command -v busybox &>/dev/null; then busybox ping -c 2 -W 5 "$TARGET_IP" > /dev/null 2>&1 else log "ERROR" "未找到ping命令!" return 1 fi return $? } # 获取系统运行时间(秒) get_uptime() { cut -d' ' -f1 /proc/uptime | cut -d. -f1 } # 增强版加载失败次数 load_failure_count() { [ -f "$DATA_FILE" ] || return 0 # 安全读取JSON文件 local json_data=$(<"$DATA_FILE") [ -z "$json_data" ] && return 0 # 使用多种方法解析JSON local count last_update last_ip # 方法1: 使用jq if command -v jq &>/dev/null; then count=$(jq -r '.count' <<< "$json_data" 2>/dev/null) last_update=$(jq -r '.last_update' <<< "$json_data" 2>/dev/null) last_ip=$(jq -r '.last_ip' <<< "$json_data" 2>/dev/null) fi # 方法2: 使用grep/awk(备用方法) if [ -z "$count" ] || [ -z "$last_update" ] || [ -z "$last_ip" ]; then count=$(grep '"count"' "$DATA_FILE" | awk -F': ' '{print $2}' | tr -d ', ') last_update=$(grep '"last_update"' "$DATA_FILE" | awk -F': ' '{print $2}' | tr -d ', ') last_ip=$(grep '"last_ip"' "$DATA_FILE" | awk -F': ' '{print $2}' | tr -d '" ,') fi # 验证数据 [[ "$count" =~ ^[0-9]+$ ]] || count=0 [[ "$last_update" =~ ^[0-9]+$ ]] || last_update=0 [[ "$last_ip" =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$ ]] || last_ip="" local current_time=$(date +%s) # 检查是否超过24小时或IP改变 if [ "$last_ip" != "$TARGET_IP" ] || \ [ $((current_time - last_update)) -gt 86400 ]; then log "INFO" "重置计数器 (IP变更或超过24小时)" echo 0 return fi echo "$count" } # 增强版保存失败次数 save_failure_count() { local count=$1 local current_time=$(date +%s) # 创建临时文件 local temp_file="${DATA_FILE}.tmp.$$" # 构建JSON数据 cat > "$temp_file" <<EOF { "count": $count, "last_update": $current_time, "last_ip": "$TARGET_IP" } EOF # 验证并移动文件 if [ -s "$temp_file" ]; then mv -f "$temp_file" "$DATA_FILE" chmod 644 "$DATA_FILE" log "DEBUG" "保存失败计数: $count" else log "ERROR" "创建数据文件失败" rm -f "$temp_file" fi } # 关机提示函数 shutdown_warning() { local remaining=$1 # 在控制台显示倒计时 if [ -t 1 ]; then echo -ne "\r\033[K" # 清除当前行 echo -ne "NAS将在 ${remaining}秒 后关机! 按Ctrl+C取消" fi # 发送系统通知 if [ $((remaining % 10)) -eq 0 ] || [ $remaining -le 5 ]; then send_notification "NAS关机警告" "检测到网络故障,NAS将在${remaining}秒后关机!" fi # 记录日志 log "WARNING" "关机倒计时: ${remaining}秒" } # 飞牛NAS专用关机函数 shutdown_nas() { log "CRITICAL" "启动关机流程: 连续$MAX_FAILURES次ping失败 ($TARGET_IP)" # 发送最终关机通知 send_notification "NAS正在关机" "检测到连续${MAX_FAILURES}次网络故障,NAS即将关机!" # 方法1: 使用飞牛官方关机API log "INFO" "尝试通过飞牛API关机" if curl -s -X POST "http://localhost:3040/api/system/shutdown" >/dev/null 2>&1; then log "INFO" "飞牛API关机命令已发送" return fi # 方法2: 使用DBus关机(飞牛推荐) log "INFO" "尝试通过DBus关机" if command -v dbus-send >/dev/null 2>&1; then if dbus-send --system --print-reply --dest=org.freenas.system \ /org/freenas/system org.freenas.system.Shutdown >/dev/null 2>&1; then log "INFO" "DBus关机命令已发送" return fi fi # 方法3: 使用系统ctl关机 log "INFO" "尝试通过systemctl关机" if command -v systemctl >/dev/null 2>&1; then systemctl poweroff if [ $? -eq 0 ]; then log "INFO" "systemctl poweroff命令已发送" return fi fi # 方法4: 传统关机命令 log "INFO" "尝试传统shutdown命令" if /sbin/shutdown -h now; then log "INFO" "传统shutdown命令已发送" return fi # 方法5: 紧急关机 log "CRITICAL" "所有关机方法均失败! 尝试紧急关机" sync echo 1 > /proc/sys/kernel/sysrq echo o > /proc/sysrq-trigger } # 清理函数 cleanup() { rm -f "${DATA_FILE}.tmp.*" exit 0 } # 主程序 main() { trap cleanup EXIT INT TERM # 检查是否以root身份运行 if [ "$(id -u)" -ne 0 ]; then echo -e "\n错误: 脚本必须以root权限运行\n" >&2 exit 1 fi # 检查关机锁文件 if [ -f "$LOCK_FILE" ]; then log "WARNING" "检测到关机锁文件 - 重置状态" rm -f "$LOCK_FILE" save_failure_count 0 fi # 获取系统运行时间 local uptime=$(get_uptime) # 检查是否达到最小运行时间 if [ "$uptime" -lt "$MIN_UPTIME" ]; then log "INFO" "系统运行时间不足 (${uptime}s < ${MIN_UPTIME}s),跳过检查" save_failure_count 0 send_notification "NAS已启动" "系统正在启动中,监控将在${MIN_UPTIME}秒后开始" exit 0 fi log "INFO" "===== Ping监控启动 =====" log "INFO" "系统运行时间: ${uptime}s" log "INFO" "目标IP: $TARGET_IP, 最大失败次数: $MAX_FAILURES" # 加载失败次数 failure_count=$(load_failure_count) log "INFO" "当前失败计数: $failure_count" # 执行Ping测试 if ping_ip; then # Ping成功时重置计数器 if [ "$failure_count" -gt 0 ]; then log "INFO" "网络恢复! 重置计数器 (原计数: $failure_count)" send_notification "网络恢复" "到 ${TARGET_IP} 的网络连接已恢复" fi save_failure_count 0 else # Ping失败时增加计数器 failure_count=$((failure_count + 1)) log "WARNING" "Ping失败! 失败计数: $failure_count/$MAX_FAILURES" save_failure_count "$failure_count" # 当接近关机阈值时发送警告 if [ $failure_count -ge $((MAX_FAILURES - 1)) ]; then send_notification "网络故障警告" "到 ${TARGET_IP} 的连接失败 (${failure_count}/${MAX_FAILURES}次)" fi # 检查是否达到关机阈值 if [ "$failure_count" -ge "$MAX_FAILURES" ]; then log "CRITICAL" "达到最大失败次数! 准备关机..." # 关机前强制重置计数器 save_failure_count 0 # 创建关机锁文件 touch "$LOCK_FILE" # 关机倒计时 log "WARNING" "开始 ${SHUTDOWN_DELAY} 秒关机倒计时" for ((i=SHUTDOWN_DELAY; i>0; i--)); do shutdown_warning $i sleep 1 done # 添加空行清除倒计时显示 [ -t 1 ] && echo # 执行关机 log "CRITICAL" "正在关闭NAS..." shutdown_nas exit 0 fi fi log "INFO" "状态更新完成。下次检查在1分钟后。" } # 执行主程序 main
2025年08月06日
55 阅读
0 评论
0 点赞
2025-08-01
制作网页网站必学,CSS单位详解:rem、em、vw、vh。
CSS单位详解:rem、em、vw、vh * { margin: 0; padding: 0; box-sizing: border-box; font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; } body { background: linear-gradient(135deg, #1a2a6c, #b21f1f, #fdbb2d); color: #333; line-height: 1.6; padding: 20px; min-height: 100vh; } .container { max-width: 1400px; margin: 0 auto; } header { background: rgba(255, 255, 255, 0.95); border-radius: 12px; padding: 20px 30px; margin-bottom: 30px; box-shadow: 0 8px 30px rgba(0, 0, 0, 0.15); display: flex; flex-wrap: wrap; justify-content: space-between; align-items: center; } h1 { font-size: 2.8rem; color: #1a2a6c; margin-bottom: 5px; text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.1); } .subtitle { font-size: 1.3rem; color: #555; max-width: 700px; } .resolution-info { background: rgba(26, 42, 108, 0.85); color: white; padding: 15px 25px; border-radius: 10px; min-width: 300px; text-align: center; } .resolution-info h3 { font-size: 1.3rem; margin-bottom: 8px; } .resolution-value { font-size: 1.8rem; font-weight: bold; color: #fdbb2d; } .content { display: flex; flex-wrap: wrap; gap: 30px; margin-bottom: 40px; } .explanation { flex: 1; min-width: 300px; background: rgba(255, 255, 255, 0.95); border-radius: 12px; padding: 30px; box-shadow: 0 8px 25px rgba(0, 0, 0, 0.1); } .demo-area { flex: 1; min-width: 300px; background: rgba(255, 255, 255, 0.95); border-radius: 12px; padding: 30px; box-shadow: 0 8px 25px rgba(0, 0, 0, 0.1); } h2 { color: #1a2a6c; margin-bottom: 25px; font-size: 2rem; text-align: center; padding-bottom: 15px; border-bottom: 3px solid #fdbb2d; } .unit-table { width: 100%; border-collapse: collapse; margin-top: 20px; } .unit-table th { background-color: #1a2a6c; color: white; padding: 15px; text-align: left; } .unit-table td { padding: 15px; border-bottom: 1px solid #ddd; } .unit-table tr:nth-child(even) { background-color: #f9f9f9; } .unit-table tr:hover { background-color: #f1f5ff; } .unit-box { height: 120px; display: flex; align-items: center; justify-content: center; margin: 25px 0; border-radius: 8px; color: white; font-weight: bold; font-size: 1.2rem; text-align: center; transition: all 0.3s ease; position: relative; overflow: hidden; } .unit-box span { background: rgba(0, 0, 0, 0.6); padding: 5px 10px; border-radius: 4px; } .rem-box { background: linear-gradient(45deg, #1a2a6c, #3a56c5); width: 15rem; } .em-box { background: linear-gradient(45deg, #b21f1f, #e84a4a); width: 15em; } .vw-box { background: linear-gradient(45deg, #006400, #00aa00); width: 30vw; } .vh-box { background: linear-gradient(45deg, #8B4513, #cd853f); height: 15vh; width: 100%; } .controls { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 20px; margin-top: 30px; padding: 20px; background: #f0f5ff; border-radius: 10px; } .control-group { display: flex; flex-direction: column; } .control-group label { margin-bottom: 8px; font-weight: bold; color: #1a2a6c; } .control-group input { padding: 10px; border: 2px solid #1a2a6c; border-radius: 6px; font-size: 1rem; } .use-cases { background: rgba(255, 255, 255, 0.95); border-radius: 12px; padding: 30px; margin-bottom: 30px; box-shadow: 0 8px 25px rgba(0, 0, 0, 0.1); } .case-container { display: flex; flex-wrap: wrap; gap: 30px; margin-top: 25px; } .case { flex: 1; min-width: 300px; padding: 25px; background: #f0f5ff; border-radius: 10px; border-left: 5px solid #1a2a6c; } .case h3 { color: #1a2a6c; margin-bottom: 15px; font-size: 1.5rem; display: flex; align-items: center; } .case h3 i { margin-right: 10px; color: #b21f1f; } .case p { margin-bottom: 15px; line-height: 1.8; } .case-code { background: #1a2a6c; color: #fdbb2d; padding: 15px; border-radius: 8px; font-family: monospace; font-size: 1.1rem; overflow-x: auto; } footer { text-align: center; padding: 25px; color: white; font-size: 1.1rem; margin-top: 20px; } .responsive-text { font-size: clamp(1rem, 2vw, 1.3rem); color: #333; margin: 20px 0; text-align: center; font-style: italic; } @media (max-width: 768px) { header { flex-direction: column; text-align: center; gap: 20px; } .resolution-info { width: 100%; } h1 { font-size: 2.2rem; } } CSS单位详解 rem、em、vw、vh的区别与应用场景 当前分辨率 1920 × 1080 单位特性对比 单位 基于 特点 响应式 rem 根元素(html)字体大小 相对于基准值,不受父元素影响 优秀 em 当前元素字体大小 受父元素字体大小影响 良好(需注意继承) vw 视口宽度的1% 直接与视口宽度关联 极佳 vh 视口高度的1% 直接与视口高度关联 极佳 提示:调整浏览器窗口大小或使用下方控制面板,观察各单位的响应变化 单位效果演示 rem 单位 (15rem = 15 × 根字体大小) em 单位 (15em = 15 × 当前字体大小) vw 单位 (30vw = 30% 视口宽度) vh 单位 (15vh = 15% 视口高度) 根字体大小 (px): 元素字体大小 (px): 实际应用场景 rem - 字体与间距 使用rem设置字体大小和间距,确保整个设计比例一致。只需更改根字体大小即可全局调整比例。 html { font-size: 16px; } h1 { font-size: 2.5rem; } /* 40px */ p { margin-bottom: 1.5rem; } /* 24px */ vw/vh - 全屏元素 创建全屏区域、保持宽高比或设置与视口相关的尺寸,如图片轮播、英雄区域等。 .hero-section { width: 100vw; height: 100vh; } .banner { font-size: 5vw; /* 响应式字体 */ } em - 相对间距 在组件内部使用em设置内边距、外边距等,使间距与组件字体大小成比例变化。 .card { font-size: 18px; padding: 1.5em; /* 27px */ } .card-title { margin-bottom: 0.8em; /* 基于自身字体大小 */ } CSS单位详解 © 2023 | 响应式设计示例 // 更新分辨率显示 function updateResolution() { const resolutionElement = document.getElementById('resolution'); resolutionElement.textContent = `${window.innerWidth} × ${window.innerHeight}`; } // 初始化 window.addEventListener('load', () => { updateResolution(); // 设置根字体大小 const rootFontInput = document.getElementById('root-font'); rootFontInput.addEventListener('input', function() { document.documentElement.style.fontSize = this.value + 'px'; }); // 设置元素字体大小(影响em单位) const elementFontInput = document.getElementById('element-font'); elementFontInput.addEventListener('input', function() { const emBox = document.querySelector('.em-box'); emBox.style.fontSize = this.value + 'px'; }); }); // 监听窗口大小变化 window.addEventListener('resize', updateResolution);
2025年08月01日
14 阅读
0 评论
0 点赞