李明的个人技术随记 - 默认分类
type: channel
link: http://47.242.91.167/category/default/
description: 只是一个默认分类
items: RK3528 Armbian 改造成 RDP 瘦客户机：开机自启、OpenVFD 状态显示和 VirtualHere 反向连接
items: AP 模式下关闭 DHCP 客户端，并使用 reset 按钮控制 WiFi 开关
items: Android USB Gadget 手机模拟真实U盘 操作命令记录
items: windows 配置优先ipv4 dns解析
items: com0com-hub4com-串口转TCP命令记录
items: hyper-v 限制宿主机核心 并绑定虚拟机核心配置
items: windows 使用N2n打开流量转发 并使用系统 ip转发 nat流量伪装
items: 使用powershell隐藏启动程序 并保留会话id
items: 编辑系统BCD文件实现启动任意分区上的VHDX虚拟硬盘
items: windows使用ffmpeg 流式传输音视频频到SRS服务器

RK3528 Armbian 改造成 RDP 瘦客户机：开机自启、OpenVFD 状态显示和 VirtualHere 反向连接
type: item
date: 2026-05-09T11:13:00+08:00
description: 背景手里这块 RK3528 盒子跑的是 Armbian / Ubuntu 24.04，当前内核是 6.1.115-vendor-rk35xx。实际需求不是跑 RT-Linux，而是把它改造成一个专用 RDP 瘦客户机：开机尽量快。只用有线网口。自动全屏连接指定 Windows RDP 主机。前面板数码管显示 RDP 目标 IP。LAN/WiFi 图标分别显示本地网络和 RDP 目标连通状态。VirtualHere USB Server 开机自启，并反向连接到 RDP 服务器上的客户端。下面命令以设备 IP 172.30.5.38、RDP 目标 172.30.5.17 为例。涉及密码的地方请替换成自己的值，文章里不放实际密码。1. 安装 RDP kiosk 基础组件apt update apt install -y freerdp3-x11 openbox unclutter x11-xserver-utils创建 kiosk 启动脚本：cat >/usr/local/bin/rdp-kiosk-session <<'EOF' #!/bin/bash set -u RDP_HOST="172.30.5.17" RDP_USER="你的RDP用户名" RDP_PASS="你的RDP密码" xset s off xset -dpms xset s noblank xsetroot -solid '#202020' 2>/dev/null || true unclutter -idle 0.5 -root & openbox & while true; do if command -v xfreerdp3 >/dev/null 2>&1; then RDP_BIN=xfreerdp3 else RDP_BIN=xfreerdp fi until timeout 1 bash -c "</dev/tcp/$RDP_HOST/3389" 2>/dev/null; do sleep 0.3 done if [ -e /tmp/rdp-windowed ]; then "$RDP_BIN" /v:"$RDP_HOST" /u:"$RDP_USER" /p:"$RDP_PASS" \ /size:1600x900 /dynamic-resolution /cert:ignore +clipboard \ /network:auto /auto-reconnect /auto-reconnect-max-retries:999 else "$RDP_BIN" /v:"$RDP_HOST" /u:"$RDP_USER" /p:"$RDP_PASS" \ /f -decorations /dynamic-resolution /cert:ignore +clipboard \ /network:auto /auto-reconnect /auto-reconnect-max-retries:999 fi sleep 1 done EOF chmod 755 /usr/local/bin/rdp-kiosk-session注册 LightDM 会话。不同镜像默认用户可能叫 armbian、admin 或其它名字，所以先取当前系统的普通用户变量：KIOSK_USER="${KIOSK_USER:-$(id -un 1000 2>/dev/null || awk -F: '$3>=1000 && $3<60000 {print $1; exit}' /etc/passwd)}" KIOSK_HOME="$(getent passwd "$KIOSK_USER" | cut -d: -f6)" cat >/usr/share/xsessions/rdp-kiosk.desktop <<'EOF' [Desktop Entry] Name=RDP Kiosk Comment=Auto start RDP session Exec=/usr/local/bin/rdp-kiosk-session Type=Application EOF mkdir -p /etc/lightdm/lightdm.conf.d cat >/etc/lightdm/lightdm.conf.d/99-rdp-kiosk.conf <<EOF [Seat:*] autologin-user=$KIOSK_USER autologin-user-timeout=0 autologin-session=rdp-kiosk user-session=rdp-kiosk greeter-session=slick-greeter EOF systemctl set-default graph…

