从零搭建区块链溯源系统:Fabric与Substrate双路线实战指南
上周我刚把一个溯源系统的 Demo 链从零跑起来从环境装包到链码部署折腾了整整一个周末。如果你也在搜“区块链搭链”大概率是接到了类似的任务领导要一条链客户要一个溯源 Demo或者你自己想搞清楚“一条链到底是怎么立起来的”。这篇文章就是把我那次搭链的全过程拆开讲——选哪条链、用什么框架、每一步做什么、哪些地方会卡你一晚上。我会拿 Hyperledger Fabric 和 Substrate 两条路线分别说清楚最后附一段溯源链码的真实代码示例。不管你之前有没有碰过链按这篇的思路走一遍基本能做到心里有数、手上不慌。先交个底区块链搭链这件事真正费时间的不是“运行节点”那一步而是“选型”和“配置”。框架选错了后面所有步骤都在跟环境打架配置没捋顺节点起了又挂日志刷屏你都不知道从哪看起。所以这篇文章不会只甩给你一堆命令我会把每个关键步骤背后的为什么也说清楚。1. 先搞清楚“区块链搭链”到底要搭哪条链1.1 公链、私链、联盟链的选型边界很多人一上来就搜“怎么搭链”但脑子里其实想的不是同一条链。公链是 Bitcoin、Ethereum 这种对所有人开放的你搭不了你只能“接进去”私链是一套网络跑在一个组织手里自己写规则自己玩联盟链是多个组织共享一条链有权限控制有通道隔离Hyperledger Fabric 就是这类里的典型代表。从搭链的实际操作来看私链和联盟链才是你真正能动手搭的东西。如果项目是面向企业内部或者要做溯源、供应链、存证这类多个参与方共同维护数据的场景直接走联盟链每个组织和节点有明确的身份证书谁可以提交交易、谁可以查数据、谁可以管理链码全都要通过权限体系控制。私链适合纯开发练手或者单一机构内部使用因为没有多组织参与配置上会省掉证书体系里最烧脑的那部分。Fabric 官方明确说过它不是公链也不提供原生加密货币定位就是企业级联盟链。这个定位意味着它的搭链难点不在共识算法而在于证书体系、通道结构、链码生命周期管理这几个模块。你得先把这几个支柱立起来链才能稳。1.2 开发链、测试链、生产链要区分开我见过不少团队把开发环境搭完直接把同一套配置往服务器上一扔就接业务流量结果没跑两天数据目录爆了、共识节点回滚、甚至证书过期导致整个网络连不上。这条经验我写了不下十次搭链之前先明确这条链是给谁用的。开发链追求的是“启动快、重启快、随便造数据”。哪怕你一天把链重置十次只要能把智能合约逻辑调通这链就完成了它 80% 的使命。测试链要在开发链基础上加稳定性和可观察性节点日志要存起来监控要做到位交易要能回放。生产链则要单独规划硬件、存储、证书轮换机制、备份恢复策略甚至在多机房部署上也跟开发链完全不是一回事。1.3 主流搭链框架的对比现在市面上能用来搭链的框架就那几个方向Fabric 系、Substrate 系、EVM 系。我直接给一张表你自己对号入座。框架方向典型代表链的类型适合场景搭链难度Hyperledger FabricFabric 2.x联盟链溯源、供应链、金融、多机构协作中高配置繁琐但规则清晰SubstrateSubstrate node template自定义链想要一条独特规则的链、研究跨链中Rust 门槛在那EVM 系Ganache / Hardhat local network开发私链/测试链Solidity 合约调试、以太坊生态低一条命令就能起Besu / Geth以太坊客户端私链/联盟链需要跟以太坊兼容的联盟方案中以我个人的体验Fabric 的“繁琐”是规则多但都有文档Substrate 是“你可以随便改”所以反而不知道往哪下手EVM 系则是“太简单了”导致很多人在真实多节点部署时反而没有积累经验。三选一的时候看你手头最熟的技术栈有 Go/Node 基础的去 Fabric有 Rust 基础的去 Substrate只会 Solidity 的那就老老实实 EVM 系。2. 搭链前的环境准备不是装个 Docker 就万事大吉2.1 最低硬件与内存要求Fabric 官方给的最低配置是 2vCPU、4GB 内存但这只是能跑。我实际测下来完整跑一遍 fabric-samples 的 test-network峰值内存能到 4.5-5GB如果还要同时编译链码、跑 SDK 调用8GB 内存是起步价。Substrate 更夸张release 模式编译 node-template 时16GB 内存的机器也经常被拉满更别提构建整个 polkadot 了。所以搭链的机器建议直接按这个标准来CPU 四核以上内存 16GB硬盘 50GB 起步且优先考虑 SSD。如果你只是在本机练手不要在跑着微信、浏览器、模拟器的电脑上同时硬跑一套 Fabric 网络后面的气都消不了。2.2 必须安装的核心依赖Fabric 2.x 的套路是用 Docker 跑 Orderer 和 Peer所以Docker 和 Docker Compose 是第一个要装好的。注意 Compose 插件的版本Fabric 官方脚本现在默认用 docker compose 子命令老版本那种 docker-compose 单独二进制经常会出现解析配置报错。然后是语言环境。Fabric 链码目前主流是 Go建议 Go 1.20而且要配好 GOPATH 和代理不然拉依赖会让你怀疑人生。对了Fabric 的 peer 命令行工具本身是编译好的二进制不需要你手动编译但链码如果要走外部构建模式还是得本地有编译环境。Substrate 这边要装 Rust 工具链而且必须用官方提供的 rustup 脚本配置因为 Substrate 编译器需要用的是 nightly 工具链加wasm32-unknown-unknowntarget。装完之后记得跑一下rustup update版本不匹配时编译出来的 runtime 可能直接跑不了。2.3 网络、端口、域名规划这条最容易被忽略但出错率极高。Fabric 网络内部有大量节点间通信容器之间默认通过 Docker 网络互通但你用 peer CLI 或 SDK 去连节点时走的又是宿主机端口映射。端口映射一旦冲突节点能起来但客户端永远连不上。以你的机器是 172.x.x.x 或 192.168.x.x 为例客户端证书里签的地址如果写的是 localhost你在宿主机能连但换一台机器立刻报endorsement failure。这种事我在多组织部署时栽过跟头预生成的证书里写死了一个内网 IP换网段后整个网络的连接全废。所以做多节点规划时组织域名、节点域名、IP 三者要在一开始就确定好后面用 cryptogen 生成证书时全部填对别指望后面能改。证书里的地址不是配置文件改起来要动整个网络。3. 以 Hyperledger Fabric 为例从创世块开始搭一条联盟链3.1 用 cryptogen 生成组织和节点身份Fabric 的身份体系依赖 MSPMembership Service Provider每个组织都要有一套自己的证书。开发环境最快速的方式是用cryptogen generate基于一个 crypto-config.yaml 批量生成所有组织的管理员、节点、用户证书。我建议直接拿 fabric-samples 里的test-network当模板改。它默认生成了 Org1、Org2 两个组织各一个 Peer 节点加上一个 Orderer 组织。你如果想多加一个组织只需要在 crypto-config.yaml 里加一段PeerOrgs: - Name: Org3 Domain: org3.example.com EnableNodeOUs: true Template: Count: 1 Users: Count: 1然后执行cryptogen generate --config./crypto-config.yaml一套新的证书、私钥、MSP 目录就生成了。这里有个经验EnableNodeOUs一定要开否则后续链码的ClientIdentity校验会非常难写。3.2 用 configtxgen 生成创世块和通道配置证书有了第二步是生成区块文件。Fabric 里有两个核心配置系统通道创世块和通道配置。先写好 configtx.yaml重点配置每个组织的 MSP 路径、锚点 Peer 地址、共识算法Raft 是现在唯一推荐的选择不要再用 Kafka 模式然后执行export FABRIC_CFG_PATH$PWD configtxgen -profile TwoOrgsOrdererGenesis -channelID system-channel -outputBlock ./system-genesis-block/genesis.block configtxgen -profile TwoOrgsChannel -channelID mychannel -asOrg Org1MSP -outputCreateChannelTx ./channel-artifacts/mychannel.tx这里有个关键configtxgen 的 -profile 名称必须和 configtx.yaml 里的 Profile 节点对得上大小写错一个都报错。另外 channelID 一旦定下来后续所有脚本、SDK 连接参数都必须用同一个名字别心血来潮改大小写。3.3 启动 Orderer 和 Peer创建通道并加入在你拿到创世块和通道交易文件之后用 docker-compose 把所有节点拉起来。Fabric 的容器编排文件核心是每个服务的 environment 里要挂对应的证书路径peer0.org1.example.com: environment: - CORE_PEER_IDpeer0.org1.example.com - CORE_PEER_ADDRESSpeer0.org1.example.com:7051 - CORE_PEER_LOCALMSPIDOrg1MSP - CORE_PEER_MSPCONFIGPATH/etc/hyperledger/fabric/msp volumes: - ./crypto-config/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/msp:/etc/hyperledger/fabric/msp节点起来后用 peer CLI 创建通道并让 Peer 加入export CORE_PEER_LOCALMSPIDOrg1MSP export CORE_PEER_ADDRESSlocalhost:7051 export CORE_PEER_MSPCONFIGPATH$PWD/crypto-config/peerOrganizations/org1.example.com/users/Adminorg1.example.com/msp peer channel create -o localhost:7050 -c mychannel -f ./channel-artifacts/mychannel.tx --outputBlock ./channel-artifacts/mychannel.block peer channel join -b ./channel-artifacts/mychannel.block这个阶段最容易翻车的是 MSP 路径写错导致 peer 报Error: proposal failed或者access denied。排查路径非常简单看容器日志Fabric 的错误日志其实已经把缺失路径或者权限问题写出来了别只看 peer CLI 终端那几行docker compose logs 才是主角。3.4 部署链码在通道上安装并激活智能合约Fabric 2.x 和 1.4 最大的不同是链码生命周期管理。不再是简单的peer chaincode instantiate而是分四步打包、安装、审批、提交。以 Go 链码为例先把代码放到fabric-samples/asset-transfer-basic/chaincode-go这种目录里然后peer lifecycle chaincode package asset.tar.gz --path ./chaincode-go --lang golang --label asset_1.0 peer lifecycle chaincode install asset.tar.gz peer lifecycle chaincode approveformyorg -o localhost:7050 --channelID mychannel --name asset --version 1.0 --package-id 刚install返回的Package ID --sequence 1 --signature-policy AND(Org1MSP.member,Org2MSP.member) peer lifecycle chaincode commit -o localhost:7050 --channelID mychannel --name asset --version 1.0 --sequence 1 --signature-policy AND(Org1MSP.member,Org2MSP.member)这里提醒一下Fabric 2.x 要求通道上的每个组织都要先 approve 再 commit所以 Org2 的管理员也要执行一遍上述 approve 命令。如果你发现自己提交了但链码调用返回chaincode is not ready基本可以断定是某个组织的 approve 没有完成。4. 用 Substrate 搭自定义链开发效率最高的一条路4.1 从 node-template 初始化一条链如果你不想跟 Fabric 的证书、通道死磕而且你手里的需求更像“我要一条能自定义业务逻辑的链”Substrate 是最舒服的入口。Substrate 的框架思路是共识、网络层、存储层都给你搭好了你只需要写业务逻辑所在的 pallet。先用官方模板初始化git clone --branch latest https://github.com/substrate-developer-hub/substrate-node-template.git cd substrate-node-template cargo build --release这段编译时间视机器而定20 分钟到一小时都很正常。编译完成之后启动./target/release/node-template --dev用--dev参数启动会直接生成一个开发用的单节点链账户默认带有大量初始资金自动出块非常适合验证 pallet 逻辑。核心点在于 node-template 的 runtime 里已经包含了 Balances、Core 资产、Sudo 等模块你可以直接用 polkadot.js Apps 界面连到ws://localhost:9944看到区块不断增长。4.2 配置初始账户与命名空间从“模板链”到“业务链”但光跑一个模板链不算搭链。搭链的意义是定义你自己的链上业务。你需要在 pallet 里定义新的 storage 和 dispatchable call。举个例子做一个最简单的“存证”业务用户提交一段内容哈希保存到链上任何人都能查询。#[pallet::storage] #[pallet::getter(fn get_evidence)] pub type EvidenceStoreT: Config StorageMap _, Blake2_128Concat, T::AccountId, Vecu8, OptionQuery, ; #[pallet::call_index(0)] #[pallet::weight(10_000)] pub fn create_evidence( origin: OriginForT, evidence: Vecu8, ) - DispatchResult { let who ensure_signed(origin)?; ensure!(evidence.len() 256, Error::T::EvidenceTooLarge); EvidenceStoreT::insert(who, evidence); Ok(()) }写完在你的construct_runtime!宏里注册这个 pallet重新cargo build --release一条支持存证业务的链就出来了。这个过程在 Fabric 里你需要写链码、装链码、审批链码在 Substrate 里你只需要编译一个新 runtime然后重启节点就生效。如果你要“一步到位”地发一条可供多人使用的链还要配置初始账户和 token 分配。Substrate 的 chain_spec.rs 里可以设置genesis_config给不同账户分配余额节点启动时这些余额会直接写入创世区块。4.3 中继链和平行链先搞清楚自己用不用得上很多教程一上来就讲波卡生态的平行链怎么连中继链但我个人建议大多数人搭链根本不需要碰平行链。中继链是波卡生态基于安全共享的一套跨链共识只有在你要发一条真正面向生态的、需要获得跨链能力的链时才需要考虑把链作为平行链接入 Rococo 或 Kusama。本地开发时你只需要 node-template 的--dev模式就行。等你想模拟多节点部署再启动两个 validator 节点生成各自的 chain spec通过--bootnodes参数互相连接。这已经能覆盖到“多节点共识”的测试需求。平行链那套等你确认需求真的需要再说别被概念拖着走。5. 搭完之后一条能跑业务的链还要补哪些配置5.1 数据持久化、日志和监控很多人搭链时只顾着把节点拉起来看到出块就欢呼。但一条能跑业务的链90% 的功夫在链外。以 Fabric 为例Peer 和 Orderer 的数据目录默认写进 Docker 容器里面容器一删账本全没了。所以 docker-compose 里必须把/var/hyperledger/production挂到宿主机目录而且要单独备份。日志这块Fabric 的节点日志默认打到 stdoutDocker 一重启就没了。我建议在部署生产链时把日志落盘到固定目录并且配置 logrotate 留足 30 天以上。Substrate 这边--rpc-port、--port、--prometheus-port几个端口要在配置时固定下来Prometheus 指标直接对接到监控看板区块高度、peer 连接数、最终确定延迟这些指标看起来才有安全感。5.2 从单节点到多节点证书和网络参数必须重做这是我最想提醒的一件事本地 test-network 跑通了不等于多节点网路能跑通。本地生成的证书中节点地址和域名全是localhost或127.0.0.1你拿到两台真实服务器上证书校验直接失败。多节点部署时你需要重新生成整套证书域名使用真实的主机名或内网 IP并在每台机器上分发对应的 MSP 目录。Orderer 和 Peer 的配置中CORE_PEER_ADDRESS必须写其他节点从网络角度能访问到的地址不能偷懒写 localhost。我遇到过最典型的坑就是把 Peer 的地址填成容器 IP容器重启后 IP 变了全网别的节点都连不上它只能重新生成证书。5.3 重启、升级和链码灰度区块链网络最尴尬的问题之一就是“想升级某个模块但链已经在跑”。Fabric 链码升级要重新打包、安装、approve、commit而且要注意旧交易如果在升级后还在通道里重复提交会查不到状态。Substrate 有 forkless runtime upgrade 机制可以不停机升级链上逻辑但你要用 Sudo 模块发起set_code调用操作前务必先在开发链上完整演练一遍。灰度这条我的建议是不管用什么框架任何变更先在测试链上跑完整流程固定版本号记录配置备份然后再操作生产链。区块链没有“回滚键”你执行一次交易它就永远留在账本里了。6. 溯源系统上链的代码示例从链码到接口一次讲清6.1 溯源数据模型怎么设计“区块链溯源系统代码”是全网热搜词但很多人没想明白一个问题溯源不是把视频或图片存上链而是把每个环节的关键信息和指纹存上链。生产商、物流商、经销商每个环节提交一条交易形成不可篡改的链条消费者扫码查到的是链上的证明。所以链码的核心数据模型就三类产品批次编号BatchID标识一件商品的唯一批次每个环节的事件Event包含操作方、时间戳、操作类型、位置/环境参数、上一步哈希产品状态当前在哪里、当前归属谁我见过直接把产品详情 JSON 全量塞进链码的。也不是不行但链码存储越大交易费越高同步越慢。建议链上只存哈希和小字段大文件放链下存储IPFS 或普通对象存储链上存文件哈希当凭证。这才是溯源系统的正常打开方式。6.2 用 Go 写一个带溯源能力的链码示例下面是一个简化但可以直接用的溯源链码核心逻辑。它先注册产品批次然后每个环节追加事件最后支持按批次查询完整溯源路径。package main import ( encoding/json fmt time github.com/hyperledger/fabric-contract-api-go/contractapi ) type TraceContract struct { contractapi.Contract } type ProductBatch struct { BatchID string json:batchId Product string json:product Producer string json:producer CreatedAt string json:createdAt Events []TraceEvent json:events TotalSteps int json:totalSteps } type TraceEvent struct { Step int json:step Operator string json:operator Action string json:action Location string json:location Timestamp string json:timestamp Temp string json:temp,omitempty Extra string json:extra,omitempty } func (c *TraceContract) CreateBatch(ctx contractapi.TransactionContextInterface, batchId string, product string, producer string) error { existing, err : ctx.GetStub().GetState(batchId) if err ! nil { return fmt.Errorf(failed to read state: %v, err) } if existing ! nil { return fmt.Errorf(batch %s already exists, batchId) } batch : ProductBatch{ BatchID: batchId, Product: product, Producer: producer, CreatedAt: time.Now().Format(time.RFC3339), Events: []TraceEvent{}, } return c.SaveBatch(ctx, batch) } func (c *TraceContract) AddEvent(ctx contractapi.TransactionContextInterface, batchId string, operator string, action string, location string, temp string, extra string) error { stub : ctx.GetStub() batchBytes, err : stub.GetState(batchId) if err ! nil { return fmt.Errorf(failed to read state: %v, err) } if batchBytes nil { return fmt.Errorf(batch %s does not exist, batchId) } var batch ProductBatch if err : json.Unmarshal(batchBytes, batch); err ! nil { return fmt.Errorf(invalid batch data: %v, err) } step : len(batch.Events) 1 batch.Events append(batch.Events, TraceEvent{ Step: step, Operator: operator, Action: action, Location: location, Timestamp: time.Now().Format(time.RFC3339), Temp: temp, Extra: extra, }) batch.TotalSteps step return c.SaveBatch(ctx, batch) } func (c *TraceContract) SaveBatch(ctx contractapi.TransactionContextInterface, batch ProductBatch) error { bytes, err : json.Marshal(batch) if err ! nil { return fmt.Errorf(failed to marshal batch: %v, err) } return ctx.GetStub().PutState(batch.BatchID, bytes) } func (c *TraceContract) GetAllEvents(ctx contractapi.TransactionContextInterface, batchId string) (*ProductBatch, error) { bytes, err : ctx.GetStub().GetState(batchId) if err ! nil { return nil, fmt.Errorf(failed to read state: %v, err) } if bytes nil { return nil, fmt.Errorf(batch %s does not exist, batchId) } var batch ProductBatch if err : json.Unmarshal(bytes, batch); err ! nil { return nil, fmt.Errorf(invalid batch data: %v, err) } return batch, nil } func main() { chaincode, err : contractapi.NewChaincode(TraceContract{}) if err ! nil { panic(fmt.Sprintf(Error creating trace chaincode: %v, err)) } if err : chaincode.Start(); err ! nil { panic(fmt.Sprintf(Error starting trace chaincode: %v, err)) } }这个链码的设计思路是CreateBatch创建批次AddEvent记录物流或加工环节GetAllEvents输出完整溯源链路。生产环境里你还应该在AddEvent里拉取调用者身份ctx.GetClientIdentity()把操作方 Restrict 到特定组织防止随便什么人都能往链上写事件。6.3 快速调通一个调用链上的数据的接口链码写完了外部系统要调用它通常走 Fabric Gateway SDK 或 REST API。最快的方式是用 Node 或 Go 的 Gateway 客户端连接 peer 节点提交交易并监听事件。拿 Node 举例核心代码也就十几行const { connect } require(hyperledger/fabric-gateway); const identity await newIdentity(org1AdminCert); const signer await newSigner(org1AdminPrivateKey); const gateway await connect({ identity, signer, client: new GrpcClient(peerEndpoint) }); const network await gateway.getNetwork(mychannel); const contract network.getContract(trace); await contract.submitTransaction(CreateBatch, BATCH001, 有机茶叶, 云南普洱某茶厂); const result await contract.evaluateTransaction(GetAllEvents, BATCH001); console.log(result.toString());这一步跑通后就说明链路闭环了外部业务系统调用 SDKSDK 提交交易到 PeerPeer 执行链码链码读写账本然后返回结果。溯源系统的后端接口就是在此基础上包一层 HTTP 服务手机扫码调用这个 HTTP 接口查询结果返回到前端。整个链路没有黑魔法就是“SDK 提交交易 → 节点执行链码 → 账本存储更新 → 查询数据返回”。7. 搭链最容易踩的坑我替你踩过的雷7.1 Docker 镜像版本不一致Fabric 2.x 的镜像版本要求和二进制版本严格对应。我严重怀疑有大量人遇到orderer panic或者 peer 之间握手失败根因都是镜像 tag 混了。比如你拉了hyperledger/fabric-peer:2.5.0但 orderer 还是2.2.0这两个节点在通道里协商协议时大概率直接断开连接。解决办法简单又粗暴把所有镜像和 CLI 工具统一到同一个版本拉镜像之前先看清楚 fabric-samples 对应分支的docker-compose.yaml里写的 tag 是什么。7.2 创世块和通道配置不匹配这个问题比镜像更隐蔽。创世块是在系统通道层面生成的而每个业务通道有自己独立的通道配置。如果你后面用configtxlator修改通道配置时改乱了某个字段比如把 Orderer 的地址写错、把共识节点列表整没了轻则通道无法更新配置重则整个通道停止出块。我的建议是每次修改通道配置前先把当前配置导出一份备份修改必须走 “fetch 配置块 → 转 JSON → 修改 → 转回 protobuf → signature 聚合 → 提交” 完整流程不要手改配置。这条流程虽然繁琐但能保命比日后再抢救账本强得多。7.3 证书、CA 和身份混乱Fabric 最折磨人的就是 MSP 概念。很多人搞混了Adminorg1.example.com的证书和peer0.org1.example.com的证书直接用管理员证书去启动 Peer启动类会一直报权限异常。你只需要记住一条主线节点的所有操作使用 Peer 自己的 MSP 证书管理员操作install、approve、创建通道使用组织 Admin 的 MSP 证书普通业务查询如果走 SDK则使用组织内某个 User 的证书每条主线对应不同的CORE_PEER_MSPCONFIGPATH环境变量不一样行为就完全不一样。我建议在脚本开头就打印当前环境变量避免在多个终端来回切换时把身份搞混。7.4 存储增长与性能误判区块链的特性是账本只增不减所以存储规划趁早不趁晚。Fabric 的账本数据包含世界状态数据库CouchDB/LevelDB和区块文件CouchDB 的性能很吃内存数据量大了以后查询会明显变慢别指望一个默认配置能用三年。另一个常见误区是把“出块速度”等同于“性能”。Fabric 默认的 Raft 出块时间是 2 秒一个块不代表你的业务只能每秒处理一笔交易。你要看的核心指标是 TPS、交易延迟、背书耗时而不是区块高度跑得多快。Substrate 那边也要理解“出块”和“最终确定性”是两个维度别拿普通数据库的直觉去评估一条链。我在实际项目中总结过一条经验搭链踩坑 80% 是环境问题15% 是配置错误只有 5% 才是框架本身没搞明白。所以真遇到问题先按“版本、路径、权限、端口、网络”五个维度排查大多数 panic 都会指向其中一个。如果你搭链时卡在某个莫名其妙的报错上大概率就是这五件事里有一件跟文档里不一致而不是“区块链太难了”。调整好状态你会发现搭链这回事没有传说中那么玄。

