首页
壁纸
留言板
友链
更多
统计归档
Search
1
主板开机跳线接线图【F_PANEL接线图】
20,042 阅读
2
移动光猫获取超级密码&开启公网ipv6
15,904 阅读
3
TensorBoard:训练日志及网络结构可视化工具
13,302 阅读
4
Linux使用V2Ray 原生客户端
10,157 阅读
5
PC电源上供电接口定义
6,330 阅读
好物分享
实用教程
学习笔记
放码过来
深度学习
杂七杂八
bug处理
登录
/
注册
Search
标签搜索
好物分享
学习笔记
linux
MySQL
nvidia
typero
内网穿透
webdav
vps
java
cudann
gcc
cuda
树莓派
CNN
图像去雾
ssh安全
nps
暗通道先验
阿里云
jupiter
累计撰写
375
篇文章
累计收到
190
条评论
首页
栏目
好物分享
实用教程
学习笔记
放码过来
深度学习
杂七杂八
bug处理
页面
壁纸
留言板
友链
统计归档
搜索到
375
篇与
的结果
2026-09-14
基于 vLLM 部署 Spark-X2.5-4B:从依赖地狱到成功启动
Spark-X2.5-4B 是个较新的模型,vLLM 上游还没直接注册它的架构,必须配合官方 Spark 插件才能加载。本文记录 Linux + RTX 3060 12GB 环境下用 vLLM 跑通它的全过程,重点是版本兼容性那几个坑和最终的显存调优。项目值GPUNVIDIA GeForce RTX 3060,12288 MiB(SM86)vLLM0.27.1transformers5.14.1Spark-plugin最新版flashinfer-cubin0.6.16.post3模型路径/data/vllm/Spark-X2.5-4B*1. 环境准备1.1 先解决 pip 下载慢一开始用阿里云源,vLLM 那个 316 MB 的包只有 111 kB/s,ETA 快 47 分钟。换清华源后直接 31.3 MB/s,9 秒下完。永久换源,省得每次加 -i:pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple pip config set global.trusted-host pypi.tuna.tsinghua.edu.cn pip config set global.timeout 1201.2 安装 vLLM 与 Spark 插件pip install vllm克隆并安装 Spark 插件(用 --no-deps,别让它把 vLLM 的依赖版本改掉):git clone https://github.com/XHToken/Spark-plugin.git cd Spark-plugin pip install -e . --no-deps1.3 下载模型建议先把模型下完再启动服务,边启动边下载很容易超时失败。export HF_ENDPOINT=https://hf-mirror.com pip install -U huggingface_hub hf download XHToken/Spark-X2.5-4B --local-dir /data/vllm/Spark-X2.5-4B下完确认目录里有 config.json、model.safetensors(或分片文件)、tokenizer.json 这些,缺文件后面启动会报找不到权重。*2. 版本兼容踩坑记录这一段是整个部署最耗时的地方。vLLM、transformers、Spark 插件三者互相死锁,得一个个拆。坑 1:transformers 5.17.0 导致 RoPE 解析报错AttributeError: 'float' object has no attribute 'get' File ".../spark2_5_config.py", line 69, in __init__ super().__init__(**kwargs)transformers 5.x 对 RoPE 参数做了破坏性重构,新增 rope_parameters 字段、废弃了独立的 rope_scaling。Spark 插件还是按旧结构读,拿到的却是个 float。坑 2:vLLM 0.29.0 拒绝 transformers v4想降级到 transformers==4.57.0 绕开坑 1,结果:ImportError: Support for Transformers v4 is deprecated and was removed in vLLM v0.24.0. Please upgrade to Transformers v5: pip install --upgrade transformersvLLM 从 v0.24.0 起强制要求 transformers v5。0.29.0 这条路走不通,得降 vLLM 版本。坑 3:vLLM 0.23.0 的 WeightsMapper 不认新参数TypeError: WeightsMapper.__init__() got an unexpected keyword argument 'orig_to_new_stacked' File ".../spark2_5.py", line 329, in Spark2_5ForCausalLMorig_to_new_stacked 是较新版本才有的参数,0.23.0 的 WeightsMapper 没有。坑 4:最终落到 vLLM 0.27.1pip uninstall vllm transformers -y pip install "vllm==0.27.1" "transformers==5.14.1"0.27.1 既有 orig_to_new_stacked,又支持 transformers v5。换到这个组合后,前面那些配置解析报错全部消失。坑 5:flashinfer-cubin 版本不匹配RuntimeError: flashinfer-cubin version (0.6.12) does not match flashinfer version (0.6.16.post3). Please install the same version of both packages.vLLM 0.27.1 依赖 flashinfer-python 0.6.16.post3,但环境里残留了旧的 cubin 0.6.12。麻烦在于:官方给的 flashinfer install-cubin-wheel 命令自身也会 import flashinfer,同样卡在这个版本检查上,形成死循环。而清华源上 flashinfer-cubin 最新只有 0.6.13,没有需要的版本。解决办法是用 pip download -vvv 拿到真实下载地址,发现文件其实托管在 GitHub Releases:https://github.com/flashinfer-ai/flashinfer/releases/download/v0.6.16.post3/flashinfer_cubin-0.6.16.post3-py3-none-any.whl用 aria2c 多线程拉下来(16 连接,约 1.6 MiB/s,9 分钟):aria2c -x 16 -s 16 --continue=true \ "https://github.com/flashinfer-ai/flashinfer/releases/download/v0.6.16.post3/flashinfer_cubin-0.6.16.post3-py3-none-any.whl"本地安装:pip install ./flashinfer_cubin-0.6.16.post3-py3-none-any.whl💡 没有 aria2c 就用 wget -c 或 curl -L -C - 断点续传,GitHub 直连不稳,多试几次或者挂代理。*3. 显存调优12GB 显存跑 4B 模型不算紧张,但前提是 max-model-len 得压住。第一次失败:默认 max-model-len 太大模型默认 max_model_len 是 1048576(1M tokens),KV cache 要 36.48 GiB,远超 12GB:ValueError: To serve at least one request with the model's max seq len (1048576), 36.48 GiB KV cache is needed, which is larger than the available KV cache memory (2.03 GiB). Based on the available memory, the estimated maximum model length is 45264.注意可用 KV cache 只有 2.03 GiB —— 因为启动命令漏了 --gpu-memory-utilization,vLLM 用了默认值。第二次失败:32768 差一点点加上 --gpu-memory-utilization 0.92 --max-model-len 32768 后,需要 1.6 GiB,可用 1.56 GiB,差 0.04 GiB:max seq len (32768), 1.6 GiB KV cache is needed, which is larger than the available KV cache memory (1.56 GiB) Based on the available memory, the estimated maximum model length is 31616.最终可用配置取一个明显小于 31616 的整数,给系统留余量:vllm serve /data/vllm/Spark-X2.5-4B \ --trust-remote-code \ --port 8000 \ --tensor-parallel-size 1 \ --gpu-memory-utilization 0.92 \ --max-model-len 28672 \ --enable-prefix-caching按上面的数据推算,28672 约对应 1.4 GiB KV cache,低于实测可用的 1.56 GiB,有约 0.16 GiB 余量。*4. 启动与验证看到这两行日志就是起来了:INFO ... Application startup complete. INFO ... API server: HTTP server started服务监听在 http://0.0.0.0:8000,所有 API 路由已注册。确认模型已加载curl http://localhost:8000/v1/models测一次实际推理curl -X POST "http://localhost:8000/v1/chat/completions" \ -H "Content-Type: application/json" \ --data '{"model": "/data/vllm/Spark-X2.5-4B","messages": [{"role": "user", "content": "你好,请用一句话介绍你自己。"}],"max_tokens": 128}'返回正常 JSON、内容字段里有模型生成的文字,就说明整条链路通了。检查显存占用nvidia-smi看 Memory-Usage 那一列:在 11.0~11.5 GiB 之间 → --gpu-memory-utilization 0.92 被充分利用,正常接近 11.8 GiB → 余量偏紧,后续长上下文推理可能 OOM*5. 参数说明与后续优化--enable-prefix-caching 是什么vLLM 的自动前缀缓存(Automatic Prefix Caching,APC)。它把已处理过的提示词 KV Cache 块缓存下来,新请求的前缀如果和旧请求相同,直接复用,跳过重复的预填充计算。实现上是按块管理 KV Cache、每块用哈希标识,新请求进来先算块哈希,命中就复用。适合:长文档问答(同一份文档反复问不同问题)、多轮对话(后续轮次复用历史 KV Cache)限制:只加速预填充阶段,不加速解码;输入提示词很短且各不相同的话提升有限如果还要更长上下文或更高并发FP8 KV Cache:--kv-cache-dtype fp8,存储精度从 bf16 降到 fp8,显存占用减半。但 RTX 3060(SM86)对 fp8 原生支持有限,可能走软件模拟反而更慢;另外有报告说非 Hopper 架构上用 FP8 KV cache 出现过输出乱码。关闭 CUDA Graph:--enforce-eager。vLLM 默认编译 CUDA Graph 加速推理,这部分本身也占显存,关掉能释放出来,代价是推理变慢。适合"就差一点点就能启动"的场景。INT4/INT8 量化:理论上显存需求会大幅下降(INT4 约 2.2 GB,INT8 约 4.5 GB),但 Spark-X2.5-4B 目前没有 vLLM 能直接加载的量化权重 —— 现有的量化版本是 LiteRT-LM / MLX / GGUF 格式,vLLM 都不认。要量化得用 llm-compressor 自己处理。*6. 总结整个过程的核心难点就是 vLLM + transformers + Spark 插件三者的版本兼容性,最终可用组合:组件版本vLLM0.27.1transformers5.14.1Spark-plugin最新flashinfer-cubin0.6.16.post3建议把这套组合冻结下来:pip freeze > requirements-lock.txt⚠️ 后面升级其中任何一个组件,都可能再次触发新的兼容性问题。要升级就先在虚拟环境里试,别直接动生产环境。
2026年09月14日
1 阅读
0 评论
0 点赞
2026-09-13
Linux系统安装 Docker Compose V2 插件
新版 Docker 装完默认没有 docker compose,docker-compose 又是 Python 写的旧版,在麒麟上动不动报 KeyError: 'ContainerConfig'。装官方 V2 插件最省事,两种方式任选其一。1. 确认系统与架构麒麟桌面版多基于 Ubuntu、服务器版多基于 CentOS,先确认一下,后面选 apt 还是 yum 就清楚了:cat /etc/os-release # 看 ID / VERSION_ID uname -m # x86_64 还是 aarch64(飞腾、鲲鹏是 aarch64) docker -v # 确认 Docker 本体已装好顺手看看是不是已经装过了:docker compose version ls /usr/local/lib/docker/cli-plugins/2. 方式一:包管理器安装(推荐)系统已经配好 Docker 官方源的话,直接装插件包:# Debian / Ubuntu 系(麒麟桌面版) sudo apt-get update sudo apt-get install -y docker-compose-plugin # RHEL / CentOS 系(麒麟服务器版) sudo yum install -y docker-compose-plugin # 或 sudo dnf install -y docker-compose-plugin如果提示找不到包,说明没配官方源,直接跳到第 3 节手动装,比折腾源快。3. 方式二:手动下载二进制(通用)# 1. 设置版本和架构,麒麟常见为 aarch64 或 x86_64 COMPOSE_VER=v2.29.7 ARCH=$(uname -m) case "$ARCH" in x86_64) DARCH=x86_64 ;; aarch64|arm64) DARCH=aarch64 ;; *) echo "不支持的架构: $ARCH"; exit 1 ;; esac # 2. 下载到 Docker CLI 插件目录 sudo mkdir -p /usr/local/lib/docker/cli-plugins sudo curl -fsSL "https://github.com/docker/compose/releases/download/${COMPOSE_VER}/docker-compose-linux-${DARCH}" \ -o /usr/local/lib/docker/cli-plugins/docker-compose # 3. 赋予执行权限 sudo chmod +x /usr/local/lib/docker/cli-plugins/docker-compose # 4. 验证 docker compose version系统级目录不生效的话,放用户级插件目录:mkdir -p ~/.docker/cli-plugins mv /usr/local/lib/docker/cli-plugins/docker-compose ~/.docker/cli-plugins/GitHub 下载慢或超时,可以在 URL 前加第三方加速前缀(如 https://ghfast.top/https://github.com/...),或用能联网的机器下载后 scp 过去。架构一定要对,aarch64 机器装了 x86_64 的二进制会报 exec format error。4. 验证与权限docker compose version # 输出 Docker Compose version v2.x.x 即成功提示权限不足就把当前用户加进 docker 组,重新登录生效:sudo usermod -aG docker $USER newgrp docker # 或注销重登 docker compose version
2026年09月13日
3 阅读
0 评论
0 点赞
2026-09-13
局域网 Docker 私有镜像仓库:Registry 3.0.0 + Registry UI 部署
局域网 Docker 私有镜像仓库:Registry 3.0.0 + Registry UI 部署内网搭一个团队共用的镜像仓库,带 Web 管理界面,支持镜像浏览、搜索、复制 docker pull 命令和 Web 端删除。1. 规划项目值部署目录/data/app/docker-registryRegistryregistry:3.0.0,端口 5000Registry UIbyrdal/registry-ui:latest,端口 3001(容器内 3000)数据目录./registry-data、./registry-ui-data示例 IP192.168.101.44(换成你自己的)2. 部署mkdir -p /data/app/docker-registry && cd /data/app/docker-registry vi docker-compose.ymlservices: registry: image: registry:3.0.0 container_name: docker-registry restart: always ports: - "5000:5000" environment: REGISTRY_STORAGE_DELETE_ENABLED: "true" volumes: - ./registry-data:/var/lib/registry networks: - registry-net registry-ui: image: byrdal/registry-ui:latest container_name: registry-ui restart: always ports: - "3001:3000" environment: REGISTRY_URL: http://registry:5000 REGISTRY_PUBLIC_URL: localhost:5000 REGISTRY_TITLE: "局域网镜像仓库" volumes: - ./registry-ui-data:/data depends_on: - registry networks: - registry-net networks: registry-net: driver: bridge几个要留意的点:REGISTRY_STORAGE_DELETE_ENABLED: "true" —— 不开这个,UI 上删除会返回 405。REGISTRY_URL 是 UI 后端访问用的,走容器网络所以写服务名 registry;REGISTRY_PUBLIC_URL 是给客户端用的,局域网部署请改成 192.168.101.44:5000,否则 UI 上复制出来的 pull 命令是 localhost,别的机器拉不动。depends_on 只保证启动顺序,UI 默认每 10 分钟同步一次,刚推完镜像没刷新的话 docker restart registry-ui 触发一次。启动:docker compose up -d docker compose ps docker compose logs -f防火墙放行:firewall-cmd --permanent --add-port=5000/tcp firewall-cmd --permanent --add-port=3001/tcp firewall-cmd --reload3. 客户端配置Registry 默认走 HTTPS,局域网用 HTTP 必须在每台推拉镜像的机器上加 insecure-registries:vi /etc/docker/daemon.json{ "insecure-registries": ["192.168.101.44:5000"] }systemctl daemon-reload systemctl restart docker docker info | grep -A 3 "Insecure Registries"不配会报 http: server gave HTTP response to HTTPS client。Docker Desktop 在 Settings → Docker Engine 里改。4. 推送 / 拉取测试# 打标签,格式必须是 <仓库地址>/<镜像名>:<tag> docker tag alpine:latest 192.168.101.44:5000/alpine:latest docker push 192.168.101.44:5000/alpine:latest # 查看仓库与 tag curl http://192.168.101.44:5000/v2/_catalog curl http://192.168.101.44:5000/v2/alpine/tags/list # 另一台机器拉取 docker pull 192.168.101.44:5000/alpine:latest浏览器打开 http://192.168.101.44:3001 即可看到镜像列表、大小、推送时间,点进去能一键复制 pull 命令。5. 删除镜像与回收空间在 UI 上点删除只删了 manifest,磁盘不会立刻释放,必须再跑一次垃圾回收。# 1. 先在 compose 的 registry.environment 里临时加上只读维护模式,重建容器 # REGISTRY_STORAGE_MAINTENANCE_READONLY_ENABLED: "true" docker compose up -d registry # 2. 先 dry-run 看看要删多少(3.x 配置路径是 /etc/distribution/config.yml) docker exec docker-registry registry garbage-collect --dry-run /etc/distribution/config.yml # 3. 确认无误后执行 docker exec docker-registry registry garbage-collect --delete-untagged /etc/distribution/config.yml # 4. 去掉只读那行,重建 docker compose up -d registry⚠️ GC 期间若有 push 上传,可能被误判为垃圾删掉,导致"tag 在但 pull 报 blob 404",所以务必先开只读模式。2.x 的配置路径是 /etc/docker/registry/config.yml,别照抄老教程。命令行删除(UI 之外的备选):DIGEST=$(curl -sSI -H "Accept: application/vnd.docker.distribution.manifest.v2+json" \ http://192.168.101.44:5000/v2/alpine/manifests/latest \ | awk 'tolower($1) == "docker-content-digest:" {print $2}' | tr -d '\r') curl -X DELETE http://192.168.101.44:5000/v2/alpine/manifests/$DIGEST
2026年09月13日
6 阅读
0 评论
0 点赞
2026-06-07
Docker 离线安装
下载 Docker 二进制包# 创建下载目录 mkdir -p /data && cd /data # 下载 Docker 29.5.3 二进制包 wget https://mirrors.tuna.tsinghua.edu.cn/docker-ce/linux/static/stable/x86_64/docker-29.5.3.tgz # 解压 Docker 二进制包 sudo tar -xzvf docker-29.5.3.tgz # 将二进制文件复制到系统 PATH sudo cp docker/* /usr/bin/ # 验证安装 docker --version # 预期输出:Docker version 29.5.3, build xxx创建 systemd 服务文件# 创建 Docker 服务文件 sudo tee /etc/systemd/system/docker.service <<-'EOF' [Unit] Description=Docker Application Container Engine Documentation=https://docs.docker.com After=network-online.target firewalld.service Wants=network-online.target [Service] Type=notify ExecStart=/usr/bin/dockerd ExecReload=/bin/kill -s HUP $MAINPID LimitNOFILE=infinity LimitNPROC=infinity LimitCORE=infinity TimeoutStartSec=0 Delegate=yes KillMode=process Restart=on-failure StartLimitBurst=3 StartLimitInterval=60s [Install] WantedBy=multi-user.target EOFsystemctl daemon-reload systemctl start docker systemctl enable docker systemctl status docker
2026年06月07日
78 阅读
0 评论
0 点赞
2026-06-03
Kibana 8.14.3 完整部署方案
一、整体规划项目值运行用户appKibana 安装路径/data/app/kibana-serverKibana 配置目录/data/app/kibana-server/configKibana 日志目录/data/app/kibana-logs监听端口5601访问协议HTTP(可后续配置 HTTPS)对接 ES 地址https://192.168.101.44:9200(使用你之前服务器的 IP)二、完整部署步骤2.1 下载并解压 Kibana(使用国内镜像)# 切换到 app 用户 sudo -i -u app # 进入安装目录 cd /data/app # 使用华为云镜像下载 Kibana 8.14.3 wget https://mirrors.huaweicloud.com/kibana/8.14.3/kibana-8.14.3-linux-x86_64.tar.gz # 解压 tar xzvf kibana-8.14.3-linux-x86_64.tar.gz # 重命名目录 mv kibana-8.14.3 kibana-server # 清理安装包 rm -f kibana-8.14.3-linux-x86_64.tar.gz # 创建日志目录 mkdir -p /data/app/kibana-logs2.2 配置 Kibana# 备份原始配置 cp /data/app/kibana-server/config/kibana.yml /data/app/kibana-server/config/kibana.yml.bak # 编辑配置文件 vi /data/app/kibana-server/config/kibana.yml写入以下完整配置(根据你的实际环境修改 ES 地址和密码):# ======================== 服务器配置 ======================== server.host: "0.0.0.0" server.port: 5601 # ======================== Elasticsearch 连接配置 ======================== elasticsearch.hosts: ["http://192.168.101.44:9200"] elasticsearch.username: "kibana" elasticsearch.password: "YourKibanaPassword123!" elasticsearch.ssl.verificationMode: none # ======================== 新版日志配置(替代 logging.dest) ======================== logging: appenders: file: type: file fileName: /data/app/kibana-logs/kibana.log layout: type: json root: appenders: [file] level: info # ======================== 其他配置 ======================== i18n.locale: "zh-CN"2.3 设置目录权限# 退出 app 用户 exit # 确保所有目录属主为 app sudo chown -R app:app /data/app/kibana-server sudo chown -R app:app /data/app/kibana-logs2.4 配置系统参数(可选,提高并发)# 增加文件描述符限制(与 ES 保持一致) echo "app soft nofile 65535" | sudo tee -a /etc/security/limits.conf echo "app hard nofile 65535" | sudo tee -a /etc/security/limits.conf三、创建 Systemd 服务文件sudo vi /etc/systemd/system/kibana.service写入以下内容:[Unit] Description=Kibana Server Documentation=https://www.elastic.co After=network.target elasticsearch.service Wants=elasticsearch.service [Service] Type=simple User=app Group=app WorkingDirectory=/data/app/kibana-server Environment=NODE_OPTIONS="--max-old-space-size=512" ExecStart=/data/app/kibana-server/bin/kibana ExecReload=/bin/kill -HUP $MAINPID KillMode=process Restart=on-failure RestartSec=3 LimitNOFILE=65535 LimitNPROC=4096 TimeoutStopSec=20 [Install] WantedBy=multi-user.target四、启动并管理 Kibana4.1 启动服务# 重载 systemd 配置 sudo systemctl daemon-reload # 启动 Kibana sudo systemctl start kibana # 设置开机自启 sudo systemctl enable kibana # 查看服务状态 sudo systemctl status kibana4.2 查看日志(排查问题)# 查看 systemd 日志 sudo journalctl -u kibana -f # 查看 Kibana 自身日志 sudo tail -f /data/app/kibana-logs/kibana.log4.3 常用管理命令# 启动 sudo systemctl start kibana # 停止 sudo systemctl stop kibana # 重启 sudo systemctl restart kibana # 查看状态 sudo systemctl status kibana # 查看实时日志 sudo journalctl -u kibana -f # 禁用开机自启 sudo systemctl disable kibana五、防火墙配置# 开放 Kibana 端口 5601 sudo firewall-cmd --permanent --add-port=5601/tcp sudo firewall-cmd --reload六、验证 Kibana 部署6.1 本地测试# 访问 Kibana 首页 curl http://localhost:5601 # 应该返回 HTML 内容(包含 "Kibana" 字样)6.2 浏览器访问打开浏览器,访问 http://<你的服务器IP>:5601如果连接正常,会看到 Kibana 欢迎页面首次访问可能需要等待几分钟初始化索引不需要额外登录(Kibana 本身不设认证,但连接 ES 使用了认证)6.3 测试与 ES 的数据交互进入 Kibana 界面 → 点击左上角菜单 → Management → Dev Tools在控制台中执行以下命令(测试 ES 连接):# 查看集群健康状态 GET /_cluster/health # 创建测试索引 PUT /test-kibana-index # 添加文档 POST /test-kibana-index/_doc { "message": "Hello Kibana!", "timestamp": "2026-06-03" } # 搜索文档 GET /test-kibana-index/_search七、常见问题排查问题可能原因解决方案Kibana 无法启动端口被占用`sudo netstat -tlnpgrep 5601,修改 server.port`连接 ES 失败ES 地址/认证错误检查 elasticsearch.hosts、用户名、密码SSL 证书错误ES 使用自签名证书设置 elasticsearch.ssl.verificationMode: nonekibana 用户不存在未在 ES 中创建在 ES 中执行创建 kibana 用户的 API日志目录权限错误目录属主不是 appsudo chown -R app:app /data/app/kibana-logs访问 5601 无响应防火墙未开放检查防火墙规则,开放 5601 端口Kibana 一直显示“Kibana server is not ready yet”ES 未就绪或 Kibana 索引初始化慢等待 2-3 分钟,查看日志 journalctl -u kibana -f
2026年06月03日
74 阅读
0 评论
0 点赞
2026-06-03
Elasticsearch 8.14.3 完整部署方案
一、环境规划项目值运行用户appJDK 安装路径/data/app/jdk17ES 安装路径/data/app/es-serverES 数据目录/data/app/es-dataES 日志目录/data/app/es-logsES 配置目录/data/app/es-server/config证书目录/data/app/es-server/config/certs服务端口9200 (HTTPS)集群模式单节点二、完整部署命令2.1 创建 app 用户和基础目录# 创建 app 用户 sudo useradd app -m -s /bin/bash # 创建安装根目录并授权 sudo mkdir -p /data/app sudo chown app:app /data/app2.2 安装 JDK 17# 切换到 app 用户 sudo -i -u app # 进入安装目录 cd /data/app # 下载 JDK 17 wget https://mirrors.tuna.tsinghua.edu.cn/Adoptium/17/jdk/x64/linux/OpenJDK17U-jdk_x64_linux_hotspot_17.0.19_10.tar.gz # 解压 tar xzvf OpenJDK17U-jdk_x64_linux_hotspot_17.0.19_10.tar.gz # 重命名目录 mv jdk-17.0.19+10/ jdk17 # 清理安装包 rm -f OpenJDK17U-jdk_x64_linux_hotspot_17.0.19_10.tar.gz # 配置环境变量 echo 'export JAVA_HOME=/data/app/jdk17' >> /home/app/.bashrc echo 'export PATH=$PATH:$JAVA_HOME/bin' >> /home/app/.bashrc source /home/app/.bashrc # 验证 JDK java -version2.3 安装 Elasticsearch# 仍在 app 用户下执行 cd /data/app # 下载 ES 8.14.3 wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-8.14.3-linux-x86_64.tar.gz # 解压 tar xzvf elasticsearch-8.14.3-linux-x86_64.tar.gz # 重命名 mv elasticsearch-8.14.3 es-server # 清理安装包 rm -f elasticsearch-8.14.3-linux-x86_64.tar.gz # 创建数据和日志目录 mkdir -p /data/app/es-data mkdir -p /data/app/es-logs2.4 生成 SSL 证书(开启安全认证必需)# 仍在 app 用户下执行 cd /data/app/es-server # 生成 CA 证书(直接回车,不设密码) ./bin/elasticsearch-certutil ca # 生成节点证书(直接回车,不设密码) ./bin/elasticsearch-certutil cert --ca elastic-stack-ca.p12 # 创建证书目录并移动证书 mkdir -p config/certs mv elastic-certificates.p12 config/certs/ mv elastic-stack-ca.p12 config/certs/ # 设置证书权限 chmod 644 config/certs/elastic-certificates.p122.5 配置 Elasticsearch# 备份原配置 cp /data/app/es-server/config/elasticsearch.yml /data/app/es-server/config/elasticsearch.yml.bak # 写入新配置 cat > /data/app/es-server/config/elasticsearch.yml << 'EOF' # ======================== 路径配置 ======================== path.data: /data/app/es-data path.logs: /data/app/es-logs # ======================== 集群配置 ======================== cluster.name: my-app-cluster node.name: node-1 network.host: 0.0.0.0 http.port: 9200 discovery.type: single-node # ======================== 安全认证配置 ======================== # 开启安全功能 xpack.security.enabled: true # 传输层 SSL 配置(节点间通信) xpack.security.transport.ssl.enabled: true xpack.security.transport.ssl.verification_mode: certificate xpack.security.transport.ssl.keystore.path: certs/elastic-certificates.p12 xpack.security.transport.ssl.truststore.path: certs/elastic-certificates.p12 # HTTP 层 SSL 配置(开启 HTTPS) xpack.security.http.ssl.enabled: false xpack.security.http.ssl.keystore.path: certs/elastic-certificates.p12 xpack.security.http.ssl.truststore.path: certs/elastic-certificates.p12 EOF2.6 配置 JVM 堆内存(可选,根据服务器内存调整)# 设置堆内存为 1G(根据实际情况调整) sed -i 's/^-Xms.*/-Xms1g/' /data/app/es-server/config/jvm.options sed -i 's/^-Xmx.*/-Xmx1g/' /data/app/es-server/config/jvm.options2.7 退出 app 用户,配置系统参数# 退出 app 用户 exit# 配置文件描述符限制 echo "app soft nofile 65535" | sudo tee -a /etc/security/limits.conf echo "app hard nofile 65535" | sudo tee -a /etc/security/limits.conf # 配置虚拟内存映射数 echo "vm.max_map_count=262144" | sudo tee -a /etc/sysctl.conf sudo sysctl -p # 配置进程限制 echo "app soft nproc 4096" | sudo tee -a /etc/security/limits.conf echo "app hard nproc 4096" | sudo tee -a /etc/security/limits.conf2.8 创建 Systemd 服务文件sudo cat > /etc/systemd/system/elasticsearch.service << 'EOF' [Unit] Description=Elasticsearch Server Documentation=https://www.elastic.co After=network.target [Service] Type=simple User=app Group=app WorkingDirectory=/data/app/es-server Environment=JAVA_HOME=/data/app/jdk17 Environment=ES_PATH_CONF=/data/app/es-server/config ExecStart=/data/app/es-server/bin/elasticsearch ExecReload=/bin/kill -HUP $MAINPID KillMode=process LimitNOFILE=65535 LimitNPROC=4096 TimeoutStopSec=20 Restart=on-failure RestartSec=3 [Install] WantedBy=multi-user.target EOF2.9 设置目录权限并启动服务# 确保所有目录属主为 app sudo chown -R app:app /data/app # 重载 systemd sudo systemctl daemon-reload # 启动 Elasticsearch sudo systemctl start elasticsearch # 查看启动状态(等待 10-20 秒让服务完全启动) sleep 15 sudo systemctl status elasticsearch2.10 设置内置用户密码# 使用 auto 模式,自动生成随机密码 sudo -u app /data/app/es-server/bin/elasticsearch-setup-passwords auto --insecure执行后,系统会提示输入以下用户的密码(请务必牢记):用户说明密码建议elastic超级管理员强密码kibanaKibana 连接用强密码logstash_systemLogstash 监控随机密码beats_systemBeats 监控随机密码apm_systemAPM 监控随机密码remote_monitoring_user远程监控随机密码2.11 开启防火墙端口# 开放 9200 端口 sudo firewall-cmd --permanent --add-port=9200/tcp sudo firewall-cmd --reload2.12 设置开机自启sudo systemctl enable elasticsearch三、验证部署3.1 基础验证(HTTPS + 认证)# 使用 elastic 用户和密码访问(-k 忽略自签名证书验证) curl -u elastic:<你设置的密码> http://localhost:9200预期输出:{ "name" : "node-1", "cluster_name" : "my-app-cluster", "cluster_uuid" : "xxxxxxxxxxxxxxxxxxxxxx", "version" : { "number" : "8.14.3", "build_flavor" : "default", "build_type" : "tar", "build_hash" : "d55f984299e0e88dee72ebd8255f7ff130859ad0", "build_date" : "2024-07-07T22:04:49.882652950Z", "build_snapshot" : false, "lucene_version" : "9.10.0", "minimum_wire_compatibility_version" : "7.17.0", "minimum_index_compatibility_version" : "7.0.0" }, "tagline" : "You Know, for Search" }3.2 查看集群健康状态curl -k -u elastic:<密码> https://localhost:9200/_cluster/health?pretty3.3 查看节点信息curl -k -u elastic:<密码> https://localhost:9200/_cat/nodes?v3.4 远程访问验证(从其他机器执行)curl -k -u elastic:<密码> https://<服务器IP>:9200四、日常管理命令4.1 服务管理# 启动 sudo systemctl start elasticsearch # 停止 sudo systemctl stop elasticsearch # 重启 sudo systemctl restart elasticsearch # 查看状态 sudo systemctl status elasticsearch # 查看日志 sudo journalctl -u elasticsearch -f # 查看最近 100 行日志 sudo journalctl -u elasticsearch -n 1004.2 密码管理# 修改 elastic 用户密码 curl -k -u elastic:<旧密码> -X POST https://localhost:9200/_security/user/elastic/_password -H "Content-Type: application/json" -d '{"password":"<新密码>"}' # 创建新用户 curl -k -u elastic:<密码> -X POST https://localhost:9200/_security/user/monitor -H "Content-Type: application/json" -d '{"password":"<密码>","roles":["monitoring_user"]}'4.3 证书管理# 查看证书信息 openssl pkcs12 -info -in /data/app/es-server/config/certs/elastic-certificates.p12 -nokeys五、目录结构总览/data/app/ ├── jdk17/ # JDK 安装目录 │ ├── bin/ │ ├── lib/ │ └── ... ├── es-server/ # ES 安装目录 │ ├── bin/ # 可执行文件 │ ├── config/ │ │ ├── elasticsearch.yml # 主配置文件 │ │ ├── jvm.options # JVM 配置 │ │ └── certs/ # SSL 证书目录 │ │ ├── elastic-certificates.p12 │ │ └── elastic-stack-ca.p12 │ ├── lib/ # 依赖库 │ └── modules/ # 模块 ├── es-data/ # 数据目录 │ └── nodes/ # 节点数据 └── es-logs/ # 日志目录 └── elasticsearch.log # 主日志文件六、常见问题排查问题检查命令解决方案服务启动失败sudo systemctl status elasticsearch查看错误信息,检查配置文件语法证书错误sudo journalctl -u elasticsearch -n 50确认证书路径正确,权限为 644内存不足free -h调整 jvm.options 中的 -Xms 和 -Xmx端口被占用`sudo netstat -tlnpgrep 9200`修改 http.port 或停止占用进程认证失败检查密码是否正确使用 elasticsearch-setup-passwords 重置远程无法访问sudo firewall-cmd --list-all确认防火墙开放 9200 端口七、安全建议(生产环境)证书替换:自签名证书仅适用于测试环境,生产环境请使用 CA 签发的正式证书IP 绑定:network.host: 0.0.0.0 允许所有 IP 访问,建议改为具体内网 IP防火墙:仅允许可信 IP 访问 9200 端口定期改密:定期更换 elastic 等内置用户密码审计日志:开启审计功能 xpack.security.audit.enabled: true备份:定期备份 /data/app/es-data 目录和证书文件
2026年06月03日
72 阅读
0 评论
0 点赞
2026-05-10
三主三从 Redis 集群搭建与重启数据保障方案
一、环境规划与准备工作1.1 节点分配服务器 IP端口角色备注192.168.101.416379Master 1主节点192.168.101.416380Slave 1从节点(作为 .41 主节点的备用)192.168.101.426379Master 2主节点192.168.101.426380Slave 2从节点(作为 .42 主节点的备用)192.168.101.436379Master 3主节点192.168.101.436380Slave 3从节点(作为 .43 主节点的备用)注意:Redis 集群的总线通信端口会自动占用 port + 10000,即 16379 和 16380,也需要开放。1.2 软件环境要求操作系统:CentOS 7.xRedis 版本:5.0 或以上(推荐 6.2.x / 7.2.x,内置集群管理工具)网络互通:三台服务器之间需能互相 ping 通,所有端口可互相访问运行账号:app(如不存在则自动创建)二、每台服务器统一操作步骤(共三台)以下操作需在 192.168.101.41、192.168.101.42、192.168.101.43 三台服务器上各自执行一遍。2.1 创建 app 账号(如已存在可跳过)# 创建 app 用户组和用户(无登录 shell) groupadd app useradd -g app -m -s /sbin/nologin app # 设置目录权限(后续创建目录后需 chown)2.2 安装 Redis(三台机器)# 安装依赖 yum install -y gcc gcc-c++ make tcl # 下载源码 mkdir -p /data/app/src && cd /data/app/src wget https://download.redis.io/releases/redis-7.2.5.tar.gz tar -zxvf redis-7.2.5.tar.gz cd redis-7.2.5 # 编译并指定安装路径 make make install PREFIX=/data/app/redis # 将二进制路径加入 PATH(永久生效) echo 'export PATH=/data/app/redis/bin:$PATH' > /etc/profile.d/redis.sh source /etc/profile.d/redis.sh # 验证 /data/app/redis/bin/redis-server --version2.3 创建工作目录(每台机器)# 创建两个实例的工作目录 mkdir -p /data/redis-cluster/{6379,6380}/data mkdir -p /data/redis-cluster/{6379,6380}/conf mkdir -p /data/redis-cluster/{6379,6380}/logs # 创建集群节点配置文件目录 mkdir -p /var/run/redis-cluster # 修改目录所有者为 app chown -R app:app /data/redis-cluster chown -R app:app /var/run/redis-cluster2.4 生成主节点配置文件(端口 6379)编辑配置文件:vi /data/redis-cluster/6379/conf/redis.conf内容如下(以 192.168.101.41 为例,其他机器相同):# 基础配置 port 6379 bind 0.0.0.0 protected-mode no daemonize yes pidfile /var/run/redis-cluster/redis_6379.pid loglevel notice logfile /data/redis-cluster/6379/logs/redis.log # 工作目录和数据目录 dir /data/redis-cluster/6379/data # ========== 集群配置 ========== cluster-enabled yes cluster-config-file /data/redis-cluster/6379/conf/nodes-6379.conf cluster-node-timeout 5000 # ========== 数据持久化配置 ========== save 900 1 save 300 10 save 60 10000 rdbcompression yes dbfilename dump-6379.rdb appendonly yes appendfilename "appendonly-6379.aof" appendfsync everysec no-appendfsync-on-rewrite no auto-aof-rewrite-percentage 100 auto-aof-rewrite-min-size 64mb # 访问密码 requirepass redispasswd # 主从同步认证密码 masterauth redispasswd2.5 生成从节点配置文件(端口 6380)vi /data/redis-cluster/6380/conf/redis.conf内容(将 6379 替换为 6380):port 6380 bind 0.0.0.0 protected-mode no daemonize yes pidfile /var/run/redis-cluster/redis_6380.pid loglevel notice logfile /data/redis-cluster/6380/logs/redis.log dir /data/redis-cluster/6380/data cluster-enabled yes cluster-config-file /data/redis-cluster/6380/conf/nodes-6380.conf cluster-node-timeout 5000 save 900 1 save 300 10 save 60 10000 rdbcompression yes dbfilename dump-6380.rdb appendonly yes appendfilename "appendonly-6380.aof" appendfsync everysec no-appendfsync-on-rewrite no auto-aof-rewrite-percentage 100 auto-aof-rewrite-min-size 64mb requirepass redispasswd masterauth redispasswd2.6 配置防火墙(三台机器)# 开放 Redis 端口 firewall-cmd --permanent --add-port=6379/tcp firewall-cmd --permanent --add-port=6380/tcp # 开放集群总线端口 firewall-cmd --permanent --add-port=16379/tcp firewall-cmd --permanent --add-port=16380/tcp # 重载防火墙 firewall-cmd --reload # 验证 firewall-cmd --list-ports若生产环境不方便关闭 SELinux,可临时关闭:setenforce 0 sed -i 's/=enforcing/=disabled/g' /etc/selinux/config2.7 配置 systemd 开机自启(使用 app 账号):# 主节点 service cat > /etc/systemd/system/redis-6379.service << EOF [Unit] Description=Redis Server 6379 After=network.target [Service] Type=forking User=app Group=app ExecStart=/data/app/redis/bin/redis-server /data/redis-cluster/6379/conf/redis.conf ExecStop=/data/app/redis/bin/redis-cli -p 6379 -a 'redispasswd' shutdown Restart=always [Install] WantedBy=multi-user.target EOF # 从节点 service(端口改为 6380) cat > /etc/systemd/system/redis-6380.service << EOF [Unit] Description=Redis Server 6380 After=network.target [Service] Type=forking User=app Group=app ExecStart=/data/app/redis/bin/redis-server /data/redis-cluster/6380/conf/redis.conf ExecStop=/data/app/redis/bin/redis-cli -p 6380 -a 'redispasswd' shutdown Restart=always [Install] WantedBy=multi-user.target EOF # 启用 systemctl enable redis-6379 redis-6380 # 验证 ps aux | grep redis-server netstat -tuln | grep -E '6379|6380'三、创建 Redis 集群(只需在一台机器执行)当 三台服务器上的 6 个 Redis 实例全部启动后,在任意一台有 redis-cli 的机器上执行:redis-cli -a 'redispasswd' --cluster create \ 192.168.101.41:6379 \ 192.168.101.42:6379 \ 192.168.101.43:6379 \ 192.168.101.41:6380 \ 192.168.101.42:6380 \ 192.168.101.43:6380 \ --cluster-replicas 1系统会输出槽位分配,输入 yes 确认。看到以下输出即成功:text[OK] All 16384 slots covered.四、数据持久化配置详解4.1 双重持久化策略:AOF + RDBAOF 每秒同步:appendfsync everysec 最多丢失 1 秒数据。重启优先使用 AOF 恢复,数据更完整。AOF 重写:自动压缩,避免文件过大。4.2 验证持久化是否生效# 写入测试数据 redis-cli -c -h 192.168.101.41 -p 6379 -a 'redispasswd' set test_key "test_value" # 检查持久化文件 ls -la /data/redis-cluster/6379/data/ # 应有 .rdb 和 .aof # 手动触发 AOF 重写 redis-cli -p 6379 -a 'redispasswd' BGREWRITEAOF五、重启与数据恢复验证方案5.1 重启单个 Redis 实例# 写入测试数据 redis-cli -c -h 192.168.101.41 -p 6379 -a 'redispasswd' set user:1001 "test1001" # 停止实例(使用 app 账号) su - app -s /bin/bash -c "/data/app/redis/bin/redis-cli -h 192.168.101.41 -p 6379 -a 'redispasswd' shutdown" # 重启 service redis-6379 restart # 验证数据 redis-cli -c -h 192.168.101.41 -p 6379 -a 'redispasswd' get user:1001 # 应返回 "test1001"5.2 模拟实例宕机(kill -9)# 写入 100 条数据 for i in {1..100}; do redis-cli -c -h 192.168.101.41 -p 6379 -a 'redispasswd' --no-auth-warning set "test:key:$i" "value_$i" 2>/dev/null printf "Progress: %3d/100\r" $i done echo -e "\n✅ 写入完成" # 强制杀死进程(查找 app 用户的进程) systemctl stop redis-6379 redis-6380 # 重启 systemctl restart redis-6379 redis-6380 # 查询所有节点的key总数 echo "=== 分别查询每个节点 ===" for node in 192.168.101.41 192.168.101.42 192.168.101.43; do count=$(redis-cli -h $node -p 6379 -a 'redispasswd' --no-auth-warning keys "test:key:*" 2>/dev/null | wc -l) echo "$node:6379 - $count 条" done echo "" echo "总计:32 + 30 + 38 = 100 条 ✅"5.3 整机重启(模拟断电/维护)前提:已配置 systemd 开机自启。# 重启前写入标记 redis-cli -c -h 192.168.101.41 -p 6379 -a 'redispasswd' set after_reboot_test "data_before_reboot" # 重启服务器 reboot # 重启后检查 systemctl status redis-6379 redis-6380 redis-cli -c -h 192.168.101.41 -p 6379 -a 'redispasswd' cluster info | grep cluster_state # 应为 ok redis-cli -c -h 192.168.101.41 -p 6379 -a 'redispasswd' get after_reboot_test # 应返回原值5.4 主节点故障自动转移(高可用)# 写入 1000 条数据 for i in {1..1000}; do redis-cli -c -h 192.168.101.41 -p 6379 -a 'redispasswd' set hatest:$i "payload_$i" done # 关闭主节点 192.168.101.41:6379 redis-cli -h 192.168.101.41 -p 6379 -a 'redispasswd' shutdown # 等待 15 秒,查看哪个从节点被提升 redis-cli -h 192.168.101.42 -p 6379 -a 'redispasswd' cluster nodes # 数据验证(连接新主节点) redis-cli -c -h 192.168.101.42 -p 6380 -a 'redispasswd' get hatest:500六、常用管理与监控命令6.1 集群状态检查redis-cli -c -h 192.168.101.41 -p 6379 -a 'redispasswd' > cluster info > cluster nodes > cluster slots6.2 单节点管理# 停止节点(使用 app 账号) su -s /bin/bash -c "/data/app/redis/bin/redis-cli -h 192.168.101.41 -p 6379 -a 'redispasswd' shutdown" app # 启动节点 su -s /bin/bash -c "/data/app/redis/bin/redis-server /data/redis-cluster/6379/conf/redis.conf" app # 查看日志 tail -f /data/redis-cluster/6379/logs/redis.log6.3 数据持久化验证ls -lh /data/redis-cluster/*/data/*.aof redis-cli -h 192.168.101.41 -p 6379 -a 'redispasswd' BGSAVE redis-cli -h 192.168.101.41 -p 6379 -a 'redispasswd' BGREWRITEAOF七、故障排查清单🔴 问题1:重启后节点未自动加入集群确保 cluster-config-file 目录可写且属主为 app检查网络:telnet 192.168.101.42 6379手动握手:redis-cli -h 192.168.101.42 -p 6379 -a 'redispasswd' CLUSTER MEET 192.168.101.41 6379🔴 问题2:数据恢复不完整检查 appendonly yes 是否配置修复 AOF:redis-check-aof --fix /path/to/appendonly.aof🔴 问题3:集群状态为 FAIL检查所有节点是否运行:ps aux | grep redis-server检查防火墙端口(包括 16379、16380)等待足够节点恢复后集群自动恢复🔴 问题4:权限不足导致启动失败检查目录权限:ls -la /data/redis-cluster(应为 app:app)检查 PID 目录权限:ls -la /var/run/redis-cluster使用 su 命令切换用户启动,或通过 systemd(已配置 User=app)启动八、Redis 集群版本升级方案(不停服滚动升级)8.1 升级前准备8.1.1 环境检查# 记录当前版本(三台机器) /data/app/redis/bin/redis-server --version # 记录集群状态 redis-cli -a 'redispasswd' --cluster check 192.168.101.41:6379 # 备份当前二进制及配置文件(三台机器) tar -czf /data/backup/redis-$(date +%Y%m%d)-bin.tar.gz /data/app/redis/ cp -r /data/redis-cluster /data/backup/redis-cluster-$(date +%Y%m%d)8.1.2 下载目标版本(以升级到 7.4.0 为例)cd /data/app/src wget https://download.redis.io/releases/redis-7.4.0.tar.gz tar -zxvf redis-7.4.0.tar.gz cd redis-7.4.0 # 编译 make8.2.1 升级从节点(以 192.168.101.41:6380 为例)# 1. 确认当前角色为从节点 redis-cli -h 192.168.101.41 -p 6380 -a 'redispasswd' role # 预期输出中 "role" 为 "slave" # 2. 停止旧版本实例 systemctl stop redis-6380 # 3. 替换二进制文件 mv /data/app/redis/bin /data/app/redis/bin.bak-$(date +%Y%m%d) mkdir -p /data/app/redis/bin cp /data/app/src/redis-7.4.0/src/{redis-server,redis-cli,redis-check-aof,redis-check-rdb,redis-sentinel} /data/app/redis/bin/ # 4. 验证新版本 /data/app/redis/bin/redis-server --version # 5. 启动新版本实例 systemctl start redis-6380 # 6. 验证同步状态 redis-cli -h 192.168.101.41 -p 6380 -a 'redispasswd' info replication | grep -E "role|master_link_status"8.2.2 执行主从切换(可选,如需升级主节点)# 手动触发故障转移,将从节点提升为主节点 redis-cli -h 192.168.101.41 -p 6380 -a 'redispasswd' cluster failover # 等待切换完成(约 5-10 秒) sleep 10 # 验证新主节点 redis-cli -h 192.168.101.41 -p 6380 -a 'redispasswd' role # 预期 "role" 变为 "master"8.2.3 升级原主节点(现在已降级为从节点)# 此时原主节点 6379 已变为从节点,重复 8.2.1 步骤升级 systemctl stop redis-6379 # ... 替换二进制 ... systemctl start redis-63798.2.4 依次升级其他机器机器升级顺序建议192.168.101.416380(从)→ 6379(原主)192.168.101.426380(从)→ 6379(原主)192.168.101.436380(从)→ 6379(原主)8.3 升级后验证8.3.1 集群健康检查# 检查集群状态 redis-cli -a 'redispasswd' --cluster check 192.168.101.41:6379 # 验证所有节点版本 for port in 6379 6380; do echo "=== 192.168.101.41:$port ===" redis-cli -h 192.168.101.41 -p $port -a 'redispasswd' info server | grep redis_version done8.3.2 数据完整性验证# 查询所有节点的key总数 echo "=== 分别查询每个节点 ===" for node in 192.168.101.41 192.168.101.42 192.168.101.43; do count=$(redis-cli -h $node -p 6379 -a 'redispasswd' --no-auth-warning keys "test:key:*" 2>/dev/null | wc -l) echo "$node:6379 - $count 条" done echo "" echo "总计:32 + 30 + 38 = 100 条 ✅"8.4 回滚方案(升级失败时)8.4.1 快速回滚(保留原二进制备份)# 停止问题实例 systemctl stop redis-6379 # 恢复旧版本二进制 rm -rf /data/app/redis/bin mv /data/app/redis/bin.bak-YYYYMMDD /data/app/redis/bin # 重启实例 systemctl start redis-63798.4.2 全量回滚(保留配置和数据)# 停止所有实例 systemctl stop redis-6379 redis-6380 # 恢复完整环境(从备份) rm -rf /data/app/redis tar -xzf /data/backup/redis-YYYYMMDD-bin.tar.gz -C / # 重启所有实例 systemctl start redis-6379 redis-63808.5 升级注意事项风险点应对措施客户端协议不兼容升级前确认业务使用的 Redis 命令未被废弃或变更RDB/AOF 加载失败升级前在测试环境验证,生产环境先升级单节点观察集群脑裂滚动升级期间避免同时重启多个主节点密码/ACL 变更新版本可能引入 ACL 规则变化,检查 requirepass 与 masterauth模块兼容性如使用了 Redis Module(如 RediSearch),需同步升级模块8.6 升级检查清单- [ ] 已记录当前版本与集群状态 - [ ] 已完成二进制及配置文件备份 - [ ] 已在测试环境完成版本兼容性验证 - [ ] 已通知业务方升级时间窗口 - [ ] 已准备回滚脚本与备份文件 - [ ] 滚动升级过程中每完成一个节点均验证同步状态 - [ ] 升级后完成集群健康检查与数据抽样验证 - [ ] 已更新运维文档中的版本信息
2026年05月10日
108 阅读
0 评论
0 点赞
2026-03-28
NFSv4服务搭建
1. 安装NFS服务端 yum install nfs-utils -y2. 创建并配置共享目录mkdir /data/nfs3.修改 /etc/exports 配置文件vim /etc/exports 在文件末尾添加一行,指定要共享的目录、允许的客户端网段和权限: /data/nfs 192.168.137.200(rw,sync,no_root_squash,fsid=0) \ 192.168.137.201(rw,sync,no_root_squash,fsid=0) \ 192.168.137.202(rw,sync,no_root_squash,fsid=0)参数说明fsid=0NFSv4 必需。标识根文件系统,NFSv4 通过此参数识别导出的根no_root_squash允许客户端 root 用户保留服务器端 root 权限rw读写权限sync同步写入,保证数据一致性4.重启服务# 重启 NFS 服务 systemctl restart nfs-server # 查看当前导出状态 exportfs -v5. 配置防火墙(NFSv4 只需开放 2049 端口)NFSv4 的优势:仅需 TCP 2049 端口!# firewalld(CentOS/RHEL) firewall-cmd --permanent --add-port=2049/tcp firewall-cmd --reload6. 客户端挂载与验证在客户端安装 NFS 支持:# CentOS/RHEL yum install nfs-utils -y挂载 NFSv4 共享:# 创建挂载点 mkdir /mnt/nfs_test # NFSv4 挂载(注意 vers=4 参数) mount -t nfs -o vers=4 192.168.137.3:/ /mnt/nfs_testdf -h验证[root@master ~]# df -h | grep nfs df: /mnt/nfs_client: Stale file handle 192.168.137.3:/ 119G 37G 76G 33%cd /mnt/nfs_test7.开机启动挂载sudo vim /etc/fstab # 在文件末尾添加以下内容: 192.168.137.3:/ /mnt/nfs_test nfs vers=4,noatime,hard,intr,_netdev 0 0 # 验证 umount /mnt/nfs_test mount -a
2026年03月28日
118 阅读
0 评论
0 点赞
2026-03-15
Scrutiny :一款基于web端的硬盘状态查看与监控工具
🔍 Scrutiny 是什么?Scrutiny 是一个专注于硬盘健康状况的开源监控工具。你可以把它想象成一个为硬盘准备的“健康监测中心”,它通过读取和分析硬盘的 S.M.A.R.T. 数据,为你提供一个清晰、美观的 Web 界面,让你能实时掌握每一块硬盘的状态、性能和潜在风险。它的核心亮点是:专业的数据分析:深入分析 S.M.A.R.T. 属性,不仅看当前值,还能追踪历史趋势,帮你判断硬盘是正常老化还是即将故障。智能预警系统:可以为不同的硬盘类型(如ATA、NVMe)设置告警阈值。一旦发现异常(比如温度过高、坏道增多),它能及时发出警报,让你有机会在数据丢失前采取行动。美观的可视化界面:它内置的仪表盘非常直观,可以一目了然地看到所有硬盘的健康状态概览,并支持深入查看每一块硬盘的详细报告和历史图表。灵活的部署方式:支持 Docker 一键部署,也支持在各种操作系统上手动安装,可以轻松实现多台主机的集中监控。🐳 Docker 部署 Scrutiny(一体化模式)你希望用 Docker 部署,这是最快、最省心的方式。官方推荐使用“一体化”(Omnibus)Docker 镜像,它把 Web 界面和后端数据收集都打包在了一个容器里,非常适合个人或家庭服务器使用。1. 准备工作在你的 Linux 服务器上,确保已经安装了 docker 和 docker-compose。2. 创建 docker-compose.yml 文件在你喜欢的目录下(例如 ~/scrutiny)创建一个名为 docker-compose.yml 的文件,并写入以下内容:version: '3.5' services: scrutiny: container_name: scrutiny image: ghcr.io/analogj/scrutiny:master-omnibus cap_add: - SYS_RAWIO # 获取机械硬盘的S.M.A.R.T 信息,默认即可 - SYS_ADMIN # 获取NVMe硬盘的S.M.A.R.T 信息,没有可以删除 ports: - "8183:8080" # webapp - "8184:8086" # influxDB admin(可以不映射) volumes: - /run/udev:/run/udev:ro - ./config:/opt/scrutiny/config - ./influxdb:/opt/scrutiny/influxdb devices: - "/dev/sda" - "/dev/sdb" - "/dev/sdc" - "/dev/sdd" - "/dev/sde"配置关键点说明:ports: 将容器的 8080 端口映射到宿主机的 8183 端口(你可以修改左侧端口避免冲突)。volumes: 挂载了主机的 udev 信息,这是容器正确识别你硬盘设备的关键。同时,也挂载了配置和数据目录到本地,方便备份和修改。devices: 这一步非常关键!你需要在这里列出所有想要监控的硬盘设备。把 /dev/sda、/dev/sdb 替换成你机器上实际的设备路径(可以通过 lsblk 命令查看)。cap_add: 添加 SYS_RAWIO 能力,赋予容器读取硬盘 SMART 数据所需的权限。environment: 设置环境变量,让这个容器同时运行 Web 服务和数据收集器(Collector)。3. 启动服务在 docker-compose.yml 文件所在的目录下,运行以下命令来启动服务:docker-compose up -d4. 访问 Web 界面服务启动后,在浏览器里打开 http://<你的Linux服务器IP>:8183(如果你修改了端口,请使用对应的端口)。稍等片刻(数据收集需要点时间),你就能看到一个漂亮的 Scrutiny 仪表盘了。界面加载后,你会看到所有被识别到的硬盘概览,绿色代表健康,黄色或红色则代表有需要关注的异常。点击任意一块硬盘,就能进入详情页,查看该硬盘完整的 S.M.A.R.T. 属性数据、温度变化曲线和历史故障记录。如果硬盘真的出了问题,这里就是第一手的“诊断报告”。5 如何实现 Scrutiny 汉化获取汉化文件你可以从以下网盘链接下载由用户“我是笨蛋小扁担”制作的汉化包:链接: https://pan.baidu.com/s/1djpIcCJB2XAClQw1Q8miEg (提取码: cnfb)在 Docker 部署中应用汉化准备目录:在与你 Scrutiny 容器映射的 config、data 目录同级的位置,创建一个名为 web 的新目录。放置文件:将下载的汉化压缩包内的所有文件解压到刚刚创建的 web 目录中。修改 Docker Compose 配置:在你原来的 docker-compose.yml 文件中,为 scrutiny 服务增加一个卷(volume)映射,将本地的 web 目录挂载到容器内的 /opt/scrutiny/web。添加的配置行如下:yamlversion: '3.5' services: scrutiny: container_name: scrutiny image: ghcr.io/analogj/scrutiny:master-omnibus cap_add: - SYS_RAWIO # 获取机械硬盘的S.M.A.R.T 信息,默认即可 - SYS_ADMIN # 获取NVMe硬盘的S.M.A.R.T 信息,没有可以删除 ports: - "8183:8080" # webapp - "8184:8086" # influxDB admin(可以不映射) volumes: - /run/udev:/run/udev:ro - ./config:/opt/scrutiny/config - ./influxdb:/opt/scrutiny/influxdb - ./web:/opt/scrutiny/web # 👈 新增这一行 devices: - "/dev/sda" - "/dev/sdb" - "/dev/sdc" - "/dev/sdd" - "/dev/sde"重建容器:保存文件后,在 docker-compose.yml 所在目录下执行 docker-compose down 和 docker-compose up -d 重新创建容器。参考资料Scrutiny 硬盘 S.M.A.R.T 可视化工具 - 踩坑、简体中文汉化 – 我是笨蛋小扁担
2026年03月15日
273 阅读
0 评论
0 点赞
2026-03-14
Copyparty:高颜值文件服务器(功能炸裂的“瑞士军刀”)(python -m强大模块)
零、Copyparty 深度介绍1. 核心哲学:极简到离谱的部署单文件即服务:整个服务器就是一个 Python 文件 (copyparty-sfx.py) 或 Windows 下的 .exe 文件,没有任何依赖,下载即用。开箱即用:无需配置数据库、无需安装复杂的依赖包,30秒内就能启动一个功能完整的文件服务器。兼容性怪兽:Python 版本:从 Python 2.7 到最新的 Python 3.x 都能运行。操作系统:Windows、Linux、macOS 是基本功,连 Windows 2000、Android(通过 Termux)、树莓派、甚至路由器都能跑。浏览器:从现代的 Chrome、Firefox,到古董级的 IE4、PSP 内置浏览器,都能访问它的 Web 界面。2. 核心功能:强得不像一个文件Copyparty 最让人着迷的是它那些超越普通文件分享的“黑科技”:功能类别具体特性体验与优势🚀 传输黑科技断点续传 (up2k 协议)上传大文件时,即使网络中断、浏览器崩溃甚至电脑重启,恢复后只需再次拖入同一个文件,它就能从中断处继续,而不是从头再来。 边传边下 (Race the Beam)上传者这边还在上传,接收方那边就可以开始下载了。上传进度即下载进度,非常适合团队紧急共享大文件。📺 媒体处理强悍的媒体能力自动为图片、视频和音频文件生成缩略图和波形图。内置的音乐播放器支持几乎所有常见格式(MP3、FLAC、AAC等),并支持实时转码,确保在任何浏览器上都能播放。🔍 搜索与去重全文搜索不仅能搜文件名,还能直接搜索文件内容里的关键词,比如在一堆 PDF 或 Word 文档里找一句话,这功能通常只有专业的文档管理系统才有。 智能去重当上传重复文件时,它不会傻傻地再存一份,而是指向已有的那份,帮你节省大量硬盘空间。🌐 多协议支持不止是 Web除了通过浏览器访问,它还原生支持 WebDAV、FTP(S)、TFTP、SMB。这意味着你可以直接把共享文件夹映射为电脑的本地磁盘来用。📦 一、安装# 使用pip安装 pip install copyparty # 如果需要增强功能(图片缩略图、音频元数据等),可以安装可选依赖 pip install copyparty[all] # 安装所有可选依赖 # 或者单独安装 pip install pillow # 图片缩略图支持 pip install mutagen # 音频元数据支持安装完成后,copyparty 命令就会添加到你的系统路径中。🚀 二、启动服务最简单启动python -m copyparty这会在当前目录启动服务,默认端口 3923,任何人都可以浏览、下载和上传文件。启动效果$ python -m copyparty Serving on http://0.0.0.0:3923 - Local: http://127.0.0.1:3923 - LAN: http://192.168.1.100:3923 - QR code: 扫描二维码用手机访问 Press Ctrl+C to stop常用启动参数场景命令说明局域网共享(读写)copyparty -v .:rw当前目录允许上传和下载自定义端口copyparty -p 8080使用8080端口启动指定共享目录copyparty -v D:\Share:rw共享指定目录只读模式copyparty -v .:r只能下载,不能上传带密码保护copyparty -a 用户名:密码 -v .:rw,用户名需要登录才能访问开启所有高级功能copyparty -e2dsa -e2ts启用搜索和音乐索引🌐 三、访问界面启动后,用浏览器访问:本机访问:http://localhost:3923局域网访问:http://你的IP:3923(如 http://192.168.1.100:3923)Web界面长什么样?🔧 四、实际使用示例示例1:快速共享当前目录(读写)# 在要共享的目录下执行 cd C:\Users\vin\Desktop\share python -m copyparty -v .:rw示例2:带密码的私人共享# 创建用户,设置权限 python -m copyparty -a alice:123456 -v ./private:rw,alice # 说明:-a 创建用户,-v 挂载目录,rw,alice 表示只有alice可读写示例3:音乐库服务器(带索引和播放)python -m copyparty -e2dsa -e2ts -v D:\Music:/music:r # 访问 http://localhost:3923/music 即可在线听歌示例4:临时接收文件(匿名上传,不暴露已有文件)python -m copyparty -v ./incoming:dropbox:w,G:c,fk=4 # - dropbox 特殊模式:匿名上传,不上传不能浏览 # - w 允许上传 # - G 上传后生成访问密钥 # - fk=4 密钥长度4位🎯 五、常用命令速查表命令作用copyparty默认启动(当前目录,端口3923)copyparty -p 8080指定端口copyparty -v D:\data:rw共享指定目录并允许读写copyparty -a user:pass添加用户认证copyparty --help查看所有参数copyparty --version查看版本
2026年03月14日
147 阅读
0 评论
0 点赞
2026-03-14
Windows netsh 端口转发完全指南[临时暴露内网服务解决方案
Windows netsh 端口转发完全指南[临时暴露内网服务解决方案netsh (Network Shell) 是 Windows 系统自带的强大网络配置命令行工具,其中的 interface portproxy 组件可以实现系统级的端口转发功能。📋 一、什么是 netsh 端口转发?端口转发是指将发往本机某个端口的网络流量,自动重定向到另一个目标地址和端口的过程。而 netsh 实现的是系统内核级别的端口转发,在 TCP/IP 协议栈层面完成流量转发。核心特点特性说明无需安装Windows 系统原生支持(Windows XP/Vista/7/8/10/11/Server 全系列)系统级转发在内核层面完成,对应用程序透明TCP 协议支持只支持 TCP 协议(不支持 UDP、ICMP 等)持久性规则永久生效(直到手动删除或系统重置)支持 IPv4 和 IPv6支持 v4tov4、v4tov6、v6tov4、v6tov6 四种组合🚀 二、核心命令详解2.1 添加端口转发规则基本语法:netsh interface portproxy add v4tov4 listenaddress=本地IP listenport=本地端口 connectaddress=目标IP connectport=目标端口参数说明:参数必填说明示例listenaddress否本机监听的IP地址192.168.1.100 或 0.0.0.0(所有接口)listenport是本机监听的端口8080connectaddress是目标服务器IP或域名10.0.0.5 或 example.comconnectport是目标服务器端口80常用示例:转发到内网服务器netsh interface portproxy add v4tov4 listenport=8080 connectaddress=192.168.1.100 connectport=80指定监听IP(多网卡环境)netsh interface portproxy add v4tov4 listenaddress=192.168.1.10 listenport=8080 connectaddress=10.0.0.5 connectport=3389IPv6 到 IPv4 转发netsh interface portproxy add v6tov4 listenport=8080 connectaddress=192.168.1.100 connectport=80转发到外部域名netsh interface portproxy add v4tov4 listenport=443 connectaddress=www.example.com connectport=4432.2 查看转发规则查看所有规则:netsh interface portproxy show all查看特定类型规则:netsh interface portproxy show v4tov4 netsh interface portproxy show v4tov6 netsh interface portproxy show v6tov4 netsh interface portproxy show v6tov6输出示例:侦听 ipv4: 连接到 ipv4: 地址 端口 地址 端口 --------------- ---------- --------------- ---------- 192.168.1.10 8080 10.0.0.5 3389 0.0.0.0 443 192.168.1.100 4432.3 删除转发规则删除单条规则:netsh interface portproxy delete v4tov4 listenaddress=192.168.1.10 listenport=8080批量删除:# 删除所有 v4tov4 规则 netsh interface portproxy reset🔧 三、完整实战案例场景1:远程桌面(RDP)转发将内网机器 A(192.168.1.100)的远程桌面(3389)通过本机(192.168.1.10)的 13389 端口暴露给外网。cmd# 1. 添加转发规则(管理员权限) netsh interface portproxy add v4tov4 listenport=13389 connectaddress=192.168.1.100 connectport=3389 # 2. 检查规则 netsh interface portproxy show all # 3. 开放防火墙端口 netsh advfirewall firewall add rule name="RDP Forward 13389" dir=in action=allow protocol=TCP localport=13389 # 4. 验证转发 # 从外网访问:你的公网IP:13389场景2:Web 服务临时共享将内网开发服务器(10.0.0.50:3000)的 Web 应用通过本机 8080 端口临时分享给团队。# 添加转发 netsh interface portproxy add v4tov4 listenport=8080 connectaddress=10.0.0.50 connectport=3000 # 开放防火墙 netsh advfirewall firewall add rule name="Web Share 8080" dir=in action=allow protocol=TCP localport=8080 # 通知同事访问:你的IP:8080场景3:多端口转发脚本创建一个批处理文件 setup_forward.bat:@echo off echo 正在设置端口转发规则... :: 转发 Web 服务 netsh interface portproxy add v4tov4 listenport=8080 connectaddress=192.168.1.101 connectport=80 :: 转发远程桌面 netsh interface portproxy add v4tov4 listenport=13389 connectaddress=192.168.1.102 connectport=3389 :: 转发数据库 netsh interface portproxy add v4tov4 listenport=3306 connectaddress=192.168.1.103 connectport=3306 :: 开放防火墙端口 for %%p in (8080 13389 3306) do ( netsh advfirewall firewall add rule name="Forward Port %%p" dir=in action=allow protocol=TCP localport=%%p ) echo 转发规则设置完成! netsh interface portproxy show all pause⚠️ 四、常见问题与解决方案问题1:转发不生效症状:规则添加成功,但访问失败排查步骤:# 1. 检查转发规则是否存在 netsh interface portproxy show all # 2. 检查防火墙是否开放端口 netsh advfirewall firewall show rule name="你的规则名" # 3. 检查端口监听状态 netstat -ano | findstr :8080 # 4. 检查 IP 路由是否启用 netsh interface ipv4 show interfaces # 需要确认"转发"状态为"已启用"问题2:只能本地访问,外部无法访问原因:listenaddress 设置了具体 IP 但防火墙或网络策略限制解决:# 修改为监听所有接口 netsh interface portproxy delete v4tov4 listenaddress=192.168.1.10 listenport=8080 netsh interface portproxy add v4tov4 listenaddress=0.0.0.0 listenport=8080 connectaddress=10.0.0.5 connectport=80问题3:重启后规则消失原因:没有将规则保存为持久化配置解决:创建启动脚本# 创建 startup_forward.bat,放入启动文件夹 # shell:startup 打开启动文件夹 @echo off netsh interface portproxy add v4tov4 listenport=8080 connectaddress=192.168.1.100 connectport=80
2026年03月14日
172 阅读
0 评论
0 点赞
2026-03-14
Java try-with-resources 介绍
Java try-with-resources 介绍1. 什么是 try-with-resources?try-with-resources 是 Java 7 引入的一个特性,用于自动管理资源(如文件流、数据库连接、网络连接等)。它确保每个资源在语句结束时自动关闭,无需显式编写 finally 块。优点:代码简洁:减少样板代码安全可靠:自动确保资源关闭异常处理更完善:保留原始异常,关闭异常作为抑制异常可读性更好:清晰地看到资源声明和使用范围2. 基本语法try (ResourceType resource = new ResourceType()) { // 使用资源的代码 } catch (ExceptionType e) { // 异常处理 }3. 工作原理资源必须实现 AutoCloseable 或 Closeable 接口在 try 块结束后,资源会按照声明的相反顺序自动关闭资源关闭操作在 finally 块之前执行4. 支持多资源try (FileInputStream fis = new FileInputStream("input.txt"); FileOutputStream fos = new FileOutputStream("output.txt")) { byte[] buffer = new byte[1024]; int length; while ((length = fis.read(buffer)) > 0) { fos.write(buffer, 0, length); } } catch (IOException e) { e.printStackTrace(); }5. 异常处理机制try-with-resources 提供了更优雅的异常处理机制:public class ResourceExample { static class Resource1 implements AutoCloseable { public void use() throws Exception { throw new Exception("异常发生在使用资源时"); } @Override public void close() throws Exception { throw new Exception("异常发生在关闭资源时"); } } public static void main(String[] args) { try (Resource1 r1 = new Resource1()) { r1.use(); } catch (Exception e) { System.out.println("捕获的异常: " + e.getMessage()); Throwable[] suppressed = e.getSuppressed(); System.out.println("被抑制的异常数量: " + suppressed.length); } } }6. 实际应用示例文件操作示例import java.io.*; public class FileCopyExample { public static void copyFile(String source, String dest) { // 传统方式 /* FileInputStream fis = null; FileOutputStream fos = null; try { fis = new FileInputStream(source); fos = new FileOutputStream(dest); byte[] buffer = new byte[1024]; int length; while ((length = fis.read(buffer)) > 0) { fos.write(buffer, 0, length); } } catch (IOException e) { e.printStackTrace(); } finally { try { if (fis != null) fis.close(); if (fos != null) fos.close(); } catch (IOException e) { e.printStackTrace(); } } */ // try-with-resources 方式 try (FileInputStream fis = new FileInputStream(source); FileOutputStream fos = new FileOutputStream(dest)) { byte[] buffer = new byte[1024]; int length; while ((length = fis.read(buffer)) > 0) { fos.write(buffer, 0, length); } } catch (IOException e) { e.printStackTrace(); } } }数据库连接示例import java.sql.*; public class DatabaseExample { public static void queryDatabase() { String url = "jdbc:mysql://localhost:3306/mydb"; String user = "root"; String password = "password"; // 自动管理 Connection, Statement, ResultSet try (Connection conn = DriverManager.getConnection(url, user, password); Statement stmt = conn.createStatement(); ResultSet rs = stmt.executeQuery("SELECT * FROM users")) { while (rs.next()) { System.out.println(rs.getString("username")); } } catch (SQLException e) { e.printStackTrace(); } } }8. Java 9 增强功能Java 9 允许在 try-with-resources 中使用 effectively final 的变量:public class Java9Example { public static void main(String[] args) throws Exception { // Java 9 之前 try (FileReader reader1 = new FileReader("file1.txt"); FileReader reader2 = new FileReader("file2.txt")) { // 使用资源 } // Java 9 及之后 FileReader reader1 = new FileReader("file1.txt"); FileReader reader2 = new FileReader("file2.txt"); // reader1 和 reader2 必须是 effectively final try (reader1; reader2) { // 使用资源 } } }9. 注意事项资源类必须实现 AutoCloseable 或 Closeable 接口资源在 try 块结束后自动关闭,无论是否发生异常多个资源按声明相反顺序关闭如果有多个异常,只有第一个异常被抛出,其他异常被抑制
2026年03月14日
71 阅读
0 评论
0 点赞
2026-03-10
Trilium Notes:个人笔记/个人知识库的开源神器
1.Trilium Notes 详细介绍Trilium Notes 是一款开源、免费、支持自部署的层级化知识管理软件。简单来说,它是一个专门为构建个人知识库(俗称"第二大脑")而设计的强大工具。1.1 核心定位与普通的笔记软件不同,Trilium 的设计理念是帮助你像管理文件系统一样管理知识。如果你觉得普通笔记本(如印象笔记)的笔记本-笔记两级结构不够用,或者觉得双链笔记(如 Obsidian)的网状结构过于自由而难以驾驭,Trilium 提供了一个介于两者之间的树状结构解决方案。1.2 核心特色1. 无限层级的树状结构这是 Trilium 最显著的特点。你可以像在电脑上创建文件夹一样,无限层级地组织笔记:📁 知识库 ├── 📁 编程学习 │ ├── 📁 前端 │ │ ├── 📄 React 笔记 │ │ └── 📄 Vue 笔记 │ └── 📁 后端 │ ├── 📄 Python │ └── 📄 数据库设计 ├── 📁 项目管理 │ ├── 📄 方法论 │ └── 📁 实际案例 └── 📁 生活记录 └── 📄 旅行日记💡 为什么重要:这种结构符合人类自然的分类思维,特别适合整理有明确归属关系的知识体系。2. 笔记克隆功能这是 Trilium 最强大的特性之一。一篇笔记可以同时出现在多个位置(类似于文件快捷方式或标签功能),但内容只有一份:示例:一篇关于"Python 装饰器"的笔记,既可以放在"编程语言/Python"目录下,又可以同时出现在"设计模式/Python实现"目录下更新同步:修改其中任何一个位置的笔记内容,所有克隆都会同步更新适用场景:一篇笔记涉及多个主题,或者需要多维度分类时非常实用3. 丰富的笔记类型Trilium 不只支持普通的富文本笔记,还内置了多种特殊类型:笔记类型用途文本笔记标准富文本编辑,支持表格、图片、待办清单等Markdown纯文本 Markdown 编辑代码笔记语法高亮,可直接运行部分代码画板笔记内置 Excalidraw,可以手绘流程图、思维导图关系图可视化展示笔记之间的连接关系书签保存网页链接文件直接存储 PDF、图片等文件4. 强大的搜索与脚本能力全文搜索:支持高级搜索语法(如 note.title:"Python" AND ~30d 表示搜索近30天内修改的标题含Python的笔记)脚本自动化:支持 JavaScript 脚本,可以:批量修改笔记属性自动生成日报/周报从外部 API 拉取数据生成笔记自定义导出格式5. 多端同步与加密同步机制:通过自部署的服务器,实现桌面端、移动端(Web 端)之间的笔记同步端到端加密:笔记在传输和存储时都可以加密,保护隐私版本控制:自动保存笔记历史版本,可以随时回溯2.Docker Compose 部署 (推荐)2.1 创建部署目录在你的服务器或NAS上创建一个目录,例如 trilium-cn,并进入该目录。2.2 创建 docker-compose.yml 文件在该目录下新建一个名为 docker-compose.yml 的文件,并将以下内容复制进去:version: '3' services: trilium-cn: image: nriver/trilium-cn:latest container_name: trilium-cn restart: always ports: - "8080:8080" # 左边端口可自定义,如 8070:8080 volumes: # 将当前目录下的 data 文件夹挂载到容器内,用于持久化存储你的笔记 - ./trilium-data:/root/trilium-data environment: # 告诉容器数据存储在哪里,必须与 volumes 中的容器内路径一致 - TRILIUM_DATA_DIR=/root/trilium-data2.3启动容器在 docker-compose.yml 所在目录下,打开终端并运行命令 docker-compose up -d 即可在后台启动服务。3.访问测试
2026年03月10日
186 阅读
0 评论
0 点赞
2025-12-26
解决 npm 全局安装后找不到命令的问题
解决 npm 全局安装后找不到命令的问题0.示例使用 npm 全局安装包后命令找不到时,通常是由于环境变量配置问题或 npm 配置路径不一致导致的。npm install -g asar asar -V # 提示找不到命令1.检查 npm 配置路径首先,检查 npm 的全局安装路径和缓存路径是否正确。npm config get prefix npm config get cache如果路径不正确,可以通过以下命令设置正确的路径:npm config set prefix "C:\Users\Administrator\AppData\Roaming\npm" npm config set cache "C:\Users\Administrator\AppData\Local\npm-cache"2.添加环境变量确保将 npm 的全局安装路径添加到系统环境变量中(prefix对应的值)。打开系统属性,选择“高级系统设置”。点击“环境变量”按钮。在“系统变量”中找到 Path,并编辑它。添加 npm 全局安装路径,例如 C:\Users\Administrator\AppData\Roaming\npm。3.验证asar -V v3.2.0
2025年12月26日
161 阅读
0 评论
0 点赞
2025-08-10
nginx编译安装
1.依赖安装yum install -y gcc-c++ pcre pcre-devel zlib zlib-devel openssl openssl-devel2.下载安装包并解压官网地址:https://nginx.orgwget https://nginx.org/download/nginx-1.27.2.tar.gztar -zxvf nginx-1.27.2.tar.gz cd nginx-1.27.23.开始编译安装./configure --with-http_ssl_module make && make install安装完成后的安装目录在/usr/local/nginx4.配置开机启动项cd /usr/local/ngin useradd nginx vim nginx.service[Unit] Description=nginx After=network.target [Service] User=nginx Group=nginx Type=forking ExecStart=/usr/local/nginx/sbin/nginx ExecReload=/usr/local/nginx/sbin/nginx -s reload ExecStop=/usr/local/nginx/sbin/nginx -s quit PrivateTmp=true [Install] WantedBy=multi-user.targetln -s /usr/local/nginx/nginx.service /usr/lib/systemd/system/nginx.service systemctl daemon-reload service nginx status service nginx restart service nginx status5.配置启动bin的软连接ln -s /usr/local/nginx/sbin/nginx /usr/bin/nginx# nginx -V nginx version: nginx/1.27.2 built by gcc 7.3.0 (GCC) built with OpenSSL 1.1.1f 31 Mar 2020 TLS SNI support enabled configure arguments: --with-http_ssl_module [root@oa-app-7 nginx]#参考资料nginx源码编译安装(详解) - penngke - 博客园 (cnblogs.com)nginx: downloadnginx配置https后报错nginx: [emerg] https protocol requires SSL support in XXX.conf详细解决方法-CSDN博客nginx 普通用户使用80端口启动nginx nginx: [emerg] bind() to 0.0.0.0:80 failed (13: Permission denied)_nginx 端口80普通用户-CSDN博客
2025年08月10日
220 阅读
1 评论
0 点赞
1
2
...
25