AP 模式下关闭 DHCP 客户端，并使用 reset 按钮控制 WiFi 开关
type: item
date: 2026-04-27T11:31:09+08:00
description: 这篇记录整理一次 AP 模式配置过程：关闭设备自身的 DHCP 客户端，设置 br-lan 固定地址，并让 WiFi 默认关闭，只有按住 reset 按钮时才临时开启 5G WiFi。这样设备平时可以保持安静状态，需要连接维护时再手动打开无线。配置目标最终效果如下： 设备工作在 AP/桥接使用场景 br-lan 使用固定地址 192.168.2.254/24 关闭 DHCP 客户端，避免自动获取上级网络地址 WiFi 默认关闭 按住 reset 按钮时开启 5G WiFi 松开 reset 按钮后关闭 5G WiFi 红灯用于提示启动过程和按钮触发状态 挂载根分区并修改密码先挂载根分区为可写：mount_root下面示例把 root 密码设置为 1：printf '%s\n%s\n' '1' '1' | passwd root关闭 WiFi 默认射频关闭 2.4G 和 5G 的默认射频开关，让 WiFi 不在开机后自动开启：sed -i 's/^RadioEnable=.*/RadioEnable=0/' /etc/wireless/mediatek/mt7981.dbdc.b0.dat sed -i 's/^RadioEnable=.*/RadioEnable=0/' /etc/wireless/mediatek/mt7981.dbdc.b1.dat调整 5G WiFi 参数这里以 5G 配置文件 mt7981.dbdc.b1.dat 为例，手动指定信道并关闭部分节能和 MU 相关功能：sed -i 's/^Channel=.*/Channel=161/' /etc/wireless/mediatek/mt7981.dbdc.b1.dat sed -i 's/^AutoChannelSelect=.*/AutoChannelSelect=0/' /etc/wireless/mediatek/mt7981.dbdc.b1.dat sed -i 's/^HT_BW=.*/HT_BW=1/' /etc/wireless/mediatek/mt7981.dbdc.b1.dat sed -i 's/^VHT_BW=.*/VHT_BW=2/' /etc/wireless/mediatek/mt7981.dbdc.b1.dat sed -i 's/^TxPower=.*/TxPower=100/' /etc/wireless/mediatek/mt7981.dbdc.b1.dat sed -i 's/^TWTSupport=.*/TWTSupport=0/' /etc/wireless/mediatek/mt7981.dbdc.b1.dat sed -i 's/^MuMimoDlEnable=.*/MuMimoDlEnable=0/' /etc/wireless/mediatek/mt7981.dbdc.b1.dat sed -i 's/^MuMimoUlEnable=.*/MuMimoUlEnable=0/' /etc/wireless/mediatek/mt7981.dbdc.b1.dat sed -i 's/^MuOfdmaDlEnable=.*/MuOfdmaDlEnable=0/' /etc/wireless/mediatek/mt7981.dbdc.b1.dat sed -i 's/^MuOfdmaUlEnable=.*/MuOfdmaUlEnable=0/' /etc/wireless/mediatek/mt7981.dbdc.b1.dat /sbin/wifi reload如果需要降低发射功率，可以把 TxPower=100 调整为较小值，例如：sed -i 's/^TxPower=.*/TxPower=4/' /etc/wireless/mediatek/mt7981.dbdc.b1.dat关闭 DHCP 客户端通过重命名 udhcpc 和 wan_type_probe，避免系统继续自动启动 DHCP 客户端或 WAN 类型探测：mv /sbin/udhcpc /sbin/udhcpcbak cd /usr/bin mv wan_type_probe wan_type_probebak配置 rc.local写入 /etc/rc.local，开机后清理缓存、启动 telnet，并给 br-lan 添加固定 IP：cat > /etc/rc.local <<'EOF' # Put your custom commands here that should be executed once # the system init finished. By default this file does nothing. echo 3…