相关新闻

macOS深度集成指南:从零打造Protocol Launcher统一调用层

macOS深度集成指南:从零打造Protocol Launcher统一调用层

一直以来,我在macOS上用力最猛的,不是某个效率App,而是那些能把系统原生应用、命令行工具和浏览器行为真正串起来的“胶水层”。今天想聊聊我折腾了挺久的一套东西:Protocol Launcher。它不是某个商店里的具体软件,而是…

2026/10/9 6:11:06 阅读更多 →
VulnHub DC-4靶机渗透实战:从命令注入到sudo提权

VulnHub DC-4靶机渗透实战:从命令注入到sudo提权

最近把 VulnHub 的 DC-4 靶机完整打了一遍。作为经常拿 VulnHub 系列做靶场练习的人,这台机器给我的感觉是:路径完整、难度适中、环境干净。它不像某些靶机为了增加难度塞一堆无关噪声,也不像 DC-1 那样需要自己翻源码找入口,DC-4…

2026/10/9 6:11:05 阅读更多 →
Java推箱子项目实战:从地图建模到BFS自动求解

Java推箱子项目实战:从地图建模到BFS自动求解

简介:基于Java实现的推箱子小游戏项目,以炮炮兵趣味形象作为主角,界面美观,适合Java初学者、课程设计学生及游戏开发爱好者学习Swing/GUI编程、事件监听与游戏状态管理。资源共60个文件,以36个关卡地图文件&#xff08…

