白色衬衫净少年 - 笔记
type: channel
link: https://bscsjsn.com/category/note/
description: 净少年的学习笔记
items: Windows系统更新启用/永久禁用批处理工具
items: Linux系统history命令配置优化【加入记录IP地址和时间】
items: 常见的浏览器指纹检测的方法
items: Win11 22H2以上版本首次启动跳过联网和配置本地账户教程
items: 一键部署Docker服务
items: 监控ssh登录并进行钉钉告警
items: 30秒快速配置Docker代理
items: docker部署rabbitmq消息持久化
items: linux管理用户脚本
items: Redis中BitMap应用场景及实现

Windows系统更新启用/永久禁用批处理工具
type: item
date: 2025-08-28T02:14:00+00:00
description: Windows系统更新启用/永久禁用批处理工具，复制代码,保存到到文件，后缀名改成bat,右键以管理员身份运行，根据提示选择即可 @echo off title 系统更新启用/禁用工具 :menu cls echo 请选择操作： echo 1. 禁用系统更新 echo 2. 启用系统更新 echo 3. 退出 set /p choice=请输入选项编号: if "%choice%"=="1" ( echo 正在禁用系统更新服务... net stop wuauserv sc config wuauserv start= disabled echo 正在禁用后台智能传输服务... net stop bits sc config bits start= disabled echo 正在禁用更新相关的计划任务... schtasks /Change /TN "\Microsoft\Windows\UpdateOrchestrator\ScheduledStart" /Disable >nul 2>&1 schtasks /Change /TN "\Microsoft\Windows\WindowsUpdate\Automatic App Update" /Disable >nul 2>&1 echo 系统更新已彻底禁用。 pause goto menu ) else if "%choice%"=="2" ( echo 正在启用系统更新服务... sc config wuauserv start= auto net start wuauserv echo 正在启用后台智能传输服务... sc config bits start= auto net start bits echo 正在启用更新相关的计划任务... schtasks /Change /TN "\Microsoft\Windows\UpdateOrchestrator\ScheduledStart" /Enable >nul 2>&1 schtasks /Change /TN "\Microsoft\Windows\WindowsUpdate\Automatic App Update" /Enable >nul 2>&1 echo 系统更新已启用。 pause goto menu ) else if "%choice%"=="3" ( exit ) else ( echo 输入无效，请输入有效的选项编号。 pause goto menu ) 如遇到右键以管理员身份运行出现乱码的问题，乱码的核心原因是文件编码与 CMD 终端的默认编码（通常为 ANSI/GBK）不匹配,按以下步骤操作: 用记事本打开 BAT 文件​ → 点击“文件” → “另存为”。 在“保存类型”下拉框中选择 ​​“所有文件”​，在“编码”下拉框中选择 ​​“ANSI”​​（中文系统下对应 GBK 编码） 覆盖原文件并重新以管理员身份运行脚本。

Linux系统history命令配置优化【加入记录IP地址和时间】
type: item
date: 2025-08-13T06:48:00+00:00
description: 加入时间和执行IP地址【全局生效、针对所有用户】 vim /etc/profile # 在/etc/profile 末尾加入以下内容 if [ `who am i| awk '{print $NF}'|awk -F'(' '{print NF}'` -eq 2 ];then unset HISTTIMEFORMAT export HISTTIMEFORMAT="[%F %T]-[`whoami`]- at [`who am i| awk '{print $NF}'`] " else unset HISTTIMEFORMAT export HISTTIMEFORMAT="[%F %T]-[`whoami`]- at [`hostname`] " fi 使其生效 source /etc/profile history其他优化 不同的终端可以通过上翻可查询到命令 vim /etc/bashrc # 避免重复命令（包括非连续重复） export HISTCONTROL=ignoredups:erasedups # 退出时追加历史而非覆盖 shopt -s histappend # 实时同步历史命令（优化性能） export PROMPT_COMMAND='history -a; history -n; echo "$(date "+%F %T") $(whoami) $(tail -n1 ~/.bash_history)" >> /var/log/audit.log' 使其生效 source /etc/bashrc 调整大小，增加到10000条 vim /etc/bashrc export HISTSIZE=10000 使其生效 source /etc/bashrc