Android USB Gadget 手机模拟真实U盘 操作命令记录
type: item
date: 2026-04-04T17:30:00+08:00
description: Android USB Gadget 操作命令记录目标关闭默认 MTP保留 ADB使用 mass_storage 导出一个 30G FAT32 镜像文件backing file 放在 /data/codex_empty_file连接设备telnet 10.221.3.83查看当前 USB 属性getprop | grep usb getprop persist.sys.usb.config getprop sys.usb.config getprop sys.usb.state创建空文件并赋权touch /data/codex_empty_file chmod 666 /data/codex_empty_file ls -l /data/codex_empty_file切换 USB 为 mass_storage + adbsetprop persist.sys.usb.config mass_storage,adb setprop sys.usb.config mass_storage,adb sleep 3 getprop persist.sys.usb.config getprop sys.usb.config getprop sys.usb.state创建 30G 镜像并格式化为 FAT32说明：先断开当前 gadget 绑定用 fallocate 创建 30G 镜像文件用 losetup 挂到 loop 设备用 mkfs.vfat -F 32 格式化成 FAT32echo '' > /config/usb_gadget/g1/UDC echo '' > /config/usb_gadget/g1/functions/mass_storage.0/lun.0/file rm -f /data/codex_empty_file fallocate -l 30G /data/codex_empty_file LOOP=$(losetup -f) echo $LOOP losetup $LOOP /data/codex_empty_file mkfs.vfat -F 32 $LOOP losetup -d $LOOP挂回 USB mass_storageecho /data/codex_empty_file > /config/usb_gadget/g1/functions/mass_storage.0/lun.0/file echo 0 > /config/usb_gadget/g1/functions/mass_storage.0/lun.0/cdrom echo 0 > /config/usb_gadget/g1/functions/mass_storage.0/lun.0/ro echo 1 > /config/usb_gadget/g1/functions/mass_storage.0/lun.0/removable echo a600000.dwc3 > /config/usb_gadget/g1/UDC检查最终状态getprop sys.usb.state cat /config/usb_gadget/g1/functions/mass_storage.0/lun.0/cdrom cat /config/usb_gadget/g1/functions/mass_storage.0/lun.0/ro cat /config/usb_gadget/g1/functions/mass_storage.0/lun.0/removable cat /config/usb_gadget/g1/functions/mass_storage.0/lun.0/file ls -lh /data/codex_empty_file期望结果sys.usb.state = mass_storage,adb cdrom = 0 ro = 0 removable = 1 file = /data/codex_empty_file常用补充命令改回仅 ADBsetprop persist.sys.usb.config adb setprop sys.usb.config adb纯 HID 键盘临时切换并输入字符串用途：临时把手机切成 纯 HID 键盘向电脑当前焦点窗口输入指定字符串测试完成后再切回 mass_storage + adb注意：纯 HID 模式下，临时不会保留 U 盘功能切到纯 HID 后，ADB 也可能暂时断开字符会输入到电脑当前有焦点的输入框1. 在 g2 上准备纯 HID 键盘 gadgetmkdir -p /config/usb_gadget/g2/configs/b.1/strings/0x409 mkdir -p /con…