2026/10/9 6:10:05 阅读更多 →

最新新闻

生产级Coding Agent调优实战:Harness工程化决定落地下限

生产级Coding Agent调优实战:Harness工程化决定落地下限

1. 从"能跑"到"好用":生产级 Coding Agent 的最后一公里到底卡在哪Vibe Coding 这个词这两年被聊得很多,大意是开发者用自然语言描述意图,让 Coding Agent 去生成、修改、验证代码,人只负责把握方向和验收。听…

2026/10/9 6:35:27 阅读更多 →
Java Swing人事管理系统:JDBC+MySQL课程设计实战与避坑指南

Java Swing人事管理系统:JDBC+MySQL课程设计实战与避坑指南

简介:这份资源是一套基于 Java Swing、JDBC 与 MySQL 实现的人事管理系统课程设计项目,面向正在完成数据库课程设计、需要可运行参考案例的计算机相关专业学生。项目包含可视化软件界面,覆盖人员信息维护、数据库连接与增删改查等典型业务场景…

2026/10/9 6:35:27 阅读更多 →
MySQL校对规则:utf8mb4_general_ci与utf8mb4_bin的差异及选型

MySQL校对规则:utf8mb4_general_ci与utf8mb4_bin的差异及选型

1. 这两个校对规则到底在吵什么看你一脸问号地点进来,我猜你多半是遇到过这种情况:建表的时候复制了一段别人的SQL,里面有CHARSETutf8mb4 COLLATEutf8mb4_general_ci,或者是utf8mb4_bin,当时也没多想,能用就…

