适用场景:OpenHarmony / HarmonyOS 设备通过 hdc 推文件、改系统分区权限配置时遇到的一系列诡异报错。

0. 背景

在给设备预置系统级权限配置文件(如 install_list_permissions.json)时,标准流程大概是:

hdc shell "mount -o remount,rw /"
hdc file send 本地配置.json system/etc/app/
hdc shell reboot

看起来每一步都没问题,但现实往往是:第一次能成功,重启之后同样一条命令开始连环报错,而且越重试越错。下面把最常见的 6 个坑一次性讲清楚。


坑 1:no such file or directory 不一定是设备上没文件

报错长这样:

[Fail]Error opening file: no such file or directory, path:E:\...\install_list_permissions.json

直觉会让你去设备里找文件是不是没了,但真相是:hdc 客户端在本地(你这台电脑上)打不开源文件。

排查要点:

  • 先在电脑上确认源文件确实存在、Test-Path / ls 能命中。
  • 重点检查路径中是否含有中文或特殊字符,以及目录名有没有隐藏字符、尾部空格。
  • 如果文件明明在,十有八九是下面「坑 4」的中文路径问题,而不是设备端问题。

一句话:这个报错指的是本地源文件,和设备、和 remount 都没关系。


坑 2:hdc shell reboot 之后链接会重新枚举

很多人习惯在推送完之后顺手 reboot,然后下一句就接着 mount / file send,结果立刻撞上:

[Fail]ExecuteCommand need connect-key? please confirm a device by help info
[Fail][E001003] USB communication abnormal, please check the USB communication link.

原因:

  • 设备重启 → USB 重新枚举 → hdc 的 session 被释放,连接标识(connect key)会变;
  • 客户端发现目标设备"变了",要求重新确认设备;
  • 如果 USB 链路在枚举瞬间没稳住,就会出现 E001003 通信异常。

正确做法:reboot 之后,等系统完全进入桌面,重新 hdc list targets 确认设备在线,再继续后续操作。 不要在一条命令串里把 reboot 和后续步骤连写。


坑 3:多版本 hdc.exe 混用,客户端和服务端版本错配

这是最隐蔽、也最坑的一个。

3.1 全局只能有 1 个 hdc server

  • hdc 是 C/S 架构:你在命令行敲的 hdc 只是客户端,真正干活的是后台服务端进程(默认监听 TCP 8710)。
  • 8710 端口是独占的,所以全机同一时刻只能有 1 个 server。
  • 机制是「谁先跑谁当 server」:客户端发现 8710 没人监听时,会用自身二进制 fork 出一个 server 进程;之后不管你敲哪个版本的 hdc,都只是连到这个已存在的 server。

3.2 版本错配的后果

如果你的机器装了多个工具(不同版本的 IDE、SDK、烧录套件等),它们各自带了一份 hdc.exe:

  • PATH 里配的版本 ≠ 实际在跑的 server 版本;
  • 任何一个工具/插件/投屏先启动,都会把 server 定成它自带那一版;
  • 于是出现「3.x 客户端 ↔ 1.x 老 server」的错配,同一条命令在不同时间点行为不一致。

自检命令:

hdc checkserver

它会同时打印 Client version 和 Server version,两边不一致就要警惕。

规避方法:

  1. 把 PATH 里多余的旧版 hdc 目录(尤其是烧录套件自带的)去掉;
  2. 固定用一个全路径的 hdc.exe,全程不切换;
  3. 必要时显式重启 server 以统一版本:
    set HDC="<固定路径>\toolchains\hdc.exe"
    %HDC% kill
    %HDC% start -r
    %HDC% checkserver    :: 确认 Client/Server 版本一致
    

注意:-s [ip:]port 这套多实例参数实测并不好用,多开还会争抢同一台 USB 设备让 E001003 更频繁。别尝试多开。


坑 4:中文路径会让 hdc 在本地就打不开文件

这个问题在版本错配时尤其容易爆发。表现为:file send 一个含中文目录的本地文件,直接 no such file or directory,但文件明明存在。

根因是某些旧版 hdc 客户端在解析本地路径时,对中文目录名做了 UTF-8 → GBK 的错解,把 权限预授予文件 之类目录变成了乱码字符串,自然找不到文件。

最稳妥的规避:把要推送的源文件复制到一个纯 ASCII 路径下,例如:

copy "E:\项目\某某系统的权限预授予文件\install_list_permissions.json" "E:\tmp\ilp.json"
hdc file send E:\tmp\ilp.json system/etc/app/

实测:同样的文件,换纯英文路径后本地立刻能正常打开,推送成功。


坑 5:file recv 会多套一层目录

从设备拉文件时:

hdc file recv /etc/app/ E:\备份目录\

实际会把设备上的文件放进 E:\备份目录\app\ 里(多了一层 app\)。如果你之后又用平铺路径去 file send,很容易把原件和手工改过的副本搞混。

建议:recv 之后先 tree / 列目录确认实际落盘结构,再决定后续推送用哪个文件。


坑 6:重启后 /system 可能回退

mount -o remount,rw / 每次重启都要重做(这点很多人知道)。但更坑的是:只读分区(如 erofs)的写入,在重启后可能被还原。

务必推送后验证:

hdc shell "ls -l /system/etc/app/install_list_permissions.json"
:: 记下 size,reboot 后再查一次,确认还在

如果重启后文件大小变了或消失了,说明写入没真正落盘,需要换写入方式或确认分区可写性。


7. 一份可直接照抄的安全流程

@echo off
set HDC="<固定路径>\toolchains\hdc.exe"
set DEV=<先用 hdc list targets 拿到的设备标识>

:: 1) 统一版本
%HDC% kill
%HDC% start -r
%HDC% checkserver

:: 2) 确认设备在线
%HDC% list targets

:: 3) 源文件放纯 ASCII 路径
copy "原始路径\install_list_permissions.json" "E:\tmp\ilp.json"

:: 4) 明确指定设备 + 重挂载
%HDC% -t %DEV% shell "mount -o remount,rw /"

:: 5) 推送(本地 ASCII 路径 + 绝对远端路径)
%HDC% -t %DEV% file send E:\tmp\ilp.json /system/etc/app/

:: 6) 验证落地
%HDC% -t %DEV% shell "ls -l /system/etc/app/install_list_permissions.json"

:: 7) 重启后复查(等系统完全进桌面再连)
%HDC% -t %DEV% shell reboot
:: ... 稍候 ...
%HDC% list targets
%HDC% -t %DEV% shell "ls -l /system/etc/app/install_list_permissions.json"

8. 速查表

现象真正含义对策
Error opening file ... no such file客户端打不开本地源文件查本地路径/中文目录,复制到 ASCII 路径
need connect-key重启后 USB 重枚举,设备变了等进系统,list targets 重确认
[E001003] USB abnormalUSB 链路断了重插拔、换口、去掉 HUB
checkserver Client≠Server多版本 hdc 错配固定单版本,kill+start 统一
recv 后文件"消失"多套了一层 app\列目录确认落盘结构
重启后配置没了只读分区回退验证 size,确认可写性

9. 小结

hdc 推送失败,90% 不是设备的问题,而是本机环境的问题:版本乱、路径带中文、reboot 后没等链路稳。记住三件事就能避开绝大多数坑:

  1. 固定一个 hdc 版本,用 checkserver verify 客户端与服务端一致;
  2. 本地源文件用纯 ASCII 路径;
  3. reboot 之后等系统就绪再操作,并验证文件是否真正落盘。

踩完这 6 个坑,希望你能一次推成功。

Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

更多推荐