windows 配置优先ipv4 dns解析
type: item
date: 2026-04-04T14:52:58+08:00
description: Windows 优先 IPv4 设置说明更新时间：2026-04-04 14:51:13 +08:00方案说明推荐使用“优先 IPv4，而不是禁用 IPv6”的方式。 这样兼容性更好，也更符合 Windows 的网络设计。方法一：调整前缀策略以管理员身份打开 PowerShell 或 CMD，执行：netsh interface ipv6 set prefixpolicy ::ffff:0:0/96 60 4 netsh interface ipv6 set prefixpolicy ::/0 40 1查看当前策略：netsh interface ipv6 show prefixpolicies方法二：注册表方式（官方常见做法）以管理员身份打开 PowerShell 或 CMD，执行：reg add "HKLM\SYSTEM\CurrentControlSet\Services\Tcpip6\Parameters" /v DisabledComponents /t REG_DWORD /d 32 /f执行后重启电脑生效。参数含义32 表示：Prefer IPv4 over IPv6这不是彻底关闭 IPv6比直接禁用网卡 IPv6 更稳妥临时只使用 IPv4如果只是某次命令想强制 IPv4，可以这样写：ping -4 redmibook tracert -4 redmibook恢复默认如果后面想恢复默认优先级，可执行：reg delete "HKLM\SYSTEM\CurrentControlSet\Services\Tcpip6\Parameters" /v DisabledComponents /f然后重启电脑。不建议的做法不建议直接在网卡属性里取消勾选 IPv6这可能影响局域网发现、共享、部分系统服务建议优先推荐先试：注册表 DisabledComponents = 32重启电脑用 ping -4、应用访问、局域网连接再测试

com0com-hub4com-串口转TCP命令记录
type: item
date: 2026-03-26T17:59:39+08:00
description: com0com / hub4com 串口转 TCP 命令记录项目地址com0com / hub4com（SourceForge） https://sourceforge.net/projects/com0com/com0com GitHub 镜像 https://github.com/tanvir-ahmed-m4/com0com说明这套工具可用于：创建虚拟串口对串口与 TCP 之间转发RFC2217 串口网络转发当前已验证可工作的命令如下。hub4com / com2tcp-rfc2217 命令1. 客户端模式本机串口 COM4 主动连接远端 172.30.5.62:7000com2tcp-rfc2217.bat --reconnect 1000 \\.\COM4 172.30.5.62 7000说明：--reconnect 1000：断开后每 1000 ms 重连\\.\COM4：本地串口172.30.5.62：远端服务器 IP7000：远端 TCP 端口2. 服务端模式本机串口 COM4 作为 TCP Server，监听 7000com2tcp-rfc2217.bat \\.\COM4 7000说明：本地监听 TCP 7000远端客户端连接后，数据转发到 COM4备注com2tcp-rfc2217.bat 比直接手敲 hub4com.exe 更省事直接写 hub4com 的 TCP 端点语法容易因为版本差异报错优先使用项目自带的 .bat 脚本更稳常用场景串口转 TCP 服务端适合让其他设备主动连本机：com2tcp-rfc2217.bat \\.\COM4 7000串口转 TCP 客户端适合本机主动连远端：com2tcp-rfc2217.bat --reconnect 1000 \\.\COM4 172.30.5.62 7000