常见的浏览器指纹检测的方法
type: item
date: 2025-07-16T02:38:00+00:00
description: 基础浏览器指纹检测 1. User-Agent 检测 // 检测浏览器基本信息 function detectUserAgent() { return { userAgent: navigator.userAgent, appName: navigator.appName, appVersion: navigator.appVersion, platform: navigator.platform, vendor: navigator.vendor, product: navigator.product }; } 2. 语言和地区检测 function detectLanguage() { return { language: navigator.language, languages: navigator.languages, timezone: Intl.DateTimeFormat().resolvedOptions().timeZone, locale: Intl.NumberFormat().resolvedOptions().locale }; } 3. 屏幕指纹检测 function detectScreen() { return { screenWidth: screen.width, screenHeight: screen.height, availWidth: screen.availWidth, availHeight: screen.availHeight, colorDepth: screen.colorDepth, pixelDepth: screen.pixelDepth, orientation: screen.orientation ? screen.orientation.type : 'unknown', devicePixelRatio: window.devicePixelRatio }; } Canvas 指纹检测 4. Canvas 2D 指纹 function getCanvas2DFingerprint() { const canvas = document.createElement('canvas'); const ctx = canvas.getContext('2d'); // 设置文本样式 ctx.textBaseline = 'top'; ctx.font = '14px Arial'; ctx.fillStyle = '#f60'; ctx.fillRect(125, 1, 62, 20); // 绘制文本 ctx.fillStyle = '#069'; ctx.fillText('Canvas fingerprint', 2, 15); // 绘制更复杂的图形 ctx.globalCompositeOperation = 'multiply'; ctx.fillStyle = 'rgb(255,0,255)'; ctx.beginPath(); ctx.arc(50, 50, 50, 0, Math.PI * 2, true); ctx.closePath(); ctx.fill(); return canvas.toDataURL(); } 5. Canvas WebGL 指纹 function getWebGLFingerprint() { const canvas = document.createElement('canvas'); const gl = canvas.getContext('webgl') || canvas.getContext('experimental-webgl'); if (!gl) return null; const fingerprint = { vendor: gl.getParameter(gl.VENDOR), renderer: gl.getParameter(gl.RENDERER), version: gl.getParameter(gl.VERSION), shadingLanguageVersion: gl.getParameter(gl.SHADING_LANGUAGE_VERSION), maxTextureSize: gl.getParameter(gl.MAX_TEXTURE_SIZE), maxViewportDims: gl.getParameter(gl.MAX_VIEWPORT_DIMS), maxVertexAttribs: gl.getParameter(gl.MAX_VERTEX_ATTRIBS), maxVaryingVectors: gl.getParameter(gl.MAX…

Win11 22H2以上版本首次启动跳过联网和配置本地账户教程
type: item
date: 2025-07-01T08:04:00+00:00
description: 装机完成以后，首次启动时需要断网(台式机记得拔网线)，然后在首次启动出现联网界面时按下Shift+F10，输入oobe\bypassnro并回车，此时系统会自动重启，重启后就可以离线配置 如果上述方案无效，可以尝试断网模式下，在首次启动出现联网界面时按下Shift+F10调出命令行，输入「start ms-cxh:localonly」就可以直接跳过联网账户登录，比目前其他需要更改注册表的方法要简单许多。

