第3章:Linux基础命令与Shell编程
各位同学,大家好。这一章我们聊聊嵌入式Linux开发中最基础、也最离不开的东西——命令和脚本。说实话,很多刚入行的朋友觉得命令就是敲敲键盘,没什么技术含量。但我在植保无人机项目里踩过的坑告诉我:命令用得熟不熟,直接决定了你的调试效率。
3.1 文件操作命令:你每天都在用的“基本功”
文件操作,说白了就是跟文件系统打交道。嵌入式Linux下,我们经常要查看日志、修改配置、拷贝固件。这些操作看似简单,但用错了命令,后果可能很严重。
核心命令清单
ls- 列出目录内容。我习惯用ls -lh,能看到文件大小和权限。cd- 切换目录。没什么好说的,但注意绝对路径和相对路径的区别。cp- 复制文件或目录。记得加-r才能复制目录。mv- 移动或重命名。这个命令很危险,我曾经不小心把系统文件移走了,系统直接挂掉。rm- 删除文件。嗯,这里要注意:rm -rf是核武器,慎用。cat/more/less- 查看文件内容。我推荐less,可以上下翻页。touch- 创建空文件或更新文件时间戳。mkdir- 创建目录。加-p可以递归创建。
举个例子。我在调试植保无人机的飞控日志时,经常需要批量拷贝当天的日志文件到U盘。命令很简单:
cp /var/log/flight/*.log /mnt/usb/logs/
但有一次,我忘了U盘挂载点,直接把日志拷贝到了 /mnt 目录下,结果系统分区被写满,无人机在空中直接宕机。你想想看,这多危险。所以,操作前一定要确认目标路径。
我的小技巧:用 pwd 确认当前路径,用 df -h 查看磁盘空间。这两个命令能帮你避免很多低级错误。
3.2 进程管理:让无人机“活”起来
嵌入式系统里,进程就是一切。飞控程序、数据记录服务、通信模块,都是一个个进程。你得知道怎么查看它们、杀死它们、调整它们的优先级。
我个人最常用的进程管理命令是 ps 和 top。
| 命令 | 用途 | 常用参数 |
|---|---|---|
ps |
查看当前进程快照 | ps aux 显示所有进程详细信息 |
top |
实时显示进程资源占用 | 按 P 按CPU排序,按 M 按内存排序 |
kill |
终止进程 | kill -9 PID 强制杀死 |
nice |
设置进程优先级 | 范围 -20 到 19,数值越小优先级越高 |
nohup |
让进程在后台持续运行 | 配合 & 使用 |
我记得有一次,植保无人机在田间作业时,数据记录进程突然卡死了。我远程SSH上去,用 top 一看,发现CPU占用率100%,是一个日志压缩进程在作怪。我直接用 kill -9 干掉它,系统立刻恢复正常。你想想,如果不会这些命令,只能重启整机,那损失就大了。
避坑指南:我曾经在调试时,用 kill -9 杀死了系统关键进程(比如 init),结果系统直接崩溃。所以,杀进程前一定要确认PID,别手滑。
3.3 简单的Shell脚本编写:把重复工作自动化
Shell脚本,说白了就是把一堆命令写进一个文件里,然后一次性执行。在嵌入式开发中,我经常用它来做自动化测试、日志收集、固件升级。
一个最简单的脚本长这样:
#!/bin/bash
# 这是一个简单的日志收集脚本
echo "开始收集日志..."
cp /var/log/flight/*.log /home/pi/logs/
echo "日志收集完成!"
保存为 collect_logs.sh,然后加执行权限:
chmod +x collect_logs.sh
./collect_logs.sh
你看,就这么简单。但实际项目中,脚本会复杂得多。比如,我们需要判断U盘是否挂载,如果没挂载就自动挂载:
#!/bin/bash
MOUNT_POINT="/mnt/usb"
if [ ! -d "$MOUNT_POINT" ]; then
echo "U盘未挂载,尝试挂载..."
mount /dev/sda1 $MOUNT_POINT
if [ $? -eq 0 ]; then
echo "挂载成功"
else
echo "挂载失败,退出"
exit 1
fi
fi
cp /var/log/flight/*.log $MOUNT_POINT/logs/
echo "日志已拷贝到U盘"
这里用到了 if 判断、$? 获取上一条命令的返回值。这些都是Shell编程的基础。
常用Shell语法速查
- 变量:
name="value",使用时加$,如$name - 条件判断:
if [ 条件 ]; then ... fi - 循环:
for i in 1 2 3; do ... done - 函数:
function_name() { ... } - 注释:
# 这是注释
我个人建议,刚开始写脚本时,多用 echo 打印调试信息。这样你能清楚地看到脚本执行到了哪一步,出了什么问题。我曾经写过一个自动升级固件的脚本,因为路径写错了,导致升级失败。幸好有 echo 打印,我一眼就看出问题出在路径拼接上。
我的习惯:每个脚本开头都加一句 set -e。这样一旦某条命令执行失败,脚本就会立即退出,避免错误累积。另外,set -x 可以打印每条命令的执行过程,调试时特别好用。
3.4 实战:一个简单的数据记录脚本
最后,我们结合植保无人机的场景,写一个完整的数据记录脚本。这个脚本会每隔5秒采集一次飞控数据,并保存到文件中。
#!/bin/bash
# 数据记录脚本 - 用于植保无人机
# 作者:你们的嵌入式Linux工程师
LOG_DIR="/var/log/flight"
DATA_FILE="$LOG_DIR/$(date +%Y%m%d_%H%M%S).csv"
# 创建日志目录
mkdir -p $LOG_DIR
# 写入CSV表头
echo "时间,高度,速度,电池电压,GPS信号强度" > $DATA_FILE
# 循环采集数据
while true; do
TIMESTAMP=$(date +"%Y-%m-%d %H:%M:%S")
HEIGHT=$(cat /sys/class/sensor/height) # 假设有传感器接口
SPEED=$(cat /sys/class/sensor/speed)
VOLTAGE=$(cat /sys/class/power_supply/battery/voltage)
GPS_STR=$(cat /sys/class/gps/signal_strength)
echo "$TIMESTAMP,$HEIGHT,$SPEED,$VOLTAGE,$GPS_STR" >> $DATA_FILE
sleep 5
done
这个脚本虽然简单,但已经具备了实际项目的雏形。你可以把它放到后台运行:
nohup ./record_data.sh &
这样,即使你退出了SSH,脚本也会继续运行。嗯,这就是嵌入式开发的日常——用最简单的工具,解决最实际的问题。
注意:实际项目中,传感器接口可能不是 /sys/class 下的文件,而是通过串口或I2C读取。这里只是演示思路,具体实现要根据硬件调整。
好了,这一章的内容就到这里。命令和脚本是嵌入式Linux的基石,你用得越熟,开发效率就越高。下一章,我们会聊聊文件系统和存储管理,这也是植保无人机数据记录系统的关键环节。