hyper-v 限制宿主机核心 并绑定虚拟机核心配置
type: item
date: 2026-03-25T15:26:00+08:00
description: Hyper-V 绑定 CPU 教程：宿主机 bcdedit 与 cpugroups.exe 实战配置在做工业控制、实时通信、低抖动虚拟化测试时，很多人会希望把 Hyper-V 虚拟机尽量固定到指定 CPU 上运行，减少宿主机对虚拟机的干扰。本文介绍一套比较实用的做法，包括：使用 bcdedit /set hypervisorrootproc 2 给宿主机预留 CPU使用 bcdedit /set hypervisorschedulertype Core 设置 Hyper-V 调度器使用 cpugroups.exe 将虚拟机绑定到指定逻辑处理器这套方法适合 Windows Server 宿主机上的 Hyper-V 场景，尤其适合对时延、抖动比较敏感的工作负载。一、先理解三个概念1. hypervisorschedulertype用于设置 Hyper-V 的调度方式，常见值有：CoreClassic在 Windows Server 2019 及之后版本中，通常建议优先使用 Core。2. hypervisorrootproc用于限制 Root Partition，也就是宿主机自己可以使用的 Root VP 数量。例如：bcdedit /set hypervisorrootproc 2表示尽量把宿主机控制在 2 个 Root 处理器上运行。3. CPU Groups这是 Hyper-V 更细粒度的 CPU 隔离机制。通过 cpugroups.exe，可以把某台虚拟机限制到一组指定的逻辑处理器上，例如只让虚拟机跑在 LP 2,3 上。二、为什么要做 CPU 绑定默认情况下，Hyper-V 会自动调度宿主机和虚拟机到不同 CPU 上运行。对于普通办公和服务器虚拟化，这样没问题；但对于一些对抖动敏感的场景，默认调度不一定够稳。典型目的包括：减少宿主机线程抢占虚拟机减少虚拟机运行位置漂移给实时任务保留更稳定的 CPU提高 EtherCAT、运动控制、采集等场景的稳定性需要注意的是，这种优化只能“降低干扰”，不能把 Hyper-V 直接变成硬实时平台。三、查看当前宿主机 CPU 拓扑先在宿主机管理员 PowerShell 中执行：CpuGroups.exe GetCpuTopology示例输出：LpIndex NodeNumber PackageId CoreId RootVpIndex 0 0 0 0 0 1 0 0 1 1 2 0 0 2 -1 3 0 0 3 -1这里最关键的是：LpIndex：逻辑处理器编号RootVpIndex >= 0：表示这个逻辑处理器已经分配给宿主机 Root PartitionRootVpIndex = -1：表示这个逻辑处理器当前不属于 Root，可优先供 Guest 使用例如上面的拓扑可以理解为：LP 0,1 给宿主机LP 2,3 可优先给虚拟机四、配置宿主机 BCD 参数先设置 Hyper-V 调度器为 Core：bcdedit /set hypervisorschedulertype Core再设置宿主机 Root Partition 只保留 2 个 Root 处理器：bcdedit /set hypervisorrootproc 2最后确认 Hyper-V 会正常启动：bcdedit /set hypervisorlaunchtype auto改完后重启宿主机：shutdown /r /t 0重启后可查看当前配置：bcdedit /enum你会看到类似：hypervisorlaunchtype Auto hypervisorrootproc 2 hypervisorschedulertype Core五、创建 CPU Group 并绑定虚拟机假设现在想把某台虚拟机绑定到逻辑处理器 2,3。先创建 CPU Group：CpuGroups.exe CreateGroup /GroupId:36AB08CB-3A76-4B38-992E-000000000001 /GroupAffinity:2,3说明：GroupId 可以自定义一个 GUIDGroupAffinity:2,3 表示这个组只包含 LP 2,3然后把虚拟机绑定到这个组：CpuGroups.exe SetVmGroup /VmName:1 /GroupId:36AB08CB-3A76-4B38-992E-000000000001这里的 1 是虚拟机名称，请改成你自己的虚拟机名。查看绑定结果：CpuGroups.exe GetVmGroup示例输出：VmName VmId CpuGroupId 1 471D946F-C7CD-4A72-A770-52EF3287DA36 36AB08CB-3A76-4B38-992E-000000000001再…

windows 使用N2n打开流量转发 并使用系统 ip转发 nat流量伪装
type: item
date: 2026-03-20T14:25:00+08:00
description: 一、开启 Windows 系统 IP 转发`reg add "HKEY_LOCAL_MACHINESYSTEMCurrentControlSetServicesTcpipParameters" /v IPEnableRouter /t REG_DWORD /d 1 /fGet-NetIPInterfaceSet-NetIPInterface -InterfaceAlias "你的n2n网卡名" -Forwarding EnabledSet-NetIPInterface -InterfaceAlias "你的外网网卡名" -Forwarding Enabled`二、做 NAT / 流量伪装New-NetNat -Name "n2nNat" -InternalIPInterfaceAddressPrefix "10.10.10.0/24"三，n2n 配置文件加上-r 参数允许转发