2026/10/9 6:35:27 阅读更多 →
PS5底层开发合规边界与技术可行性分析

PS5底层开发合规边界与技术可行性分析

我无法根据当前输入生成符合要求的博文。原因如下:项目标题 "AnyPS5" 缺乏明确指向性:该词在公开技术语境中无公认定义,既非官方产品名(索尼未发布/命名过 AnyPS5)、非开源项目(GitHub、GitLab、…

2026/10/9 6:35:27 阅读更多 →
claude-mem:为Claude Code打造跨会话长期记忆的实战指南

claude-mem:为Claude Code打造跨会话长期记忆的实战指南

用过 Claude Code 写真实项目的人,基本都遇到过这个场景:昨天刚跟 AI 讨论清楚的一个架构方案,今天新开一个会话,它完全不记得了。你在同一个仓库里翻历史对话记录,发现上一个会话已经把项目的来龙去脉都喂给了它&…

2026/10/9 6:35:27 阅读更多 →
Agent-Reach:LLM API智能路由与成本可控调度中枢

Agent-Reach:LLM API智能路由与成本可控调度中枢

1. 项目概述:Agent-Reach 是什么?它解决的不是“能不能用”,而是“怎么用得稳、用得准、用得省”Agent-Reach 这个名字乍看像某个开源模型或工具库,但结合 CLI、API、YouTube、Reddit 这些高频热词,再叠加上“zcode cl…

2026/10/9 6:34:27 阅读更多 →

日新闻

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/8 10:10:36 阅读更多 →

月新闻

我发现了一个新思路:用 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 阅读更多 →