第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 进程管理:让无人机“活”起来

嵌入式系统里,进程就是一切。飞控程序、数据记录服务、通信模块,都是一个个进程。你得知道怎么查看它们、杀死它们、调整它们的优先级。

我个人最常用的进程管理命令是 pstop

命令 用途 常用参数
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的基石,你用得越熟,开发效率就越高。下一章,我们会聊聊文件系统和存储管理,这也是植保无人机数据记录系统的关键环节。