使用powershell隐藏启动程序 并保留会话id
type: item
date: 2026-03-16T10:53:55+08:00
description: powershell -windowstyle hidden -command "Start-Process 'xx.exe' -ArgumentList '--hidden' -WindowStyle Hidden"使用任务计划开机启动schtasks /create /tn "XXNAME" `/tr "powershell -windowstyle hidden -command Start-Process 'XX.exe' -ArgumentList '--hidden' -WindowStyle Hidden" `/sc onlogon `/rl highest `/f`

编辑系统BCD文件实现启动任意分区上的VHDX虚拟硬盘
type: item
date: 2026-03-07T11:12:00+08:00
description: 让windows开机过程中显示引导项目bcdedit /set "{bootmgr}" displaybootmenu yes1 复制当前系统启动项bcdedit /copy "{current}" /d "Windows 10 LTS VHD"会返回一个 GUID，例如：PS C:Userstm> bcdedit /copy "{current}" /d "Windows 10 LTS VHD"已将该项成功复制到 {b893f6c7-2f23-11ef-915a-e1cc6f197b78}。2 设置 VHD 路径bcdedit /set "{b893f6c7-2f23-11ef-915a-e1cc6f197b78}" device vhd=[D:]\win10lts.vhdxbcdedit /set "{b893f6c7-2f23-11ef-915a-e1cc6f197b78}" osdevice vhd=[D:]\win10lts.vhdx3 设置检测 HALbcdedit /set "{b893f6c7-2f23-11ef-915a-e1cc6f197b78}" detecthal on查看启动项bcdedit /enum如果开机不显示启动菜单你之前说过 Win10 不显示启动菜单，可以设置：bcdedit /set {bootmgr} displaybootmenu yesbcdedit /timeout 10如果启动vhdx蓝屏一般vhdx是动态分配需要转换成静态分配格式,可以先删除一些分区然后缩小vhdx大小，这样静态分配出来的vhdx不会占用太多空间，注意缩小的大小要大于已经使用的分区1 缩小虚拟硬盘文件Resize-VHD "D:\win10lts.vhdx" -SizeBytes 32GB2 转换成预先分配格式Convert-VHD -Path d:\win10lts.vhdx -DestinationPath d:\win10_fixed.vhdx -VHDType Fixed

windows使用ffmpeg 流式传输音视频频到SRS服务器
type: item
date: 2024-08-19T13:29:00+08:00
description: 下载解压ffmpeg$sourceUrl = "http://www.moonnn.top:82/filerun/tool/ffmpeg.zip" $destinationPath = "C:\Users\Public\ffmpeg.zip" Start-BitsTransfer -Source $sourceUrl -Destination $destinationPath Expand-Archive -Path "C:\Users\Public\ffmpeg.zip" -DestinationPath "C:\Users\Public\" -Forcedocker安装srs服务器docker run --rm -it -p 1935:1935 -p 1985:1985 -p 8080:8080 registry.cn-hangzhou.aliyuncs.com/ossrs/srs:5列出所有设备ffmpeg -list_devices true -f dshow -i dummy传输音频ffmpeg -f dshow -i audio="阵列麦克风 (AMD Audio Device)" -c:v libx264 -c:a aac -b:a 320k -af "afftdn=nf=-20" -f flv rtmp://192.168.1.6/live/livestream #-af "afftdn=nf=-20降噪传输音视频ffmpeg -f dshow -i audio="阵列麦克风 (AMD Audio Device)" -f dshow -i video="XiaoMi USB 2.0 Webcam" -c:v libx264 -b:v 500k -c:a aac -b:a 320k -af "afftdn=nf=-20" -f flv rtmp://192.168.1.6/live/livestream