Shell脚本自动化部署Java项目:常用命令速查与排障实战
2. 脚本常用命令速查搞不定的先查表下面这张表是我在日常脚本里使用频率最高的命令每条都标注了实际用途和踩坑提醒建议收藏。命令批次用途我的提醒set -euxo pipefail脚本头部统一开启严格模式-x会打印每条命令生产环境建议去掉否则日志太吵date %Y%m%d%H%M%S生成时间戳用于版本号和备份目录不要在 Windows 上跑date 语法不兼容git rev-parse --short HEAD取当前提交短哈希拼进包名先确认在 git 仓库内执行不然报错mvn -q clean package -DskipTests跳过测试快速打包-q静默模式能少刷一大半日志scp file userhost:/path推送构建产物到目标机注意目标路径的写权限否则报 Permission deniedssh userhost command远程执行命令双引号里的$会被本地 shell 吃掉需要转义rsync -avz --delete增量同步文件目录--delete慎用会删目标端多余文件ln -sfn new old软链接原子切换版本-n参数很关键避免链接套链接nohup java -jar app.jar app.log 21 后台启动 Java 应用一定要重定向日志否则 stdout 会把终端撑爆curl -s -o /dev/null -w %{http_code} http://localhost:8080/actuator/health健康检查应用要暴露健康检查端点才有意义4.4 启动脚本与健康检查启动成功不等于可用部署链路里最容易混过去的一步就是启动。很多人在脚本里写nohup java -jar xxx.jar 就觉得完事了结果应用 JVM 起来了端口没监听或者 Spring 容器还没初始化完成流量已经切过来了。这种假启动在生产环境是要出大事的。我的启动脚本里有一个固定单元分三步走# 4.1 启动应用 nohup java -Xms512m -Xmx1024m -jar $APP_HOME/$APP_NAME $LOG_DIR/app.log 21 echo $! $APP_HOME/app.pid # 4.2 等待端口就绪最多 60s for i in $(seq 1 30); do if ss -tln | grep -q :$SERVER_PORT; then echo 端口监听正常 break fi sleep 2 done # 4.3 等待健康检查通过最多 120s for i in $(seq 1 30); do HTTP_CODE$(curl -s -o /dev/null -w %{http_code} http://127.0.0.1:$SERVER_PORT$HEALTH_PATH) if [ $HTTP_CODE 200 ]; then echo 健康检查通过 exit 0 fi sleep 4 done echo 健康检查超时部署失败 exit 1端口检测用ss而不是netstat新系统都自带 ss性能更好。健康检查推荐用 Spring Boot Actuator 的/actuator/health端点返回 200 才代表应用真的可用。注意这里有个细节健康检查是返回 200 了但可能是 Liveness 探针而不是 Readiness 探针如果服务还没完全准备好对外提供服务建议检查 readiness 状态。我自己踩过一次坑健康检查配的是 LivenessSpring 容器还在初始化 Bean 时端口就监听了恰好返回 200脚本认为部署成功结果上游服务疯狂报错。后来改成 Readiness 的/actuator/health/readiness才彻底解决。5. 常见坑位与排障实录说真的Shell 自动化脚本写起来容易但真正考验功底的是排障。我在这里把实际踩过的高频坑整理出来分门别类讲清楚原因和解决方案这些几乎都是网上搜不到的实战经验。5.1 Maven 构建内存溢出不是你代码的问题mvn package的时候突然报java.lang.OutOfMemoryError: PermGen space或者GC overhead limit exceeded大多数人第一反应是查代码、调 JVM 参数但你得先搞清楚Maven 本身跑在 JVM 里Maven 进程的内存配置和你的应用 JVM 完全不相干。Maven 默认的堆内存太小构建大型项目多模块、大量依赖时很容易触顶。解决方案是在构建命令里显式指定 MAVEN_OPTSexport MAVEN_OPTS-Xms512m -Xmx2048m -XX:MaxMetaspaceSize512m mvn clean package -DskipTests建议把这段写在构建脚本的头部而不是每个执行构建的终端手动配。如果你用 Jenkins 这类 CI 工具也要在全局配置里加 MAVEN_OPTS否则每次构建都吃默认值。另外一个隐蔽但是极其常见的坑clean阶段会把target目录整个删掉如果构建过程中某个模块失败前面已经编译好的模块产物也被清了导致排查问题的时候找不到现场。我习惯在构建脚本里把target/classes目录做一次快照备份少走很多冤枉路。5.2 中文乱码问题一次发布事故的复盘有次我在服务器上部署了一个新版本启动之后业务方反馈中文全是乱码。我把锅甩给了运维运维把锅甩给了开发最后查下来问题出在打包机上的环境变量。Maven 编译时用的源码编码由project.build.sourceEncoding决定这属于 pome.xml 范畴但运行时 JVM 读取文件的编码由file.encoding决定而这个值受操作系统 locale 影响。我在构建脚本里加了一行export LANGen_US.UTF-8 export LC_ALLen_US.UTF-8这能保证file.encoding是 UTF-8但还有个更稳妥的做法在启动脚本的 Java 参数里显式加-Dfile.encodingUTF-8。这两个地方都堵住中文乱码的坑基本就杜绝了。还有个容易忽略的点如果你用 GitHub Actions 或者其他云构建平台构建容器的默认 locale 五花八门一定要在构建脚本里统一设置 locale不然本地没问题的代码一上 CI 就乱码。5.3set -e的副作用脚本突然诡异退出set -e是一个非常好的命令表示任何命令返回非零退出码就立即退出。但它有个隐患在多管道场景下比如mvn package | tee build.logtee的退出码是 0即使 mvn 失败了整条管道的退出码也可能是 0set -e就失效了脚本继续往下走部署了一个残缺的包。解决方案有两个# 方案一关闭管道退出码掩盖 set -o pipefail set -e # 方案二关键步骤不用管道用临时文件 mvn clean package build.log 21 BUILD_EXIT_CODE$? if [ $BUILD_EXIT_CODE -ne 0 ]; then echo 构建失败退出码 $BUILD_EXIT_CODE exit $BUILD_EXIT_CODE fi我实际生产环境用的是方案一加方案二混合全局开set -euo pipefail在极端重要的步骤构建、部署额外检查退出码。这样既不漏错又能精准定位出错位置。5.4 权限与安全脚本不要裸奔在服务器上部署脚本一般要执行rm、scp、ssh这类高权限命令很多人直接把整个脚本放在 root 下跑或者将私钥文件 644 权限裸放在目录里这都是非常危险的事。我建议三步脚本归属专用部署账号不要用 root。如果是测试环境图省事至少把rm -rf这类命令限定在明确的目录路径里绝对禁止变量未展开时执行rm -rf $APP_HOME/如果变量为空这条命令会变成rm -rf /血泪教训。SSH 私钥权限设为 600放在~/.ssh目录并加上 passphrase配合 ssh-agent 使用。脚本里的敏感信息数据库密码、API Key不要硬编码改用环境变量或外部配置文件同时将配置文件加入.gitignore。另外一个小细节把脚本中所有绝对路径统一用变量定义在脚本头部用readonly修饰防止中途被其他脚本或误操作改写。6. 进阶玩法多环境、多模块、通知机制到这里基础链路已经通了但真实项目往往没那么简单。你可能有 dev、test、prod 三套环境可能是多模块项目还可能有十几个人在等部署结果。接下来讲三个高频进阶需求。6.1 多环境切换的优雅做法一个脚本通吃不要在脚本里写死服务器 IP 和目录用环境参数控制#!/bin/bash ENV${1:-dev} case $ENV in dev) SERVER_HOST192.168.1.10 SERVER_USERdeploy APP_HOME/opt/app/dev ;; test) SERVER_HOST192.168.1.20 SERVER_USERdeploy APP_HOME/opt/app/test ;; prod) SERVER_HOSTyour-prod-host SERVER_USERdeploy APP_HOME/opt/app/prod ;; *) echo 未知环境: $ENV exit 1 ;; esac调用方式是./deploy.sh prod整个脚本的环境相关配置集中在一个 case 分支里清晰好维护。如果有条件不同环境的连接信息也可以放在独立配置文件中用source引入但我更喜欢上面这个方式少一层文件管理负担。6.2 多模块项目构建找准 Reactor 顺序Maven 多模块项目父 pom 加多个子模块构建时模块之间是有依赖顺序的依赖关系不对会直接编译失败。用mvn package会按 Reactor 自动排序一般没问题。但有一个细节容易踩如果只想构建某个子模块及其依赖需要加-pl和-am参数mvn clean package -pl gateway-service -am -DskipTests-pl指定要构建的模块列表-am表示同时构建该模块依赖的其他模块。实际场景中微服务项目往往只有一两个模块需要发布没必要全部重新编译能省几分钟构建时间。打包完以后每个子模块的 jar 在各自的target目录下收集时注意别漏for module in gateway-service user-service order-service; do find $module/target -name *.jar -newer $module/target/classes -exec cp {} dist/ \; done更稳妥的方式是直接用 Maven 的maven-assembly-plugin或者配置好finalName让产物输出到统一目录避免脚本里写死模块名。6.3 部署完成后的通知别让人盯着屏幕等发布脚本跑完如果大家只能蹲在终端等结果这个体验太原始了。建议加一步通知机制用最轻量的方案钉钉机器人 Webhook。NOTICE_URLhttps://oapi.dingtalk.com/robot/send?access_tokenYOUR_TOKEN curl -s $NOTICE_URL -H Content-Type: application/json -d { msgtype: text, text: { content: [$ENV] 部署完成$APP_NAME 版本 $VERSION构建耗时 $COST_TIMEs } }类似的也可以用企业微信、Slack、飞书原理都一样无非是换个接口和 JSON 格式。关键点是在脚本的关键节点都埋入通知开始构建、构建完成、部署中、部署成功、部署失败不要只在最后发一条。部署失败时的告警信息里带上日志文件路径和最近 20 行日志能省掉不少沟通成本。6.4 把脚本交给定时任务或 CI人机分离的最后一步脚本本身很好但如果每次部署还要人肉登录服务器执行那自动化的价值就少了一半。我最后会加一层把脚本挂到 Jenkins 或 GitLab CI当发布分支有 tag 推送时自动触发构建部署。你可以在本地触发模拟比如在 GitLab CI 中配置deploy-to-prod: stage: deploy script: - chmod x deploy.sh - ./deploy.sh prod only: - tags本地调试脚本时一定要记得在开发机上跑通全链路后再切入 CI否则 CI 环境没有你本地的私钥、环境变量脚本跑了半天才发现全部权限错误。这里我把最有价值的建议放在最后永远不要直接修改线上在生产跑的脚本。先复制一份带.test后缀的副本在测试环境验证确认无问题后再替换线上脚本。这是我从一次事故得到的教训线上脚本里手一抖改错一个路径变量部署直接切到了旧版本的软链接目录上20 分钟后才发现问题。7. 实操总结一套可以直接用的完整模板我把整套方案整合成两份脚本模板一份是主控脚本build_deploy.sh一份是远程目标机上的启动脚本startup.sh。生产环境我上线的版本比这个略复杂但核心骨架完全一致你可以在这上面按照自己的项目情况加功能。这两份脚本我建议直接复制保存遇到问题再参照本文的排障章节逐项排查。7.1 主控脚本模板本机执行#!/bin/bash # build_deploy.sh - Java 项目自动化编译打包部署脚本 set -euo pipefail # 配置区 ENV${1:-dev} GIT_URLgitgithub.com:yourorg/yourproject.git GIT_BRANCHmain MODULEScommon,service-api,service-impl,web APP_NAMEyour-app.jar DIST_DIRdist BACKUP_DIRbackup SERVER_HOST SERVER_USERdeploy SERVER_PATH/opt/app/${ENV}/releases APP_HOME/opt/app/${ENV}/current # 环境配置映射 case $ENV in dev) SERVER_HOST192.168.1.10 ;; test) SERVER_HOST192.168.1.20 ;; prod) SERVER_HOSTyour-prod-host ;; *) echo Unknown env: $ENV; exit 1 ;; esac # 准备工作 TIMESTAMP$(date %Y%m%d%H%M%S) VERSION${GIT_BRANCH}-${TIMESTAMP} WORK_DIRbuild_${TIMESTAMP} mkdir -p $WORK_DIR $DIST_DIR $BACKUP_DIR # 拉取代码 cd $WORK_DIR if [ -d .git ]; then git fetch origin else git clone $GIT_URL . fi git checkout $GIT_BRANCH git pull origin $GIT_BRANCH GIT_COMMIT$(git rev-parse --short HEAD) echo 代码版本: $GIT_BRANCH $GIT_COMMIT cd .. # 编译打包 export MAVEN_OPTS-Xms512m -Xmx2048m -XX:MaxMetaspaceSize512m mvn -f $WORK_DIR/pom.xml clean package -DskipTests | tee $BACKUP_DIR/build_${VERSION}.log BUILD_EXIT${PIPESTATUS[0]} if [ $BUILD_EXIT -ne 0 ]; then echo 构建失败退出码 $BUILD_EXIT请查看日志 $BACKUP_DIR/build_${VERSION}.log exit $BUILD_EXIT fi echo 构建成功开始收集产物 # 收集产物 # 按模块收集支持多模块项目 IFS, read -ra MODULE_ARRAY $MODULES for module in ${MODULE_ARRAY[]}; do jar_path$WORK_DIR/$module/target/*.jar # 排除 sources.jar 和 javadoc.jar cp $jar_path $DIST_DIR/ 2/dev/null || true done # 兼容单模块项目 if [ ! $(ls -A $DIST_DIR) ]; then cp $WORK_DIR/target/*.jar $DIST_DIR/ 2/dev/null || true fi # 将 app 包复制为标准的 APP_NAME find $DIST_DIR -name *.jar ! -name *-sources.jar ! -name *-javadoc.jar | head -1 | xargs -I{} cp {} $DIST_DIR/$APP_NAME # 推送产物 ssh ${SERVER_USER}${SERVER_HOST} mkdir -p ${SERVER_PATH}/${VERSION} scp $DIST_DIR/$APP_NAME ${SERVER_USER}${SERVER_HOST}:${SERVER_PATH}/${VERSION}/${APP_NAME} scp $WORK_DIR/startup.sh ${SERVER_USER}${SERVER_HOST}:${SERVER_PATH}/${VERSION}/startup.sh 2/dev/null || true echo 产物已推送到 ${SERVER_HOST}:${SERVER_PATH}/${VERSION} # 远程部署 ssh ${SERVER_USER}${SERVER_HOST} set -e # 备份当前版本 if [ -L ${APP_HOME} ]; then CURRENT_VERSION\$(readlink ${APP_HOME}) cp -a \$CURRENT_VERSION ${SERVER_PATH}/backup-${VERSION} || true fi # 切换软链接原子操作 ln -sfn ${SERVER_PATH}/${VERSION} ${APP_HOME} # 重启应用 if [ -f ${APP_HOME}/app.pid ]; then kill \$(cat ${APP_HOME}/app.pid) || true sleep 3 fi # 启动新版本 nohup java -jar -Xms512m -Xmx1024m ${APP_HOME}/${APP_NAME} ${APP_HOME}/app.log 21 echo \$! ${APP_HOME}/app.pid echo 部署脚本执行完成开始健康检查 # 健康检查 # 简单远程健康检查请按实际端口和路径修改 sleep 10 HTTP_CODE$(ssh ${SERVER_USER}${SERVER_HOST} curl -s -o /dev/null -w %{http_code} http://127.0.0.1:8080/actuator/health) if [ $HTTP_CODE 200 ]; then echo 健康检查通过部署成功 else echo 健康检查失败HTTP_CODE$HTTP_CODE echo 请登录服务器查看 ${APP_HOME}/app.log 排查问题 exit 1 fi7.2 目标机启动脚本模板startup.sh随产物一起推送#!/bin/bash # startup.sh - 目标机服务的启动/停止/重启控制脚本 set -euo pipefail APP_NAMEyour-app.jar APP_HOME/opt/app/${APP_NAME%.jar}/current LOG_DIR/opt/app/${APP_NAME%.jar} SERVER_PORT8080 HEALTH_PATH/actuator/health start() { echo 启动 ${APP_NAME}... nohup java -Xms512m -Xmx1024m -jar ${APP_HOME}/${APP_NAME} ${LOG_DIR}/app.log 21 echo $! ${APP_HOME}/app.pid echo PID: $(cat ${APP_HOME}/app.pid) } stop() { if [ -f ${APP_HOME}/app.pid ]; then PID$(cat ${APP_HOME}/app.pid) echo 停止进程 ${PID}... kill $PID || true rm -f ${APP_HOME}/app.pid else echo PID 文件不存在尝试用 pkill 停止 pkill -f ${APP_NAME} || true fi } status() { if [ -f ${APP_HOME}/app.pid ]; then PID$(cat ${APP_HOME}/app.pid) if ps -p $PID /dev/null; then echo 运行中 (PID: $PID) return 0 fi fi echo 未运行 return 1 } healthcheck() { for i in $(seq 1 30); do CODE$(curl -s -o /dev/null -w %{http_code} http://127.0.0.1:${SERVER_PORT}${HEALTH_PATH} || true) if [ $CODE 200 ]; then echo 健康检查通过 return 0 fi sleep 2 done echo 健康检查失败 return 1 } case ${1:-} in start) start ;; stop) stop ;; restart) stop sleep 2 start ;; status) status ;; health) healthcheck ;; *) echo 用法: $0 {start|stop|restart|status|health} exit 1 ;; esac7.3 脚本使用注意事项过来人的经验这套模板我用了很长一段时间整体稳定但有几个坑你得提前知道一是主控脚本中的IFS, read -ra拆分模块列表如果某个模块名称里包含空格会被意外拆分。实际问题里很少遇到但如果你在 Windows 上编辑脚本再传到 Linux 执行务必确认脚本是 LF 换行而不是 CRLF否则 bash 会报错$\r: command not found。用sed -i s/\r$// script.sh一键处理。二是scp $WORK_DIR/startup.sh这行如果你本地的 startup.sh 路径和远程不一致或没有这个文件scp 会直接报错中断整条链路。我在模板里已经加了|| true兜底同时建议你最好把 startup.sh 放在项目仓库里统一维护随代码一起走版本控制。三是健康检查只检查了一次 200 就认为部署成功。真实场景里建议在部署后连续检查 3 次间隔 2 秒并且把/actuator/health换成更严格的接口。如果你用的不是 Spring Boot请把健康检查地址改成你项目实际的接口。四是最重要的一点——这套流程看似把部署这件大事简化成了敲一条命令但每一步背后都是有事可查、有日志可追溯的。无论你把它接到 CI还是人肉执行都要保证出现任何一个非预期结果时你能快速找到日志和版本信息。这比脚本本身写得多优雅更重要。

