尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
离线安装deb包:构建APT本地仓库与依赖解析实践
离线安装 deb 包这件事我最早的想法很简单U 盘拷过去dpkg -i完事。真到了隔离网里才发现一个包背后挂着十几个依赖缺一个就卡住报错还只给一行干巴巴的提示。后来我把整套软件源搬进内网用 APT 本地仓库做离线安装让 apt 自己去算依赖这条路才算走顺。这篇就聊我实际落地过的做法怎么在完全没有外网的机器上把 deb 包和它的依赖一次性准备好构建一个能被apt update正常识别的本地仓库以及批量部署时那些文档里不写、只有踩过才知道的细节。适合手里管着几台到几十台隔离机、需要反复装包的人看如果你只是偶尔装一个包前面方案对比那节看完就可以直接选最省事的那条路。1. 离线装 deb 这件事先想清楚再动手1.1 离线场景到底长什么样坑通常出在哪我接触过的离线环境大概分三类。第一类是物理隔离的生产网机器在机房里网线只连内网交换机任何外联都走审批第二类是现场设备比如工控机、边缘盒子装完系统就封箱现场只有维护口第三类是临时场景比如某次培训或演示十几台机器要装同一批软件但场地网络不通。这三类的共同点是apt update跑不通apt install自然也用不了所有包必须提前准备好。最早的坑几乎都出在依赖上。dpkg -i只负责解包和配置不负责找依赖缺一个libxxx就停在那里你补一个它再报下一个像剥洋葱。更麻烦的是版本依赖比如某个包要求libssl大于等于某个版本你手头只有旧版装上去运行时报符号找不到。还有人图省事直接把联网机器的/var/cache/apt/archives整个拷过去结果发现里面只有最近装过的包依赖并不全而且混着不同架构的文件。这些问题在联网环境里被 apt 自动解决了到了离线环境全暴露出来所以方案选型的第一步不是比谁快而是比谁能把依赖关系处理干净。1.2 几种离线安装方式的横向对比我把常见做法列了个表都是实际用过的优缺点比较直白方式依赖处理适合场景主要缺点dpkg -i xxx.deb不处理需手动补齐单个无依赖或依赖已满足的包依赖缺失时反复试错容易装到一半apt install ./xxx.deb会从已配置源里找依赖本机已有可用源或缓存离线机没有源时仍然找不到依赖gdebi xxx.deb读取本地 deb 解析依赖少量包、单机操作依赖包本身也得提前放好批量效率低APT 本地仓库由 apt 统一解析多包、批量、需反复安装前期要建仓库、配源有一次性的搭建成本直接解包到目录完全不处理绿色软件、应急排查不走包管理后续升级卸载都麻烦单看单包安装dpkg -i确实最快几条命令就完事。但只要包带依赖你就会陷入“装一个、报一个、补一个”的循环。apt install ./xxx.deb稍微好一点它会把本地 deb 当作一个临时源然后去已配置的源里找依赖可离线机的源列表里通常什么都没有所以还是白搭。gdebi的思路是对的它读 deb 的 control 信息逐个提示缺什么但缺的包还是得你自己找。真正适合批量的是本地仓库。它的本质是把一堆 deb 包按 apt 认识的格式组织起来生成索引文件和元数据再让离线机把这个目录当成一个软件源。之后你执行apt installapt 会像访问网络源一样解析依赖、计算安装顺序缺什么直接在同一仓库里找。这套机制不新鲜但每一步都有细节下面拆开讲。1.3 为什么我把本地仓库当成默认方案判断标准其实就一条这套东西要不要重复用。如果一台机器只装一次用完就扔那没必要建仓库把依赖列表拉全、按顺序dpkg -i也能过。但只要是批量、或者后续还要加包、或者要交给别人维护本地仓库的优势就出来了。第一是可重复。仓库建好之后装包命令和联网环境完全一样不需要记住“先装 A 再装 B”的顺序apt 自己会算。第二是可审计仓库目录里有什么包、什么版本一目了然出问题能回溯。第三是可扩展后面新增软件只需要把 deb 丢进 pool 目录、重建索引客户端apt update一下就生效不用改任何安装脚本。第四是能配合版本锁定离线环境最怕的就是版本漂移仓库里放哪个版本装出来就是哪个版本不会因为某次误操作装上新版。提示本地仓库不是“把 deb 堆在一个目录”就完事索引文件、Release 元数据、签名三样缺一不可少一样 apt 就会报错或者拒绝使用。2. 准备阶段先把依赖闭包和目录骨架定下来2.1 系统版本、架构与包格式核对建仓库之前第一件事是确认联网机和离线机的系统大版本一致。debian 包虽然格式通用但依赖的库版本是跟发行版走的用新版系统下载的包拿到旧版系统上大概率卡在libc6或libssl的版本要求上。我一般用这几条命令核对cat /etc/os-release uname -m dpkg --print-architecture dpkg --print-foreign-architecturesdpkg --print-architecture输出的是主架构常见是amd64或arm64。--print-foreign-architectures看有没有开多架构如果输出里有i386说明这台机器允许装 32 位包下载依赖时要把这部分也考虑进去。包文件名里带架构信息比如nginx_1.22.1-9_amd64.deb中间那段就是架构拷贝的时候别把arm64的包混进amd64的仓库apt 虽然会忽略不匹配的包但索引里多出来的条目会让排查变麻烦。还有一个容易忽略的点是包格式。现在 deb 包有deb和udeb两种后者是安装器用的精简包普通仓库里不该出现。另外有些第三方包依赖multiarch支持装的时候需要dpkg --add-architecture这个在离线机上也要提前做否则apt install会提示架构不支持。2.2 依赖闭包的收集与下载策略依赖收集我试过三种路子各有适用面。最直接的是apt-cache depends --recurse把目标包的所有依赖递归列出来apt-cache depends --recurse --no-recommends --no-suggests \ --no-conflicts --no-breaks --no-replaces --no-enhances \ nginx | grep ^\w | sort -u这里几个--no-参数是有讲究的。--no-recommends表示不把推荐包算进去离线环境空间有限推荐包往往不是必需的--no-suggests同理。--no-conflicts、--no-breaks这些是排除关系型依赖只保留真正需要安装的包名。最后的grep ^\w是过滤掉Depends:这类前缀行只留包名。这个列表拿去循环下载基本能覆盖硬依赖但虚拟包和Provides的情况它处理不干净需要人工看一眼。第二种是让 apt 自己下载这是我最推荐的方式mkdir -p /data/offline-debs apt-get install --download-only --reinstall \ -o Dir::Cache::archives/data/offline-debs \ nginx--download-only只下载不安装--reinstall保证已经装过的包也会重新下载一份-o Dir::Cache::archives把下载目录指到我们准备好的位置。这条命令的好处是 apt 会完整走一遍依赖解析下载下来的就是它认为需要的那一套版本也匹配当前源。唯一的前提是联网机的源配置要和离线机目标系统一致不能拿 testing 源去给 stable 系统下包。第三种是apt-get --print-uris只打印下载地址不实际下载适合需要走其他下载工具或者做审计的场景apt-get --print-uris --yes install nginx | grep ^ | cut -d -f2输出是一串 URL可以交给下载工具批量拉取。不过这种方式拿不到依赖的依赖需要配合前面的apt-cache depends一起用。注意不管用哪种方式下载完都要检查一遍dpkg-deb -I xxx.deb里的Depends字段确认没有漏掉Pre-Depends。Pre-Depends的包必须在解包前就位漏了会导致安装直接失败而不是装完再报错。2.3 仓库目录结构与工具准备目录结构有两种常见形态我两种都用过建议按规模选结构目录样子源配置写法适用扁平结构所有 deb 和 Packages 在同一层deb [trustedyes] file:///srv/repo ./包少、临时用标准结构pool/放包dists/放索引deb [trustedyes] file:///srv/repo stable main包多、长期维护扁平结构省事dpkg-scanpackages . /dev/null一条命令生成索引Release 文件也放在同一层。但包一多目录会很乱而且没法区分组件和架构。标准结构多几层目录但扩展性好后面要加contrib或者多架构都方便。我现在的习惯是一律用标准结构反正脚本写一次就能复用。标准结构的骨架大概是这样/srv/offline-repo ├── pool/ │ └── main/ │ ├── nginx_1.22.1-9_amd64.deb │ └── libssl3_3.0.11-1_amd64.deb └── dists/ └── stable/ ├── Release ├── Release.gpg ├── InRelease └── main/ └── binary-amd64/ ├── Packages └── Packages.gz工具方面需要dpkg-dev提供dpkg-scanpackages、apt-utils提供apt-ftparchive、gnupg签名用。联网机上装好离线机不需要这些它只要能读仓库就行。装的时候注意dpkg-dev会带进来一批 perl 依赖如果联网机是最小化安装先确认磁盘空间够。3. 从零构建 APT 本地仓库3.1 放入 deb 包并生成 Packages 索引包准备好之后全部拷进pool/main/。这里有个小细节pool 目录的层级可以按包名首字母再分一层比如pool/main/n/nginx/这是官方仓库的做法包多了之后查找方便。但 apt 本身不关心层级只要dpkg-scanpackages扫得到就行小规模场景直接平铺也没问题。生成索引cd /srv/offline-repo mkdir -p dists/stable/main/binary-amd64 dpkg-scanpackages --arch amd64 pool/main /dev/null \ dists/stable/main/binary-amd64/Packages gzip -9c dists/stable/main/binary-amd64/Packages \ dists/stable/main/binary-amd64/Packages.gzdpkg-scanpackages的第一个参数是扫描目录第二个参数是 override 文件没有就写/dev/null。--arch amd64限定架构避免把其他架构的包扫进来。生成的 Packages 文件里每条记录包含包名、版本、架构、依赖、文件名、大小和校验和长这样Package: nginx Version: 1.22.1-9 Architecture: amd64 Maintainer: ... Installed-Size: 512 Depends: libc6 ( 2.34), libssl3 ( 3.0.0), ... Filename: pool/main/nginx_1.22.1-9_amd64.deb Size: 512340 SHA256: 9f2c...Filename字段是相对仓库根目录的路径这个路径必须和实际文件位置一致写错了 apt 会报“找不到文件”。SHA256是 apt 下载后校验用的本地仓库虽然不走网络但 apt 仍然会校验文件被改过就会拒绝安装。Package 文件生成完记得看一眼行数包多的时候如果某条记录缺字段多半是 deb 包本身不完整用dpkg-deb -I检查一下。3.2 生成 Release 元数据与多架构处理Packages 只是包清单apt 还需要一个 Release 文件来描述整个仓库包括有哪些组件、哪些架构、各个索引文件的校验和。生成命令cd /srv/offline-repo/dists/stable apt-ftparchive \ -o APT::FTPArchive::Release::OriginOfflineRepo \ -o APT::FTPArchive::Release::LabelOffline Repo \ -o APT::FTPArchive::Release::Suitestable \ -o APT::FTPArchive::Release::Codenamestable \ -o APT::FTPArchive::Release::Architecturesamd64 \ -o APT::FTPArchive::Release::Componentsmain \ release . Release这几个字段各有含义写错会导致客户端识别异常字段作用常见写法Origin仓库来源标识自定义名称如 OfflineRepoLabel仓库标签同 Origin 或更简短Suite发行版套件名stable、bookworm 等Codename代号与 Suite 一致即可Architectures支持的架构amd64多架构用空格分隔Components组件列表main多个用空格分隔Date生成时间apt-ftparchive 自动填Architectures如果写成amd64 arm64那dists/stable/main/下就要同时有binary-amd64和binary-arm64两个目录各自有 Packages 文件否则 apt update 会报找不到索引。多架构场景下建议每个架构单独跑一次dpkg-scanpackages不要试图用一个 Packages 文件混装。Release 文件生成后apt 还会去找Release.gpg和InRelease。前者是分离签名后者是 clearsign 的内联签名。两个都没有的话客户端要么报“仓库未签名”要么需要显式加trustedyes。这就引到下一节的签名问题。3.3 GPG 签名与免签两条路线签名的作用是让 apt 确认仓库内容没被篡改。本地文件仓库理论上风险很低但如果仓库目录放在共享盘上、或者多个人维护签名还是有意义的。生成密钥可以走批处理避免交互export GNUPGHOME/srv/offline-repo/.gnupg mkdir -p $GNUPGHOME chmod 700 $GNUPGHOME gpg --batch --gen-key EOF %no-protection Key-Type: RSA Key-Length: 4096 Name-Real: Offline Repo Name-Email: repolocal Expire-Date: 0 %commit EOF%no-protection表示私钥不设密码适合自动化脚本如果环境对安全要求高去掉这行用--passphrase-file传密码。密钥生成后签名cd /srv/offline-repo/dists/stable gpg --batch --yes --default-key repolocal \ --armor --detach-sign -o Release.gpg Release gpg --batch --yes --default-key repolocal \ --clearsign -o InRelease Release客户端要信任这个签名需要把公钥导过去gpg --export repolocal /srv/offline-repo/repo.gpg # 离线机上 install -m 644 repo.gpg /etc/apt/keyrings/offline-repo.gpg然后源配置里用signed-by指定deb [signed-by/etc/apt/keyrings/offline-repo.gpg] \ file:///srv/offline-repo stable main免签路线就是加trustedyesapt 会跳过签名校验deb [trustedyes] file:///srv/offline-repo stable main两种方式我都用过。内网单机、仓库目录只有自己能写免签完全够用省去密钥管理的麻烦。但只要是多人维护或者仓库放在共享存储上我建议还是签名因为trustedyes意味着这个源里的任何包都会被无条件信任万一目录被替换apt 不会有任何提示。注意私钥目录.gnupg不要放在仓库根目录下被客户端读到权限设成 700只给维护账号。导出给客户端的只有公钥私钥泄露等于仓库可以被任意伪造。3.4 客户端源配置与首次验证离线机上的配置很简单在/etc/apt/sources.list.d/下新建一个文件比如offline.list写入源地址。注意file://路径的写法末尾的./或组件名要和仓库结构对应# 扁平结构 deb [trustedyes] file:///srv/offline-repo ./ # 标准结构 deb [trustedyes] file:///srv/offline-repo stable main配置完执行apt-get update正常输出里能看到类似Get:1 file:/srv/offline-repo stable InRelease的行。如果报错先看错误类型Release file ... is not valid yet多半是系统时间不对does not have a Release file是路径或结构不对NO_PUBKEY是签名公钥没导入。验证仓库识别成功可以用apt-cache policy nginx输出里会显示候选版本和来源来源那行应该指向file:/srv/offline-repo。再跑一次模拟安装确认依赖能解析apt-get -s install nginx-s是模拟只打印安装计划不实际执行。这一步很关键它能在真正动手之前暴露依赖缺失、版本冲突的问题。4. 离线安装的完整实操从单包到整机批量4.1 单包装载与依赖自动补齐假设要装一个监控代理联网机上执行apt-get install --download-only --reinstall \ -o Dir::Cache::archives/data/offline-debs \ monitoring-agent下载完把/data/offline-debs里的 deb 全部拷到离线机的仓库 pool 目录重建索引、重新签名客户端apt-get update然后apt-get install monitoring-agent输出会列出所有将被安装的包包括自动补齐的依赖确认后输入y。整个过程和联网安装没有区别。如果中途报依赖错误先看报错里提到的包名用apt-cache policy 包名确认它是否在仓库里、版本是否满足要求。常见情况是仓库里只有新版而目标包要求旧版这时候要么补旧版包进去要么用apt-get install 包名版本号指定。还有一种情况是包已经用dpkg -i装了一半处于iFhalf-configured状态。这时候直接apt-get install -f可能因为没网而失败正确做法是先把缺的依赖补进仓库apt-get update之后再执行apt-get -f install让 apt 把未完成的配置走完。4.2 批量部署与版本锁定几十台机器装同一批软件我一般把包名写成一个列表文件然后用脚本循环#!/bin/bash set -euo pipefail PKGS/opt/deploy/pkglist.txt while read -r pkg; do [ -z $pkg ] continue apt-get install -y $pkg done $PKGS列表里可以带版本号比如nginx1.22.1-9这样每台机器装出来的版本完全一致。装完再做一次锁定防止后续误升级apt-mark hold nginx monitoring-agentapt-mark hold会把包标记为保持当前版本apt upgrade时跳过。离线环境其实很少触发升级但如果仓库后续追加了新版本锁定能避免批量机器出现版本不一致。版本锁定还有一层是源优先级。如果离线机同时配了本地仓库和某个残留的网络源可以用 pin 把本地源优先级拉高。在/etc/apt/preferences.d/offline.pref里写Package: * Pin: origin Pin-Priority: 1001origin 对应file://这类没有 Origin 字段的源优先级 1001 高于默认的 500能保证 apt 优先从本地仓库取包。这个配置在混合源环境里很有用避免 apt 跑去找一个连不上的网络源然后超时。4.3 增量更新仓库的正确姿势仓库不是建完就不管了后面加包是常态。增量更新的流程是新 deb 拷进 pool重新生成 Packages重新生成 Release重新签名客户端 update。手动敲命令容易漏步骤我一般写成一个脚本#!/bin/bash set -euo pipefail REPO/srv/offline-repo CODENAMEstable COMPmain ARCHamd64 KEYrepolocal cd $REPO mkdir -p dists/$CODENAME/$COMP/binary-$ARCH dpkg-scanpackages --arch $ARCH pool/$COMP /dev/null \ dists/$CODENAME/$COMP/binary-$ARCH/Packages gzip -9c dists/$CODENAME/$COMP/binary-$ARCH/Packages \ dists/$CODENAME/$COMP/binary-$ARCH/Packages.gz cd dists/$CODENAME apt-ftparchive \ -o APT::FTPArchive::Release::OriginOfflineRepo \ -o APT::FTPArchive::Release::LabelOffline Repo \ -o APT::FTPArchive::Release::Suite$CODENAME \ -o APT::FTPArchive::Release::Codename$CODENAME \ -o APT::FTPArchive::Release::Architectures$ARCH \ -o APT::FTPArchive::Release::Components$COMP \ release . Release gpg --batch --yes --default-key $KEY --armor --detach-sign -o Release.gpg Release gpg --batch --yes --default-key $KEY --clearsign -o InRelease Release脚本跑完客户端apt-get update就能看到新包。这里有个顺序不能错必须先更新 Packages再生成 Release因为 Release 里记录了 Packages 的校验和顺序反了校验和对不上apt 会报Hash Sum mismatch。签名必须在 Release 生成之后否则签的是旧内容。5. 常见报错与排查实录5.1 索引、签名、权限三类高频问题apt-get update报The repository ... does not have a Release file八成是源配置的路径和实际结构不匹配。比如仓库是标准结构源却写成file:///srv/offline-repo ./apt 会去根目录找 Release找不到就报这个。反过来扁平结构写成stable main它会去找dists/stable/Release同样找不到。排查方法很简单按照源配置里的路径手动ls一遍看 Release 文件在不在。签名类报错长这样The repository ... is not signed或者NO_PUBKEY xxxx。前者是 Release.gpg 和 InRelease 都不存在解决要么补签名要么加trustedyes后者是公钥没导入用gpg --export导出后放到/etc/apt/keyrings/并在源里用signed-by指定。老系统可能还在用apt-key add这个命令已经废弃新系统上会警告尽量改用 keyrings 目录。权限问题比较隐蔽。file://源是由 apt 的_apt用户去读的如果仓库目录权限是 700或者文件属主是 root 但其他用户没有读权限apt 会报Permission denied或者Unable to read。解决方法是给目录和文件放开读权限chmod -R arX /srv/offline-repoarX的意思是所有用户可读目录可进入文件不额外加执行位。这个命令我一般在每次重建仓库后跑一遍省得后面排查。5.2 依赖与版本冲突的定位方法apt-get install报Depends: xxx but it is not installable说明依赖包不在仓库里或者版本不满足。先用apt-cache policy xxx看仓库里有没有这个包、候选版本是多少如果没有输出就是 Packages 里没有这条记录。再用apt-cache showpkg xxx看它被哪些包依赖、版本要求是什么。版本要求是的情况补一个满足条件的新版进去就行是的情况比较麻烦必须精确匹配通常出现在内核模块或者特定驱动上。还有一种报错是Breaks或Conflicts表示新包和已装包冲突。这种在离线环境里不好解因为不能在线找替代版本。我的做法是先用apt-get -s install模拟看冲突涉及哪些包再决定是降级、卸载还是换一个替代包。模拟输出里会写明“将卸载 xxx”看到这种行要停下来确认别直接-y跑过去。5.3 常见问题速查表现象可能原因处理方式does not have a Release file源路径与目录结构不匹配核对file://路径和dists/层级is not signed缺少 Release.gpg/InRelease补签名或加trustedyesNO_PUBKEY公钥未导入导出公钥到 keyrings 并配signed-byHash Sum mismatchPackages 与 Release 不同步按 Packages→Release→签名顺序重建Unable to locate package索引未生成或组件名不对检查 Packages 是否存在、Components 是否匹配Permission denied_apt用户无读权限chmod -R arXDepends ... not installable依赖包缺失或版本不符补包或用apt-cache policy核对版本dpkg中断在iF状态安装过程被依赖打断补依赖后apt-get -f install客户端 update 很慢仓库目录过大或磁盘慢精简 pool只保留必要包时间相关报错离线机时钟偏差校准时间或去掉 Valid-Until6. 把它做成可维护的工程习惯6.1 仓库目录的版本化与校验仓库本身建议用 Git 管配置deb 包不进 Git但生成脚本、Release 模板、源配置样例都放进去。每次重建仓库除了 Release 自带的校验和我会额外生成一份SHA256SUMS放在仓库根目录cd /srv/offline-repo find pool -name *.deb -print0 | xargs -0 sha256sum SHA256SUMS这份文件用来做传输校验。U 盘拷贝、共享盘同步之后在离线机上跑一遍sha256sum -c SHA256SUMS能确认文件没有在传输过程中损坏。我遇到过一次拷贝中断导致 deb 包截断apt 安装时报archive has unexpected end查了半天才发现是文件不完整。有了校验和这种问题在安装前就能发现。6.2 回滚与审计的一点做法仓库更新前我会把旧的Packages、Release、InRelease备份到一个带日期的目录比如dists/stable/.backup/2024-06-01/。万一新加的包引入冲突把旧索引拷回来、重新签名客户端 update 一下就回到之前的状态不用重新整理包。这个做法成本很低但真出问题时能省不少时间。审计方面/var/log/apt/history.log会记录每次安装的包名和版本离线机上也一样。批量部署之后我会把这份日志收集起来和仓库里的包清单对一遍确认每台机器装的东西一致。如果某台机器少了包日志里会有记录比挨个dpkg -l查快得多。6.3 个人踩坑体会这套东西我前后搭过四五次最大的体会是离线环境的问题很少出在“不会做”而是出在“以为做完了”。索引生成了但没压缩apt 能读但慢签名做了但公钥没导客户端报错包拷进去了但权限没放_apt读不到。每一个都是小细节但每一个都能让整条链路卡住。所以我现在建完仓库固定跑三步验证apt-get update看有没有报错apt-cache policy看包能不能识别apt-get -s install看依赖能不能解析。三步都过才认为仓库是可用的。另一个体会是关于包的精简。最开始我图省事把联网机/var/cache/apt/archives整个拷进去结果仓库里堆了几百个包索引文件好几兆客户端 update 要等好几秒而且里面混着不同时期、不同版本的重复包。后来改成按需下载、只保留目标包和它的依赖闭包仓库体积小了一个数量级排查也清楚。离线环境存储通常不宽裕这一点还是值得花时间整理的。
RELATED