一键部署Docker服务
type: item
date: 2025-07-01T02:26:00+00:00
description: 准备工作 此脚本支持centos系列有yum命令的系统 可以访问外网的网卡 移除虚拟机原有的yum源（可删除或移走） 使用脚本直接安装 #!/bin/bash #version=v1 ########## #关闭防火墙 systemctl stop firewalld systemctl disable firewalld setenforce 0 if [ "$EUID" -ne 0 ]; then echo -e "\033[31m请使用root权限运行此脚本！\033[0m" exit 1 fi if [ ! -f /etc/yum.repos.d/centos.repo ]; then # 如果文件不存在，打印创建信息 echo "创建 /etc/yum.repos.d/centos.repo文件..." # 使用网络传输下载阿里云yum源 curl http://mirrors.aliyun.com/repo/Centos-7.repo -o /etc/yum.repos.d/centos.repo # 将文件内的http改成https，使用安全访问 sed -i 's/http/https/g' /etc/yum.repos.d/centos.repo # 更新 yum clean all && yum repolist else # 如果文件已存在，打印警告信息 echo -e "\033[32m警告：/etc/yum.repos.d/centos.repo 文件已存在，不会进行修改。\033[0m" fi if [ ! -f /etc/yum.repos.d/docker.repo ]; then # 如果文件不存在，打印创建信息 echo "创建 /etc/yum.repos.d/docker-ce.repo 文件..." # 安装 wget 工具（如果尚未安装） yum -y install wget # 从阿里云镜像下载 Docker CE 的 yum 仓库配置文件 wget -O /etc/yum.repos.d/docker-ce.repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo # 更新 yum 缓存 yum makecache else # 如果文件已存在，打印警告信息 echo -e "\033[0m 警告：/etc/yum.repos.d/docker.repo 文件已存在，不会进行修改。\033[0m" fi ########## # 输出提示信息 a="如果之前有安装docker的话，先删除docker" echo -e "\033[31m$a\033[0m" # 检查是否安装了 Docker if [ -x "$(command -v docker)" ]; then # 停止 Docker 服务 echo -e "\033[32m正在停止 Docker 服务...\033[0m" if systemctl is-active --quiet docker; then sudo systemctl stop docker else echo -e "\033[33mDocker 服务未运行，跳过停止步骤。\033[0m" fi # 停止 Docker 套接字 if systemctl is-active --quiet docker.socket; then echo -e "\033[32m正在停止 Docker 套接字...\033[0m" sudo systemctl stop docker.socket else echo -e "\033[33mDocker 套接字未运行，跳过停止步骤。\033[0m" fi # 禁用 Docker 服务 if systemctl is-enabled --quiet docker; then echo -e "\033[32m正在禁用 Docker 服务...\033[0m" sudo systemctl disable docker else echo -e "\033[33mDocker 服务未启用，跳过禁用步骤。\033[0m" fi # 禁用 Docker 套接字 if systemctl is-enabled --quiet docker.socket; then echo -e "\033[32m正在禁用 Docker 套接字...\033[0m" sudo systemctl disable docker.socket else echo -e "\033[33mDocker 套接字未启用，跳过禁用步骤。\033[0m" fi # 卸载 Do…