相关新闻

Java Swing实验室管理系统源码与数据库设计:课程设计实战指南

Java Swing实验室管理系统源码与数据库设计:课程设计实战指南

简介:这是一套面向高校计算机相关专业课程设计场景的实验室管理系统完整源码包,采用Java Swing构建带图形界面的桌面应用,并配套数据库文件,适合正在做课程设计、毕业设计或需要Java桌面项目练手的同学参考与二次开发。系统按功能…

2026/10/9 17:16:04 阅读更多 →
【多智能体】非线性多智能体定向网络中的共识问题附matlab代码

【多智能体】非线性多智能体定向网络中的共识问题附matlab代码

✅作者简介:热爱科研的Matlab仿真开发者,擅长数学建模、数据处理、算法改进、程序设计科研仿真。🍎 往期回顾关注个人主页:完整代码获取 定制创新 论文复现私信🍊个人信条:做科研,博学之、审问之…

2026/10/9 17:15:03 阅读更多 →
SVR做时间序列预测:滑动窗口特征构造与参数调优实战

SVR做时间序列预测:滑动窗口特征构造与参数调优实战

简介:本资源是一份面向Python初学者与时间序列建模实践者的完整入门级项目包,聚焦于使用支持向量机(SVM)解决实际回归预测问题,适用于金融趋势预判、销售量预测、传感器时序分析等典型场景。压缩包共2个文件&#xff0…