相关推荐

电机驱动器通讯中断导致失控的排查与根治方案

电机驱动器通讯中断导致失控的排查与根治方案

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

📅 2026/10/23 7:06:53
英雄联盟语音没声音排查:声卡驱动与音频服务修复

英雄联盟语音没声音排查:声卡驱动与音频服务修复

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

📅 2026/10/23 7:06:53
K8s入门本质:从kubectl命令逆向解剖控制平面

K8s入门本质:从kubectl命令逆向解剖控制平面

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

📅 2026/10/23 7:06:53
MORE NEWS

更多资讯

📰

基于 Spring Boot 的研究生导师信息管理系统设计与实现

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

📰

基于 Spring Boot 的学校浴室管理系统设计与实现

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

📰

ADK A2A 实战:从零跑通分布式智能体协作,把孤岛智能体连成网络

ADK A2A 实战:从零跑通分布式智能体协作,把孤岛智能体连成网络 【免费下载链接】adk-docs An open-source, code-first toolkit for building, evaluating, and deploying sophisticated AI agents with flexibility and control. 项目地址: https://g…

📰

如何快速选对 Rime 输入方案:awesome-rime 完整指南

如何快速选对 Rime 输入方案:awesome-rime 完整指南 【免费下载链接】awesome-rime A curated list of Rime IME schemata and configs | Rime 輸入方案和配置列表 项目地址: https://gitcode.com/GitHub_Trending/aw/awesome-rime 拼音候选翻不完&#xff0…

📰

平衡车FOC固件改造完全实战:hoverboard-firmware-hack-FOC 上手指南

平衡车FOC固件改造完全实战:hoverboard-firmware-hack-FOC 上手指南 【免费下载链接】hoverboard-firmware-hack-FOC With Field Oriented Control (FOC) 项目地址: https://gitcode.com/GitHub_Trending/ho/hoverboard-firmware-hack-FOC 平衡车FOC固件项目…

📰

Minecraft启动器PCL2:免费开源,5分钟跑起来还能自动装Java

Minecraft启动器PCL2:免费开源,5分钟跑起来还能自动装Java PCL2(Plain Craft Launcher 2)是一款免费开源的Minecraft启动器:自动匹配并下载Java、多版本并存、一键导入模组整合包,下载、启动、崩溃排查全包…

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

读完文章,想聊聊您的网站?

告诉我们您的行业与需求,资深顾问一对一梳理方案与报价,全程免费。

📞 💬