监控ssh登录并进行钉钉告警
type: item
date: 2025-06-26T01:19:00+00:00
description: 版本一 重点监控某些 IP 地址的多次失败登录尝试，并针对特定 IP 发送告警，该脚本会监控并告警那些尝试登录次数超过阈值的 IP 地址 #!/bin/bash # 设置钉钉 webhook URL 改为自己的钉钉机器人webhook WEBHOOK_URL="https://oapi.dingtalk.com/robot/send?access_token=your_access_token" # 设置日志文件路径，默认是 /var/log/auth.log（具体路径根据你的系统调整） LOG_FILE="/var/log/auth.log" # 设置匹配的异常登录模式，例如：多个错误登录尝试或 IP 地址 # 这里假设我们匹配 "Failed password" 登录尝试 PATTERN="Failed password" # 设置阈值，超过此次数的 IP 会触发告警 THRESHOLD=5 # 获取当前时间，格式化为 YYYY-MM-DD HH:MM:SS CURRENT_TIME=$(date "+%Y-%m-%d %H:%M:%S") # 提取失败登录的 IP 地址，并统计每个 IP 的尝试次数 IP_ATTEMPTS=$(grep "$PATTERN" $LOG_FILE | grep -oP 'from \K(\S+)' | sort | uniq -c | sort -nr) # 检查每个 IP 是否超过阈值，若超过则触发告警 ALERT_IPS="" while read -r count ip; do if [ "$count" -gt "$THRESHOLD" ]; then ALERT_IPS="$ALERT_IPS\nIP 地址 $ip 尝试登录次数：$count 次" fi done <<< "$IP_ATTEMPTS" # 如果有 IP 地址超过阈值，则发送钉钉告警 if [ -n "$ALERT_IPS" ]; then # 构造告警内容 MESSAGE="警告：检测到以下 IP 地址的 SSH 异常登录尝试。\n当前时间：$CURRENT_TIME\n$ALERT_IPS" # 发送钉钉告警 curl -X POST $WEBHOOK_URL \ -H "Content-Type: application/json" \ -d '{ "msgtype": "text", "text": { "content": "'"$MESSAGE"'" } }' fi 版本二 为了避免频繁的告警，新增加一个机制，确保只有当出现 新的异常攻击 IP 地址 时才触发告警。具体思路是： 记录上次已经告警过的 IP 地址：可以通过保存一个文件，记录上次已经触发告警的 IP 地址 检查新增的攻击 IP 地址：在每次运行时，比较当前的异常登录 IP 地址和上次记录的 IP 地址，只有新增的 IP 地址才会触发告警 更新已告警的 IP 地址列表：告警后，将新增的 IP 地址加入到记录文件中，避免重复告警 #!/bin/bash # 设置钉钉 webhook URL WEBHOOK_URL="https://oapi.dingtalk.com/robot/send?access_token=your_access_token" # 设置日志文件路径，默认是 /var/log/auth.log（具体路径根据你的系统调整） LOG_FILE="/var/log/auth.log" # 设置匹配的异常登录模式，例如：多个错误登录尝试或 IP 地址 PATTERN="Failed password" # 设置阈值，超过此次数的 IP 会触发告警 THRESHOLD=5 # 获取当前时间，格式化为 YYYY-MM-DD HH:MM:SS CURRENT_TIME=$(date "+%Y-%m-%d %H:%M:%S") # 提取失败登录的 IP 地址，并统计每个 IP 的尝试次数 IP_ATTEMPTS=$(grep "$PATTERN" $LOG_FILE | grep -oP 'from \K(\S+)' | sort | uniq -c | sort -nr) # 临时存储上次告警过的 IP 地址 LAST_ALERT_FILE="/tmp/last_alert_ips.txt" # 读取上次告警过的 IP 地址列表 if [ -f "$LAST_ALERT_FILE" ]; then LAST_ALERT_IPS=$(cat "$LAST_ALERT_FILE") else LAST_ALERT_IPS="" fi # 检查每个 IP 是否超过阈值，若超过则触发告警 ALERT_IPS="" NEW_ALERT_IPS="…

30秒快速配置Docker代理
type: item
date: 2025-06-03T02:12:00+00:00
description: 完整脚本,建议保存为docker-proxy.sh #!/bin/bash # ===================== 用户配置区 ===================== # ▼▼▼ 以下变量必须修改 ▼▼▼ HTTP_PROXY="http://192.168.1.118:7890/" # 改为你的代理IP和端口 HTTPS_PROXY="http://192.168.1.118:7890/" # 同上 NO_PROXY="localhost,127.0.0.1,.corp.com" # 内网域名白名单 # ▲▲▲ 修改结束 ▲▲▲ # ===================== 执行逻辑 ===================== if [ $# -eq 0 ]; then echo "错误：请指定操作模式" echo "用法：sudo $0 {set|remove}" exit 1 fi # 创建配置目录 sudo mkdir -p /etc/systemd/system/docker.service.d/ case "$1" in "set") echo "▶ 正在注入代理配置（目标地址：${HTTP_PROXY}）..." # 生成代理配置文件 sudo tee /etc/systemd/system/docker.service.d/proxy.conf > /dev/null <<EOF [Service] Environment="HTTP_PROXY=${HTTP_PROXY}" Environment="HTTPS_PROXY=${HTTPS_PROXY}" Environment="NO_PROXY=${NO_PROXY}" EOF # 重载服务配置 sudo systemctl daemon-reload sudo systemctl restart docker echo "✔ 代理已生效！" echo " 验证命令：docker info | grep -i proxy" ;; "remove") echo "▶ 正在清除代理配置..." sudo rm -f /etc/systemd/system/docker.service.d/proxy.conf sudo systemctl daemon-reload sudo systemctl restart docker echo "✔ 已恢复原始环境" ;; *) echo "错误：无效参数，支持 set 或 remove" exit 1 ;; esac echo " 注意：若容器网络异常，请尝试重启容器！" 操作指南 chmod +x docker-proxy.sh 修改配置 将192.168.1.118:7890替换为实际代理地址 白名单按需添加（如.alibaba.com、.docker.io） 执行命令 # 设置代理 ./docker-proxy.sh set # 清除代理 ./docker-proxy.sh remove

