做嵌入式Linux这些年我见过太多人把精力全花在C语言和驱动框架上结果到了真机调试环节连在板子上查个CPU占用都要翻半天笔记。还有人抱着厚厚的《Linux命令大全》从头啃记了一大堆命令上板之后发现一半命令不存在——嵌入式设备的根文件系统是用BusyBox裁剪出来的不是装了完整发行版的服务器。今天这篇东西我想从一个常年跟开发板、交叉编译工具链、JTAG和串口打交道的工程师角度把嵌入式Linux命令这件事彻底聊透它跟普通Linux命令有什么区别、哪些命令在开发中最值得投入时间、真正遇到问题的时候应该怎么用命令一层层排查下去。内容不会按“命令手册”那种罗列方式写而是按真实开发场景拆给你看。1. 嵌入式Linux命令的认知框架先搞清楚板子上到底有什么1.1 为什么开发板上的命令和PC上的不一样很多人第一次拿到开发板敲ls /home发现目录不存在敲useradd直接报错敲vim告诉你没有这个程序瞬间就懵了。这不是你操作错误而是嵌入式系统的根文件系统天生就“缺斤少两”。嵌入式设备里的绝大多数命令来自BusyBox——一个把上百个Linux常用工具集合进单一可执行文件的黑科技程序。它就像一个瑞士军刀一个二进制文件里同时提供了ls、cat、grep、ps、route等命令的简化实现。由于资源受限Flash存储空间往往只有几十MB甚至几MB所以BusyBox默认只编译进一部分常用命令而且每条命令的实现都只保留核心参数砍掉了不常用的选项和详细帮助文档。这就带来两个直接影响第一命令数量不全man、apt、systemctl这种重工具基本不会出现第二即使命令存在行为也跟PC上有细微差别。比如BusyBox的ps默认只显示当前终端的进程加-ef才能看到全部进程BusyBox的top没有彩色界面某些列也不一样。十几年来我踩过的坑里有一大半不是业务逻辑写错了而是搞混了“宿主机上的命令”和“目标板上的命令”。理解这个差异特别重要。你在Ubuntu虚拟机里用得好好的ifconfig到板子上可能名字变成了ip甚至两个都没有只剩一个busybox ifconfig。我在项目里就遇到过只有ip命令、没有ifconfig的内核版本如果你的脚本里写死了ifconfig eth0 192.168.1.10 up那么对不起直接提示ifconfig: not found。1.2 学习路线的现实建议既然板子上的环境这么“简陋”学习嵌入式Linux命令就不能像备考计算机二级那样面面俱到。我个人建议按下面的优先级来学这是无数个项目验证过的有效路径第一阶段文件系统与基础操作。cd、ls、cp、mv、rm、mkdir、cat、mount、df。这些是你在板子上搬运文件、挂载SD卡和U盘都要用的基础。第二阶段文本处理与系统信息。grep、sed、awk、tail、head、ps、top、free、dmesg。查日志、看内存、定位进程全靠这批命令。第三阶段网络诊断。ping、ifconfig、ip、telnet、nc、route、tcpdump。嵌入式开发躲不开网络NFS挂载、远程调试、端口连接测试全都依赖它们。第四阶段命令组合与脚本化。管道|、重定向、xargs、find。把多个命令串起来解决实际问题这是从“会敲命令”到“会调问题”的分水岭。还有一个很关键的练习方法不要只在虚拟机上敲强烈建议入手一块能跑真系统的开发板或者至少在虚拟机里用QEMU模拟一个ARM环境。因为只有在一个命令不全、性能受限、行为跟PC有差异的环境里你才会真正理解哪些命令是“保命”的哪些命令是“花架子”。练习时间不需要太长每天二十分钟坚持两周你的上手速度会明显不一样。2. 板子上最高频的系统与文本命令深度用法2.1 文件操作最基础也最容易被低估文件操作命令看起来简单但在嵌入式场景里围绕它们有很多工程细节。先说ls。查看根文件系统用ls -l能看权限、大小、链接这是确认驱动节点是否生成的第一手段。比如你加载了一个USB驱动怎么看设备有没有注册先去/dev下ls看有没有对应的设备文件。驱动名字是内核里的但用户态能不能用就取决于设备节点。很多时候你写好了驱动但/dev下没节点ls -l /dev/xxx返回No such file or directory这时候你就知道问题出在设备节点创建而不是驱动代码本身。mount命令在嵌入式开发里的地位是顶级的。开发阶段最舒服的做法是什么把编译好的可执行程序放到Ubuntu服务器上开发板上用NFS挂载服务器目录直接运行不用反复拷贝进Flash。挂载命令一般这样写mount -t nfs -o nolock 192.168.1.100:/home/project/nfs /mnt/nfsnolock这个参数是重点。很多简单的嵌入式NFS客户端没有实现完整的文件锁协议不加nolock就会挂载后一切正常但一执行文件就卡住弹出一堆RPC相关报错。这是我在三个不同项目里反复确认过的坑也是网上被问烂了的问题你提前知道就能省一天时间。df -h用于查看分区占用情况。嵌入式设备Flash空间紧张经常出现日志把系统写满、程序崩溃的情况。怀疑磁盘满了先执行df -h看到/使用率100%然后du -sh /var/log找出哪个目录在吃空间这条排查路径能解决八成“我的程序怎么跑着跑着不跑了”的问题。2.2 文本处理三件套grep、sed、awk如果只能选择三个命令带开发板我会选grep、sed、awk。大部分人在嵌入式Linux里调bug本质上就是在文本海洋里捞关键信息。grep的核心场景是过滤。调试网络驱动异常先看内核打印了什么dmesg | grep -i eth看应用日志里有没有发生错误还是警告不看整个文件只关注关键字tail -f /var/log/app.log | grep -i error-i忽略大小写-r递归子目录-v反向匹配这几个参数必须刻在脑子里。我在串口终端看启动日志时经常用dmesg | grep -i failed\|error\|oops把异常信息一屏拉出来效率极高。sed在嵌入式里的主要用途是改配置不用进编辑器。很多板子的根文件系统只读需要先把配置文件复制到可写分区再用sed -i批量替换。比如把服务地址改成新IPsed -i s/192.168.1.10/192.168.1.20/g /mnt/config/app.confawk最常见的用法是取某一列。查进程ID并把它杀掉这在嵌入式调试里出现频率极高ps -ef | grep myapp | grep -v grep | awk {print $2} | xargs kill -9这段命令的组合逻辑很值得拆。第一个grep myapp把包含应用名字的进程行筛出来第二个grep -v grep是去掉grep自己这个进程行awk {print $2}在ps -ef输出里第二列正好是PID最后xargs kill -9对提取出的PID逐个执行强制杀死。这套组合拳我在各种场景里用了无数次已经成了肌肉记忆。2.3 系统状态与性能排查不看白学的ps和top板子上程序起来之后不正常第一步永远是查系统状态。BusyBox的top -n 1 -b要记住-n 1表示只刷新一次-b是批处理模式适合在串口终端里直接看结果。它能列出CPU占用最高的几个进程。看到可疑进程占用99%多半是死循环或者驱动轮询出了问题。free查看内存总量和剩余量。嵌入式设备内存本来就小泄漏几十KB都可能让系统慢慢卡死。如果程序长时间运行后free显示available持续下降基本可以断定有内存泄漏。这时候下一步就是配合ps看看哪个进程的VSZ虚拟内存大小一直在涨。cat /proc/meminfo是个宝藏命令很多工程师不知道去看内存细节数值。它有MemTotal、MemFree、Buffers、Cached、Slab这些项配合free能得到比服务器工具还准确的内存画像。有一次我的板子频繁OOMfree看着还有几十MB但系统就是被杀进程最后是看/proc/meminfo里MemAvailable远小于MemFree才定位到问题——原来是被内核页缓存吃掉了这个经验非常冷门但很救命。dmesg是另一个亲爹级命令。内核打印的启动信息、驱动注册信息、错误中断信息全在这里。设备树配置错了、中断号冲突、DMA分配失败、文件系统挂载失败都会在dmesg里留下痕迹。遇到任何启动异常先dmesg | tail -50看看最后打印了什么比盲猜代码逻辑高效得多。3. 网络与调试命令嵌入式联调的关键武器3.1 网络配置与连通性检查一步到位现代嵌入式设备几乎都联网网络命令的重要性怎么强调都不过分。配置IP地址老工程师习惯用ifconfig eth0 192.168.1.100 netmask 255.255.255.0 up新工具链里用ip addr add 192.168.1.100/24 dev eth0。两个命令在不同系统上各有一席之地建议都熟。很多人困惑为什么自己配了IP还是ping不通网关实际上可能是没加up或者路由表里没有默认网关route add default gw 192.168.1.1要快速验证链路通不通ping是第一步。但要注意嵌入式里的ping行为比PC简单它只发ICMP包不代表TCP端口是通的。很多时候ping通了但你的应用连不上服务器因为服务器上对应的TCP服务根本没起来。检查TCP端口连通性最经典的办法就是用telnet直接连一下目标地址和端口。比如测试192.168.1.10这台设备上的80端口通不通telnet 192.168.1.10 80如果你看到输出的最后是屏幕变黑或者出现Connected to 192.168.1.10 Escape character is ^].说明端口开放连接成功。如果输出Connection refused说明端口没监听如果卡住不动直到超时提示timed out说明路由不可达或者防火墙把包丢了。测完以后记得退出先按Ctrl ]进入telnet命令行再敲quit回车。我刚开始不知道这个退出方法每次只能靠Ctrl C硬断在串口终端里很容易留下残缺状态。在BusyBox里如果没有telnet客户端有些裁剪版确实没有可以用ncnc -vz 192.168.1.10 80-v打印详细过程-z只扫描端口不发送数据。这个组合用来写网络检测脚本非常干净输出结果容易解析。3.2 NFS挂载开发阶段离不了的“免烧录大法”嵌入式开发里最普遍的调试手段就是NFS根文件系统或者NFS数据目录挂载。编译服务器上存放源码、库和应用开发板通过网络挂载直接运行服务器上的程序。代码改动、重新编译、直接在板子上跑全程不需要烧录Flash迭代速度快得不是一个量级。前面提过挂载命令一定要加nolock。除此之外nfsvers3也是个常见选项因为新版本NFS协议可能在内核配置简单的板子上不稳定mount -t nfs -o nolock,nfsvers3 192.168.1.100:/srv/nfs /mnt挂载成功后板子上ls /mnt就能看到服务器的目录内容。这一步验证通过代表网络链路、NFS服务、内核的NFS客户端支持全都正常。我处理过很多“为什么我的应用程序在板子上跑不起来”的问题最后发现根源不是代码而是NFS挂载失败导致动态库没加载到或者权限位错乱。3.3 抓包与运行时调试三板斧当网络通了、程序还是有问题时就轮到抓包和运行时调试上场。tcpdump是网络问题定位的王牌。嵌入式里没有Wireshark的图形界面但tcpdump -i eth0直接抓取网卡上的所有流量并打印到终端。你可以配合-c限制包数量比如抓10个包就自动停止tcpdump -i eth0 -c 10 host 192.168.1.100当你的MQTT发送不出去、TCP握手一直SYN_SENT、UDP收不到回复时用tcpdump观察有没有包发出、有没有包回来、包的大小和TCP标志位是什么问题就原形毕露了。很多时候不是应用层代码错了而是路由表错误或者对端根本没回包。strace是另一个调试神器。它是一个系统调用跟踪器能记录程序执行过程中调用的所有系统函数、参数和返回值。编译时要确认Buildroot里勾选了strace工具很多裁剪系统上没有那就要自己交叉编译一份拷进根文件系统。用法strace -f -o /tmp/trace.log ./my_app看日志里哪个系统调用返回-1以及errno是多少往往立刻就能定位到文件、设备节点或权限问题。cat /proc/interrupts也值得提一句。它能查看中断分发情况如果你的驱动注册了中断但一直没有中断计数增长说明硬件信号没到CPU或者中断配置错了。这种内核层面的调试命令行反而是最直观的。4. 命令组合实战从现象到根因的一次完整排查4.1 一个真实可复现的排查场景假设你负责的板子上跑着一个采集程序刚启动时一切正常跑了几个小时后变得很卡串口敲命令都延迟网络也时通时断。如果是我来处理一定会按照下面的命令顺序层层剥开而不是直接去翻源代码找死循环。第一步看系统负载和CPU谁在忙top -n 1 -b我会盯住占用前三名的进程。如果是一个叫sensor_d的进程占了90%问题基本锁定下一步看它是不是在什么路径上卡死了。第二步看进程状态和线程数ps -ef | grep sensor_d进程还在但状态是R运行、S睡眠还是D不可中断睡眠如果大量D状态说明进程在做磁盘IO或访问一个不响应的设备节点。嵌入式里这种问题特别多程序代码去读一个没有应答的I2C外设内核驱动在等待总线超时进程就挂在了D状态。第三步查看内核日志确认异常来源dmesg | tail -30如果有大量I2C transfer timeout或者virtio_net: receive error之类的日志原因就清晰了某个外设挂起驱动反复重试最终拖垮了整个系统。第四步结合网络检查端口和服务状态netstat -an | grep 8080排查网络时通过netstat看8080端口有没有LISTEN连接数是不是爆满了。如果大量连接处于TIME_WAIT或CLOSE_WAIT说明应用没有正确关闭socket文件描述符泄漏了。配合ls /proc/pid/fd | wc -l看看这个进程打开了多少文件描述符如果这个数字不断上涨泄漏实锤。这个排查思路的最高价值在于每一条命令都只解决一个层级的问题从CPU到进程到内核到网络层层推进。很多新手一出问题就直接改代码重编译烧进板子发现还是老样子折腾一整天。命令行的正确姿势是“先观察后下结论”让系统自己告诉你它哪里不舒服。4.2 常见问题速查表我把这些年被问得最多、自己踩得最深的几个坑整理成一张表拿去就能用现象最高优先级检查命令常见原因与对策命令提示not foundwhich 命令名、ls /bin/命令名BusyBox没编译进该命令或者PATH环境变量缺失。重新编译BusyBox勾选命令或改用等效命令程序权限报错ls -l /path/to/app文件没有执行权限用chmod x补上或者根文件系统挂载为只读改挂载为rwNFS挂载卡死mount -t nfs -o nolock ...确认加了nolock参数NFS服务端目录存在服务器防火墙放行telnet端口不通ping 目标IP、netstat -an先ping确认主机可达再确认目标端口服务在监听最后检查应用侧防火墙应用程序找不到动态库echo $LD_LIBRARY_PATH、ls /usr/lib库文件没拷贝到板子或没把库路径加入LD_LIBRARY_PATH用ldd查看依赖网络丢包严重ifconfig eth0看RX/TX errors、tcpdump -i eth0检查网线、PHY芯片驱动、MAC地址是否冲突嵌入式里不太可能是带宽问题内存越来越少cat /proc/meminfo、ps -ef对比VSZ大概率内存泄漏用strace跟踪malloc/free或查/dev下设备节点是否无限创建这张表的原理不是让你背答案而是帮你建立一套“看到现象联想到哪个命令”的反射弧。5. 面试题自查与技能提升清单5.1 嵌入式Linux命令高频面试题很多应届生和转行工程师在嵌入式面试里被问到的Linux命令题非常集中。把这些题目的回答要点记牢比背五十条冷门命令有用得多。“怎么查看某个进程占用了多少内存”先ps -ef找到进程PID再cat /proc/PID/status看VmRSScat /proc/PID/smaps看详细内存映射。回答时主动提/proc文件系统面试官会觉得你的Linux功底到位。“怎么从一个日志文件里找出包含error的行并统计出现次数”grep error app.log | wc -l。再加一层如果要忽略大小写加-i如果要求去掉重复行加sort -u。这道题考察的是管道组合能力。“怎么判断服务器上某个TCP端口是否开放”答telnet ip port通了就是开放拒绝或超时就是关闭或者在脚本里用nc -vz。注意别只答一个把两个都放出来看起来经验更丰富。“启动时报错说找不到文件系统该怎么查”先dmesg | grep -i mount\|ext4\|emmc看内核挂载日志再cat /proc/mounts看当前挂载情况最后blkid或者ls /dev/mmcblk*确认设备节点是否存在。回答时能提到“设备树里root分区名和实际内核识别名不一致”这个细节会非常加分。“怎么把一段命令的输出写入文件并在屏幕上同时显示”tee。例如dmesg | tee /tmp/bootlog.txt。这个命令嵌入式调试里特别常用因为串口终端滚动太快边看边存下来非常节省时间。5.2 从命令熟练到项目经验怎么让技能落地只会敲命令不会做项目面试一样过不了。我见到成功的嵌入式工程师基本上都在两个方向上有积累一是对开源项目的深入理解二是自主完成的完整小项目。命令层面的“开源项目”最值得看的就是BusyBox和Buildroot的源码。BusyBox的代码结构能让你看到一条命令在资源受限环境下如何裁剪功能、如何用最小代码实现最常用功能。Buildroot则可以让你直观感受“勾选了哪些工具包生成的文件系统就有什么命令”这个认知是嵌入式Linux的基础能力。“完整小项目”不要求高大上。做一个用I2C读温度和湿度的采集器数据存成日志文件通过TCP上传由上位机展示。这样一个小项目你自然就会用到i2cdetect找设备地址、grep查日志、netstat确认端口、crontab做定时采集、awk处理数据全套命令都在项目里串起来了。面试官听你讲这个项目的技术细节时你顺口说出一句“当时发现日志文件一直在涨我写了个脚本用find按大小清理旧文件”比干巴巴说“我掌握了find命令”有说服力一百倍。关于版本管理嵌入式项目同样离不开git。git diff看代码改动、git log --oneline回顾提交历史、git status确认工作区状态。别小看这些基础操作它们是你代码质量的可视化证明。面试复盘项目时能清晰讲出某个bug在第几次提交后用什么方式修复的会让你的项目经历真实可信得多。写在最后的一点实操体会文章讲到这里技术内容已经差不多了。最后我想说的是命令这种技能光看不敲等于零。现在很多人收藏夹里躺了一堆命令大全面试前翻一翻上板以后脑子一片空白。我在带新人的时候经常让他们干一件事对着板子故意把系统搞坏几次——把网络配置删掉把脚本权限改成无执行权限把NFS目录卸掉再启动应用——然后用命令一层层排查恢复。这个过程走三遍基本上常见的命令组合和排查思路就刻进本能里了。顺便说一句tail -f看日志一定要养成习惯它能在几秒内让你看到程序实时的打印比反复重跑程序不知道高到哪里去。实战这东西没有任何捷径但一次认真的折腾胜过二十次背诵。
阅读完成 · 觉得有帮助?