2026/10/9 17:15:03 阅读更多 →

最新新闻

基于PyQt+YOLOv5+dlib的驾驶员行为监控系统实战

基于PyQt+YOLOv5+dlib的驾驶员行为监控系统实战

简介:这份课程设计资源面向计算机视觉与深度学习方向的本科生及自学者,提供一套基于PyQt5、YOLOv5与Dlib的驾驶员行为监控系统完整实现,可用于课程设计、毕业设计或视觉项目练手。系统通过摄像头实时采集视频流,结合YOLOv5完成目标…

2026/10/9 17:57:30 阅读更多 →
23k张道路病害XML数据集:VOC转YOLO训练指南与避坑实践

23k张道路病害XML数据集:VOC转YOLO训练指南与避坑实践

简介:道路病害检测数据集压缩包,面向计算机视觉与深度学习开发者,适用于道路病害识别模型的数据准备与工程落地,核心价值在于解决标注数据获取难的痛点。压缩包内共两千个文件,其中一千九百九十八个为XML格式的标注文件…

2026/10/9 17:57:30 阅读更多 →
从impeccable到可执行标准:如何打造无可挑剔的代码与交付物

从impeccable到可执行标准:如何打造无可挑剔的代码与交付物

1. 从一个词出发:为什么"impeccable"值得单独拿出来聊第一次看到"impeccable"这个词被单独拎出来当作一个项目标题,我的反应是愣了一下。这不是一个技术名词,也不是某个框架或者工具的名字,它就是一个英文形容…