docker部署rabbitmq消息持久化
type: item
date: 2025-05-27T06:07:00+00:00
description: docker部署rabbitmq:3-management配置消息持久化 version: '3' services: rabbit: image: rabbitmq:3-management container_name: "rabbitmq" hostname: rabbitmq # 持久化必须有，否则重启会重置hostname，持久化会失败 restart: always ports: - "5672:5672" - "15672:15672" environment: - RABBITMQ_NODENAME: rabbit@localhost # 持久化必须有，否则重启会重置nodename，持久化会失败 - RABBITMQ_DEFAULT_USER: guest - RABBITMQ_DEFAULT_PASS: *** # 根据实际情况设置 - RABBITMQ_DEFAULT_VHOST: *** # 根据实际情况设置 volumes: - ./data:/var/lib/rabbitmq - ./10-defaults.conf:/etc/rabbitmq/conf.d/10-defaults.conf # 更改管理界面路由 networks: - localnet networks: localnet: external: true name: localnet driver: bridge 更改管理界面路由 ## DEFAULT SETTINGS ARE NOT MEANT TO BE TAKEN STRAIGHT INTO PRODUCTION ## see https://www.rabbitmq.com/configure.html for further information ## on configuring RabbitMQ ## allow access to the guest user from anywhere on the network ## https://www.rabbitmq.com/access-control.html#loopback-users ## https://www.rabbitmq.com/production-checklist.html#users loopback_users.guest = false ## Send all logs to stdout/TTY. Necessary to see logs when running via ## a container log.console = true # 最重要的是这条,配置并挂载到容器内部以后，访问管理界面url由原来的http://IP:15672变成http://IP:15672/rabbit/ management.path_prefix = /rabbit

linux管理用户脚本
type: item
date: 2025-04-28T09:37:00+00:00
description: 写了一个新的小脚本，用于管理linux用户 #!/bin/bash # Linux用户管理脚本 - 支持CentOS、Rocky Linux和Ubuntu系统 # 颜色设置 RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[0;33m' BLUE='\033[0;34m' NC='\033[0m' # 初始化 init() { # 检查root权限 [ "$(id -u)" -ne 0 ] && echo -e "${RED}错误: 需要root权限${NC}" && exit 1 # 检测Linux发行版 if [ -f /etc/os-release ]; then . /etc/os-release OS=$NAME if $OS == *"CentOS"* || $OS == *"Rocky"* ; then PACKAGE_MANAGER="yum" USER_ADD_CMD="useradd" GROUP_ADD_CMD="groupadd" elif $OS == *"Ubuntu"* || $OS == *"Debian"* ; then PACKAGE_MANAGER="apt" USER_ADD_CMD="adduser" GROUP_ADD_CMD="addgroup" else echo -e "${YELLOW}警告: 未知的Linux发行版: $OS, 使用通用命令${NC}" PACKAGE_MANAGER="apt" USER_ADD_CMD="useradd" GROUP_ADD_CMD="groupadd" fi else echo -e "${RED}错误: 无法检测操作系统${NC}" && exit 1 fi echo -e "${GREEN}检测到: $OS${NC}" } # 检查用户是否存在 user_exists() { id "$1" &>/dev/null return $? } # 检查组是否存在 group_exists() { grep -q "^$1:" /etc/group return $? } # 添加用户 add_user() { read -p "用户名: " username user_exists "$username" && echo -e "${RED}用户已存在${NC}" && return 1 read -p "主目录(默认/home/$username): " homedir homedir=${homedir:-/home/$username} read -p "Shell(默认/bin/bash): " usershell usershell=${usershell:-/bin/bash} read -p "密码: " userpass if $PACKAGE_MANAGER == "apt" ; then $USER_ADD_CMD $username --home $homedir --shell $usershell echo "$username:$userpass" | chpasswd else $USER_ADD_CMD -m -d $homedir -s $usershell $username echo "$userpass" | passwd --stdin $username fi [ $? -eq 0 ] && echo -e "${GREEN}用户创建成功${NC}" || echo -e "${RED}创建失败${NC}" read -p "添加sudo权限? (y/n): " add_sudo [[ $add_sudo == [yY] ]] && set_sudo_permission "$username" } # 删除用户 delete_user() { read -p "要删除的用户名: " username user_exists "$username" || { echo -e "${RED}用户不存在${NC}"; return 1; } read -p "同时删除主目录? (y/n): " del_home [[ $del_home == [yY] ]] && userdel -r $username || userdel $username [ $? -eq 0 ] && echo -e "${GREEN}用户已删除${NC}" || echo -e "${RED}删除失败${NC}" } # 修改用户 modify_user() { read -p "要修改的用户名: " username…

