嵌入式Linux开发必备:Shell命令与脚本实战指南

📅 2026/7/29 5:21:10
嵌入式Linux开发必备:Shell命令与脚本实战指南
1. 从“黑盒子”到“指挥棒”为什么Shell是嵌入式的命门刚接触嵌入式Linux的朋友常常会陷入一个误区把开发板当成一个“黑盒子”烧写好系统镜像后就一头扎进应用程序的C代码里。直到某一天需要查看一下系统日志、拷贝一个文件、或者临时改个网络配置才发现自己对这个运行着的系统几乎一无所知寸步难行。这时你才会真正意识到那个看似简陋的、只有光标闪烁的终端窗口才是你与这个嵌入式系统“对话”的唯一通道而这个通道的语言就是Shell。网络上热门的“嵌入式学习路线”里Shell和常用命令往往是基础中的基础但也是最容易被轻视的一环。很多人觉得不就是几个命令吗用到的时候查一下就行了。但真实的工作场景恰恰相反高效的嵌入式开发与调试80%的时间是在与Shell打交道。无论是排查一个偶发的内存泄漏关键词free,top,ps还是分析一个启动失败的问题关键词dmesg,journalctl或是批量处理测试数据关键词shell脚本Shell命令的熟练程度直接决定了你的“排障效率”和“控制力”。我们可以把嵌入式Linux系统想象成一个复杂的智能机器人。你的应用程序C/C程序是它的大脑和核心算法而Shell就是你手中的多功能遥控器。没有这个遥控器你无法命令它抬手操作硬件、查看自身状态系统监控、或者临时调整姿态修改配置。那些搜索“linux常用命令”、“adb shell”操作的朋友本质上都是在寻找这个“遥控器”的使用说明书。特别是对于资源受限的嵌入式设备没有图形界面Shell就是全部。理解Shell就是理解如何真正“驾驭”你的设备而不是仅仅“使用”它。2. Shell的本质不仅仅是命令解释器2.1 Shell是什么内核与用户之间的翻译官给一个最直白的定义Shell是一个命令行解释器它是用户与Linux内核进行交互的界面。你输入一串字符命令Shell负责理解这串字符调用对应的系统功能通过内核然后把结果返回给你。但这样理解太单薄了。在嵌入式领域Shell的深层价值在于统一的抽象层无论底层是ARM、MIPS还是RISC-V架构无论硬件是树莓派、i.MX6ULL还是STM32MP1只要运行Linux你面对的Shell比如Bash和基本命令集都是相同或高度相似的。这极大地降低了跨平台开发和维护的成本。强大的自动化能力通过Shell脚本shell脚本编程100例是很好的学习资源你可以将一系列复杂的调试、部署、测试流程固化下来。比如一个脚本可以自动登录设备、拉取日志、过滤错误关键字、打包并传回主机。这在批量处理、持续集成中不可或缺。系统状态的探针很多嵌入式问题应用程序本身是看不出所以然的。你需要用Shell命令去查看系统级的状态内存还剩多少CPU占用谁最高某个驱动模块加载了吗网络端口谁在监听这些信息是定位复杂问题的起点。2.2 Bash嵌入式世界的主流选择虽然Shell有很多种sh, csh, ksh, zsh但在嵌入式Linux领域BashBourne-Again SHell是绝对的主流。你看到的绝大多数教程、脚本范例、以及开发板出厂系统默认使用的都是Bash。所以我们的学习重点就是Bash。为什么是Bash因为它功能强大且兼容性好。它兼容古老的Bourne Shellsh同时又提供了诸如命令历史、命令行编辑、别名、作业控制等极其方便的特性。当你通过串口工具如Minicom, Picocom或者网络SSH登录到你的开发板那个等待你输入的光标通常就是Bash的提示符可能长这样rootimx6ull:~#。一个关键认知在嵌入式环境中你经常不是在设备的本地键盘上操作而是通过“远程”方式连接。主要有两种串口UART连接最基础、最可靠的调试手段。即便网络还没起来也可以通过串口登录Shell。命令picocom -b 115200 /dev/ttyUSB0就是在主机上打开一个串口终端。网络SSH连接系统启动并配置好网络后更便捷的方式。命令ssh root192.168.1.100即可远程登录。无论通过哪种方式你最终进入的都是同一个Bash Shell环境。因此掌握在纯键盘环境下高效工作的技巧是嵌入式工程师的必修课。3. 生存必备嵌入式开发高频命令精讲下面我们抛开教科书式的命令列表聚焦于嵌入式开发与调试中最常遇到、最能解决实际问题的命令。我会结合具体场景告诉你“为什么用这个”以及“怎么用得更好”。3.1 文件与目录操作你的“资源管理器”嵌入式系统的根文件系统Rootfs通常比PC的Linux精简得多但目录结构遵循同样的标准FHS。熟练操作文件是基础。pwd(Print Working Directory)“我在哪”在复杂的目录跳转后特别是通过相对路径操作时先用pwd确认当前位置能避免很多“文件找不到”的错误。ls(List)“这里有什么”它的参数决定了你能看到多少信息。ls -l长格式显示能看到文件权限、所有者、大小、修改时间。权限问题是嵌入式文件操作的常见坑这个视图至关重要。ls -a显示所有文件包括以.开头的隐藏文件如.bashrc配置文件。ls -lh-h参数将文件大小以K、M、G等易读格式显示结合-l非常实用。嵌入式场景经常需要检查/lib下的库文件、/etc下的配置文件、/dev下的设备节点是否存在。例如检查摄像头驱动设备节点ls -l /dev/video*。cd(Change Directory)“我要去…”支持绝对路径cd /usr/local/bin和相对路径cd ../返回上级cd ./subdir进入当前目录的子目录。cd -可以在上一个目录和当前目录间快速切换在对比两个目录内容时很好用。cp/mv/rm(Copy/Move/Remove)复制、移动重命名、删除。核心警告嵌入式系统很多目录是只读的如只读根文件系统cp或mv可能会失败提示“Read-only file system”。需要先重新挂载为可写mount -o remount,rw /操作完再改回去mount -o remount,ro /。rm命令要格外小心特别是rm -rf /这样的命令强制递归删除根目录在嵌入式设备上执行等同于“变砖”。永远不要在根目录下使用通配符执行rm比如rm -rf *。先pwd确认位置。cp -a参数在备份或复制整个目录结构时非常有用它能保留文件的所有属性权限、时间等。mkdir/rmdir(Make/Remove Directory)创建/删除目录。rmdir只能删除空目录删除非空目录用rm -r。find“文件侦探”。当你不记得文件放在哪或者需要批量处理某些文件时find是神器。场景在整个根文件系统里寻找所有名为libc.so的库文件find / -name libc.so* 2/dev/null。2/dev/null是为了过滤掉大量“Permission denied”的错误提示让结果更清晰。场景查找最近5天内被修改过的.log日志文件find /var/log -name *.log -mtime -5。结合-exec参数可以对找到的文件执行操作例如删除所有临时文件find /tmp -name *.tmp -exec rm {} \;。3.2 文本查看与编辑如何“阅读”和“修改”配置文件、日志、代码在嵌入式里基本都是文本文件。cat(Concatenate)快速查看整个文件内容。适合看小文件。cat /proc/version可以查看内核版本和编译信息。more/less分页查看大文件。less更强大支持上下翻页、搜索按/然后输入关键词。查看长日志的首选less /var/log/messages。head/tail查看文件开头或结尾。head -n 20 file.log看前20行。tail -n 50 file.log看末尾50行最常用于实时查看最新日志。tail -f file.log“跟随”模式实时显示文件新增的内容。这是调试程序输出的黄金命令。比如你的应用程序往/var/log/myapp.log写日志在另一个终端执行tail -f /var/log/myapp.log就能像看直播一样看到程序的打印信息。grep(Global Regular Expression Print)“文本搜索之王”。在文件或输出流中搜索包含特定模式的行。基本用法grep error dmesg.log在日志中找所有含“error”的行。强大参数-i忽略大小写。-r递归搜索目录下的所有文件。grep -r TIMEOUT /etc/搜索配置文件中所有超时设置。-n显示匹配行的行号。-v反向搜索显示不匹配的行。排除无关信息时有用。组合技dmesg | grep -i usb。dmesg命令输出内核日志通过管道|传给grep过滤出所有USB相关的信息。这是嵌入式驱动调试的日常。vi/vim终端下的文本编辑器。虽然学习曲线陡峭但它是嵌入式设备的标配几乎肯定存在。掌握最基本的操作是必须的i进入插入模式ESC退出插入模式:wq保存并退出:q!不保存强制退出。网上有很多“vim速成”教程花半小时就能应付基本编辑。3.3 系统状态监控给设备“把把脉”嵌入式设备资源紧张监控其状态是保证稳定性的关键。ps(Process Status)查看进程信息。ps显示当前终端下的进程。ps aux显示系统所有进程的详细信息。这是最常用的格式。可以看到进程的PID进程ID、CPU/内存占用率、启动命令等。当你的应用程序卡死了首先用ps aux | grep your_app找到它的PID。top/htop动态的进程监控仪表盘。top是交互式命令启动后实时刷新显示CPU、内存使用情况以及进程列表。按q退出。htop是top的增强版界面更友好但嵌入式系统不一定预装。嵌入式调试重点看%CPUCPU占用率、%MEM内存占用率、RES实际物理内存。如果某个进程的%CPU长期接近100%可能就是死循环如果RES不断增长可能就有内存泄漏。free查看内存使用情况。free -h以人类可读方式显示。重点关注“available”字段它表示系统立即可用的内存量。嵌入式设备内存小这个值如果长期很低系统就会开始使用交换分区如果有的话甚至可能被OOM Killer杀掉进程。df(Disk Free)查看磁盘空间使用情况。df -h。嵌入式设备的Flash存储空间有限需要经常检查根文件系统是否快满了/挂载点使用率。日志文件、临时文件是常见的“磁盘杀手”。uname查看系统信息。uname -a显示所有信息包括内核版本、架构如armv7l在确认交叉编译环境是否匹配时很有用。dmesg(Driver Message)内核环缓冲区。它记录了内核启动和运行过程中的所有信息是驱动调试和系统启动问题排查的第一现场。查看所有信息dmesg。查看尾部最新信息dmesg | tail -50。持续监控dmesg -w类似tail -f。驱动加载失败、设备树Device Tree解析错误、硬件初始化问题都会在这里留下痕迹。搜索“linux tcp协议栈数据流走读”这类底层问题也离不开分析dmesg输出。3.4 网络诊断让设备“开口说话”网络是嵌入式设备的重要功能相关命令必须掌握。ifconfig/ip addr查看和配置网络接口。老式系统用ifconfig新系统推荐功能更强大的ip命令。ip addr show可以查看所有网络接口的IP地址、MAC地址、状态UP/DOWN。ping测试网络连通性。ping -c 4 192.168.1.1向网关发送4个探测包。这是检查设备能否上网、能否与主机通信的最简单方法。netstat显示网络连接、路由表、接口统计等。netstat -tulpn常用组合。显示所有监听-l的TCP-t和UDP-u端口并显示对应的进程名和PID-p且不解析主机名-n。当你写的服务器程序启动后用这个命令可以立刻看到它是否在预期的端口上成功监听。ssh/scp远程登录和安全拷贝。ssh userhost登录。scp local_file userhost:/remote/path将本地文件传到设备scp userhost:/remote/file local_path从设备下载文件。这是在主机和嵌入式设备间传输文件、程序、日志的最常用方式。4. 效率倍增器Shell的高级技巧与脚本入门只会单个命令就像只会用单词而Shell脚本和高级特性让你能写出“句子”和“文章”实现自动化。4.1 管道|与重定向,,这是Shell的精华所在体现了“组合小工具完成复杂任务”的Unix哲学。管道|将一个命令的输出作为另一个命令的输入。例子ps aux | grep python。ps aux列出所有进程输出通过管道传给grepgrep从中过滤出包含“python”的行。完美组合。例子dmesg | grep -i error | wc -l。统计内核日志中“error”关键词出现的行数。wc -l是统计行数的命令。重定向和将命令的输出导入到文件。command file将command的输出覆盖写入file。如果file不存在则创建。command file将command的输出追加到file的末尾。嵌入式应用将程序的标准输出和错误输出重定向到日志文件便于离线分析。./my_app /var/log/app.log 21。21表示将标准错误文件描述符2也重定向到标准输出文件描述符1所在的地方。重定向将文件内容作为命令的输入。较少用但某些命令支持如wc -l file.txt。4.2 环境变量与export环境变量是Shell中用于存储系统和工作环境信息的变量。查看echo $PATH。PATH是最重要的环境变量它定义了Shell在执行命令时搜索程序的目录列表。当你输入lsShell会依次在PATH列出的目录中寻找名为ls的可执行文件。设置临时MY_VARhello。设置为环境变量export MY_VARhello。这样这个变量才会被传递给从当前Shell启动的子进程比如你运行的其他程序。嵌入式场景交叉编译时经常需要设置ARCH架构、CROSS_COMPILE交叉编译工具链前缀等环境变量。例如export CROSS_COMPILEarm-linux-gnueabihf-。然后执行makeMakefile就会使用这个前缀来调用编译器arm-linux-gnueabihf-gcc。4.3 Shell脚本入门从一行到自动化当你的命令序列需要反复执行时就该写脚本了。脚本本质就是一个包含一系列Shell命令的文本文件。创建脚本文件vim deploy.sh第一行指定解释器#!/bin/bash这被称为Shebang编写命令#!/bin/bash # 这是一个简单的部署脚本 echo “开始部署应用程序...” # 停止旧进程 killall -9 my_app 2/dev/null # 拷贝新程序 scp ./my_app root192.168.1.100:/usr/bin/ # 修改权限 ssh root192.168.1.100 “chmod x /usr/bin/my_app” # 启动新程序 ssh root192.168.1.100 “/usr/bin/my_app ” echo “部署完成”赋予执行权限chmod x deploy.sh运行./deploy.sh脚本中的关键元素变量APP_NAME“my_app”使用时用$APP_NAME。条件判断if [ -f “$FILE” ]; then ... fi。-f判断是否为文件。循环for file in *.log; do echo “Processing $file”; done。传递参数脚本内通过$1,$2...获取执行脚本时传入的参数。./deploy.sh debug则$1就是“debug”。从简单的备份脚本、日志清理脚本到复杂的系统初始化、自动化测试框架Shell脚本是提升嵌入式工作效率的利器。网上搜索“shell脚本编程100例”或“bash shell学习”能找到大量实用范例。5. 嵌入式专属场景与避坑指南掌握了通用命令我们来看看嵌入式环境下特有的一些场景和容易踩的坑。5.1 权限管理root不是万能的但没有root是万万不能的嵌入式Linux通常直接以root用户运行这带来了便利也带来了风险。sudo的缺失很多精简的嵌入式系统不安装sudo你就是root。这意味着你的任何命令都具有最高权限。敲击回车前务必三思特别是rm、dd、mkfs这类危险命令。文件权限当你从主机scp一个可执行程序到设备后经常发现无法执行。这是因为拷贝过程可能丢失了“可执行”权限。记住这个命令chmod x your_program。同样如果你写的程序需要创建或写入某个文件如日志却报“Permission denied”检查目标目录或文件的权限ls -l可能需要用chmod或chown修改。只读文件系统Read-only Rootfs为了系统安全性和稳定性防止突然断电导致文件系统损坏许多产品化的嵌入式设备会将根文件系统挂载为只读。这时任何写操作包括创建文件、修改配置都会失败。临时写入如果需要调试或临时修改可以重新挂载为可写mount -o remount,rw /。操作完成后建议改回只读mount -o remount,ro /。永久修改真正的修改应该在编译构建根文件系统镜像时完成而不是在运行时。5.2 存储空间管理寸土寸金的Flash嵌入式设备的存储eMMC, NAND Flash容量有限且频繁写入会影响寿命。日志轮转Logrotate应用程序如果持续写日志很快就会塞满存储。成熟的方案是使用logrotate工具它可以按时间或大小切割、压缩、删除旧日志。你需要为你的应用配置/etc/logrotate.d/yourapp文件。/tmp目录这是一个基于内存的临时文件系统tmpfs重启后数据丢失。适合存放临时的大文件或频繁读写的数据既能节省Flash空间速度也快。但要注意它占用的是RAM。使用df和du定位空间占用df -h看哪个挂载点快满了。du -sh /*查看根目录下各一级目录的大小找到“罪魁祸首”。du -sh /var/log/*可以进一步查看/var/log下各个日志文件的大小。5.3 进程与调试让程序“听话”信号Signal管理kill -9 PID强制杀死一个进程SIGKILL信号进程无法捕获或忽略可能导致资源未释放。kill -15 PID优雅地终止进程SIGTERM信号进程可以捕获这个信号进行清理工作后退出。应该优先使用-15。killall -15 process_name根据进程名终止所有同名进程。后台运行与在命令末尾加上可以让程序在后台运行不占用当前终端。例如./my_server 。之后可以用fg命令将其调回前台。nohup让进程在终端关闭后依然继续运行。nohup ./my_app app.log 21 是部署后台服务的标准写法。strace系统调用跟踪器这是高级调试神器。当你的程序行为诡异卡住、崩溃、返回错误时strace可以跟踪它发出的所有系统调用如打开文件、读写网络、申请内存。strace -f -p PID跟踪一个已运行进程及其子进程。通过观察系统调用的成功与失败往往能直接定位到问题根源如某个配置文件路径不对导致open()失败。5.4 与主机交互adb与fastboot的特殊角色在Android嵌入式开发或一些特定平台中adbAndroid Debug Bridge和fastboot是绕不开的工具。它们本质上是主机上的命令通过USB与设备通信在设备端有对应的守护进程响应。adb shell这相当于在主机上打开了一个通往设备Shell的通道。之后你输入的命令如ls,cat都是在设备端执行的。搜索“adb shell pm uninstall”就是在设备上卸载应用。adb push/adb pull替代scp在Android环境下传输文件。fastboot用于在设备的bootloader模式下刷写分区镜像boot, system, recovery等是系统级烧录和升级的关键工具。注意这些工具需要设备端有相应的服务adbd, fastbootd在运行且主机与设备USB连接正确。对于非Android的纯Linux嵌入式设备通常不使用adb而是直接用ssh或scp。学习Shell命令切忌死记硬背。最好的方法是在实践中学习给自己设定一些小任务比如“把开发板的日志下载到主机并找出所有错误行”、“写一个脚本每天凌晨自动备份关键配置”、“不重启服务的情况下热更新一个配置文件”。在解决这些实际问题的过程中命令和技巧自然就内化了。这个终端窗口就是你探索和控制嵌入式世界的强大武器用得越熟你的开发之路就越顺畅。