2026/10/9 17:57:30 阅读更多 →
终端AI编码助手魔改实战:从配置加载到钩子脚本的完整定制指南

终端AI编码助手魔改实战:从配置加载到钩子脚本的完整定制指南

前阵子有几个做开发的朋友不约而同来问我同一个问题:网上到处都在说终端里的 AI 编码助手可以魔改,改完之后能自动生成提交信息、自动带项目上下文、自动调用团队工具链,到底是怎么做到的?说实话,我刚接触这个玩法的时…

2026/10/9 17:57:29 阅读更多 →
历年数学建模竞赛真题高效刷题与建模流程避坑指南

历年数学建模竞赛真题高效刷题与建模流程避坑指南

简介:《历年数学建模竞赛试题及参考答案》是一份面向数学建模竞赛参赛者、高校指导教师和自学者的rar压缩包,汇集了一九九四年至二〇〇三年以及二〇〇五年的全国竞赛试题,并纳入国内多所高校的竞赛自命题,同时配有参考答案与讲解幻…

2026/10/9 17:56:28 阅读更多 →
YOLOv5生活垃圾分类系统:从数据噪声建模到树莓派实时部署

YOLOv5生活垃圾分类系统:从数据噪声建模到树莓派实时部署

简介:本资源是一套基于YOLOv5实现的智能生活垃圾分类系统完整工程,面向人工智能与深度学习初学者、本科毕业设计及课程设计学生,解决实际场景中垃圾图像识别与分类落地难题。项目含76个文件,以40个Python源码(涵盖dete…

2026/10/9 17:56:28 阅读更多 →

日新闻

Java时间API实战:LocalDate、Date与ZonedDateTime的转换与避坑指南

Java时间API实战:LocalDate、Date与ZonedDateTime的转换与避坑指南

Java时间API这个话题,隔三差五就会在群里被翻出来讨论一次。上周还有个同事线上处理一个订单超时问题,排查到最后发现是ZonedDateTime序列化后时区丢了,用户在下单当天晚上看到的时间整整差了8个小时。这类问题几乎每个做Java开发的人都遇到过…

2026/10/9 0:00:49 阅读更多 →
EasyTier实践:从NAT穿透到子网代理的异地组网部署与排错

EasyTier实践:从NAT穿透到子网代理的异地组网部署与排错

前几个月我手头有好几台机器需要互相访问:办公室台式机、家里 NAS、还有一台云主机。如果只是偶尔传个文件倒还好,问题是工作场景经常要在几处环境之间来回切换,每次都先登录跳板机再层层代理,实在折腾。我先后试过端口映射、自建…

2026/10/9 0:00:49 阅读更多 →
AI Agent工程实战:从七要素到七个决策点的系统设计指南

AI Agent工程实战:从七要素到七个决策点的系统设计指南

AI Agent 这个词在过去一年里被反复提及,但真正动手搭过一套能跑起来的 Agent 系统的人都知道,从"知道它是什么"到"让它稳定干活"之间隔着一整套工程决策。我前后参与过几个 Agent 项目的落地,从最初用现成框架拼装&…

2026/10/9 0:01:50 阅读更多 →

周新闻

KT148A语音芯片外挂8002D功放的工程实践指南

KT148A语音芯片外挂8002D功放的工程实践指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/8 15:26:32 阅读更多 →
LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/8 15:26:40 阅读更多 →
ARM架构深度解析:从RISC设计理念到交叉编译实战

ARM架构深度解析:从RISC设计理念到交叉编译实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/9 10:11:06 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/8 21:13:17 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/8 15:26:17 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/9 6:17:20 阅读更多 →