Redis中BitMap应用场景及实现
type: item
date: 2025-04-23T07:28:00+00:00
description: Redis BitMap是一种高效的位操作数据结构，它将字符串看作是由二进制位组成的数组。 在Redis中，一个BitMap最大可存储2^32个位，约512MB，而操作单个位的时间复杂度为O(1)。 这种结构在处理海量数据的布尔型状态时尤其高效，能在极小的内存占用下完成高性能的统计与分析任务。 Redis BitMap基础 基本概念 BitMap本质上是一个位数组，数组的每个元素只能是0或1。在Redis中，BitMap是基于String类型实现的，一个字符串的每个字节(8位)可以表示8个不同位，从而实现了位数组的功能 核心命令 Redis提供了一系列操作BitMap的命令： SETBIT key offset value : 设置key在offset处的位值 GETBIT key offset : 获取key在offset处的位值 BITCOUNT key [start end] : 统计指定范围内1的数量 BITPOS key bit [start end] : 返回第一个被设置为bit值的位的位置 BITOP operation destkey key [key ...] : 对多个BitMap执行位操作(AND, OR, XOR, NOT) BITFIELD key [GET type offset] [SET type offset value] : 原子操作多个位域 应用场景1：用户签到系统 场景描述 在许多应用中，需要记录用户每天是否签到，并支持查询用户连续签到天数、当月签到总天数等统计功能。 传统的方案可能使用关系型数据库存储每日签到记录，但这种方式既耗费存储空间，查询效率也低。 BitMap解决方案 使用BitMap，我们可以用一个位表示一天的签到状态，一个月只需30-31位，非常节省空间。 实现示例 import redis.clients.jedis.Jedis; import java.time.LocalDate; import java.time.format.DateTimeFormatter; public class SignInSystem { private Jedis jedis; private static final DateTimeFormatter MONTH_FORMATTER = DateTimeFormatter.ofPattern("yyyyMM"); public SignInSystem(String host, int port) { this.jedis = new Jedis(host, port); } // 用户签到 public void signIn(long userId, LocalDate date) { String signKey = getSignKey(userId, date); int dayOfMonth = date.getDayOfMonth() - 1; // Redis BitMap是0-based jedis.setbit(signKey, dayOfMonth, true); } // 检查用户是否签到 public boolean hasSignedIn(long userId, LocalDate date) { String signKey = getSignKey(userId, date); int dayOfMonth = date.getDayOfMonth() - 1; return jedis.getbit(signKey, dayOfMonth); } // 获取用户当月签到次数 public long getMonthlySignCount(long userId, LocalDate date) { String signKey = getSignKey(userId, date); return jedis.bitcount(signKey); } // 获取用户当月首次签到日期 public int getFirstSignInDay(long userId, LocalDate date) { String signKey = getSignKey(userId, date); long pos = jedis.bitpos(signKey, true); return pos == -1 ? -1 : (int) pos + 1; // 转换回自然日 } // 获取用户当月连续签到天数 public int getConsecutiveSignDays(long userId, LocalDate date) { String signKey = getSignKey(userId, da…