NuttX 命令行原生脚本文件完全指南
NuttX 命令行原生脚本文件完全指南
引言
在嵌入式开发中,脚本文件是自动化任务的重要工具。NuttX 作为一款轻量级、POSIX 兼容的实时操作系统,同样提供了强大的脚本支持能力。本文将深入介绍 NuttX 命令行下原生脚本文件的功能和使用方法,帮助开发者充分利用脚本提升开发效率。
一、NuttX 脚本系统概述
1.1 NSH 脚本解释器
NuttX 的脚本支持是通过 NuttShell (NSH) 实现的。NSH 是一个专为嵌入式系统设计的轻量级命令行解释器,具备以下核心特点:
- 轻量级设计:占用内存少,适合资源受限的嵌入式环境
- POSIX 兼容:命令语法与 Unix/Linux Shell 高度相似
- 脚本支持:支持
.sh脚本文件的解析和执行 - 可配置性:可通过 Kconfig 灵活启用或禁用脚本功能
1.2 脚本系统架构
二、脚本文件基础
2.1 脚本文件格式
NuttX 脚本文件遵循以下基本格式:
#!/bin/sh
# 脚本注释
# 命令序列
echo "Hello, NuttX!"
ls -l /
关键要素说明:
| 要素 | 说明 | 示例 |
|---|---|---|
| Shebang | 指定脚本解释器 | #!/bin/sh |
| 注释 | 以 # 开头的注释行 |
# 这是注释 |
| 命令 | NSH 支持的命令 | echo, ls, cd |
| 变量 | 使用 $ 引用变量 |
$PATH, ${VAR} |
2.2 脚本创建方法
方法一:使用 cat 命令创建
nsh> cat > myscript.sh << EOF
#!/bin/sh
echo "Hello from script"
ls -l /
EOF
方法二:使用编辑器创建
nsh> vi myscript.sh
方法三:从宿主机传输
# 在宿主机上
$ cp myscript.sh /mnt/nuttx/
# 或通过串口传输
$ minicom -b 115200 -D /dev/ttyUSB0
2.3 脚本执行方式
方式一:使用 sh 命令执行
nsh> sh myscript.sh
方式二:直接执行(需可执行权限)
nsh> chmod 755 myscript.sh
nsh> ./myscript.sh
方式三:使用 source 命令(在当前 Shell 环境执行)
nsh> source myscript.sh
三种方式对比:
| 方式 | 特点 | 适用场景 |
|---|---|---|
sh script.sh |
在子 Shell 中执行,不影响当前环境 | 独立任务脚本 |
./script.sh |
需要可执行权限,子 Shell 执行 | 独立任务脚本 |
source script.sh |
在当前 Shell 环境执行,影响当前环境 | 环境配置脚本 |
三、NSH 脚本核心功能
3.1 变量支持
环境变量:
# 查看所有环境变量
nsh> set
# 设置环境变量
nsh> set MY_VAR=hello
# 使用环境变量
nsh> echo $MY_VAR
hello
# 删除环境变量
nsh> unset MY_VAR
脚本变量:
#!/bin/sh
# 定义变量
NAME="NuttX"
VERSION="12.0"
# 使用变量
echo "系统名称: $NAME"
echo "系统版本: $VERSION"
# 变量替换
echo "$NAME 版本 $VERSION"
# 变量计算
COUNT=10
echo "计数: ${COUNT}"
特殊变量:
| 变量 | 含义 | 示例 |
|---|---|---|
$0 |
脚本名称 | myscript.sh |
$1-$9 |
位置参数 | 命令行参数 |
$# |
参数数量 | 参数个数 |
$@ |
所有参数 | 完整参数列表 |
$? |
上一条命令返回值 | 0 表示成功 |
3.2 命令行参数
#!/bin/sh
# 带参数的脚本示例
echo "脚本名称: $0"
echo "参数数量: $#"
echo "所有参数: $@"
# 遍历参数
for i in "$@"
do
echo "参数: $i"
done
# 判断参数数量
if [ $# -lt 2 ]; then
echo "用法: $0 <参数1> <参数2>"
exit 1
fi
echo "第一个参数: $1"
echo "第二个参数: $2"
执行示例:
nsh> sh args.sh hello world
脚本名称: args.sh
参数数量: 2
所有参数: hello world
参数: hello
参数: world
第一个参数: hello
第二个参数: world
3.3 重定向功能
输出重定向:
# 覆盖写入文件
nsh> echo "hello" > output.txt
# 追加写入文件
nsh> echo "world" >> output.txt
# 错误重定向
nsh> nonexistent_cmd 2> error.log
# 同时重定向标准输出和错误
nsh> cmd > output.log 2>&1
输入重定向:
# 从文件读取输入
nsh> cat < input.txt
# 脚本中使用
#!/bin/sh
echo "请输入内容:"
read LINE
echo "您输入了: $LINE"
3.4 管道功能
# 基本管道
nsh> ls / | grep "bin"
# 多级管道
nsh> cat file.txt | grep "error" | wc -l
# 脚本中的管道
#!/bin/sh
echo "系统进程数量:"
ps | grep -v "PID" | wc -l
3.5 命令组合
# 分号分隔(顺序执行)
nsh> cmd1; cmd2; cmd3
# && 组合(前一个成功才执行下一个)
nsh> mkdir -p /tmp/data && echo "创建成功"
# || 组合(前一个失败才执行下一个)
nsh> cd /nonexistent || echo "目录不存在"
# 脚本中的命令组合
#!/bin/sh
echo "开始执行..."
mkdir -p /tmp/data && echo "目录创建成功" || echo "目录创建失败"
echo "执行完毕"
3.6 通配符支持
# * 匹配任意字符
nsh> ls *.txt
# ? 匹配单个字符
nsh> ls file?.txt
# [] 匹配字符集
nsh> ls file[123].txt
# 脚本中的通配符
#!/bin/sh
echo "列出所有文本文件:"
ls *.txt
echo "\n列出所有日志文件:"
ls *.log
四、常用脚本文件示例
4.1 系统初始化脚本
文件名:init.sh
功能:系统启动时自动执行,完成目录创建、环境变量设置、服务启动等初始化工作。
#!/bin/sh
# 系统初始化脚本
# 作者: NuttX Developer
# 日期: 2024-01-01
echo "[INIT] ==================================="
echo "[INIT] NuttX 系统初始化脚本"
echo "[INIT] ==================================="
# 创建必要的目录结构
echo "[INIT] 创建目录结构..."
mkdir -p /tmp/data
mkdir -p /tmp/logs
mkdir -p /tmp/config
mkdir -p /mnt/flash
mkdir -p /mnt/sdcard
# 设置环境变量
echo "[INIT] 设置环境变量..."
set PATH=/bin:/usr/bin:/sbin:/usr/sbin
set HOME=/root
set LOG_DIR=/tmp/logs
set DATA_DIR=/tmp/data
# 挂载文件系统
echo "[INIT] 挂载文件系统..."
mount -t tmpfs none /tmp
if [ $? -eq 0 ]; then
echo "[INIT] tmpfs 挂载成功"
else
echo "[INIT] tmpfs 挂载失败"
fi
mount -t romfs /dev/rom0 /mnt/flash
if [ $? -eq 0 ]; then
echo "[INIT] romfs 挂载成功"
else
echo "[INIT] romfs 挂载失败"
fi
# 设置文件权限
echo "[INIT] 设置文件权限..."
chmod 755 /tmp
chmod 777 /tmp/logs
# 启动系统服务
echo "[INIT] 启动系统服务..."
# 启动 HTTP 服务器
if [ -x /bin/httpd ]; then
httpd &
echo "[INIT] HTTP 服务器已启动"
fi
# 启动 Telnet 服务器
if [ -x /bin/telnetd ]; then
telnetd &
echo "[INIT] Telnet 服务器已启动"
fi
# 启动日志守护进程
if [ -x /bin/logd ]; then
logd &
echo "[INIT] 日志守护进程已启动"
fi
echo "[INIT] ==================================="
echo "[INIT] 系统初始化完成!"
echo "[INIT] ==================================="
4.2 文件备份脚本
文件名:backup.sh
功能:定期备份重要文件,支持自定义源目录和目标目录,自动生成带时间戳的备份文件。
#!/bin/sh
# 文件备份脚本
# 用法: backup.sh <源目录> <目标目录>
# 检查参数数量
if [ $# -lt 2 ]; then
echo "用法: $0 <源目录> <目标目录>"
echo "示例: $0 /tmp/data /mnt/flash/backup"
exit 1
fi
SRC_DIR=$1
DST_DIR=$2
# 检查源目录是否存在
if [ ! -d $SRC_DIR ]; then
echo "错误: 源目录 $SRC_DIR 不存在"
exit 1
fi
# 创建目标目录
mkdir -p $DST_DIR
if [ $? -ne 0 ]; then
echo "错误: 无法创建目标目录 $DST_DIR"
exit 1
fi
# 获取当前日期时间
DATE=$(date +%Y%m%d_%H%M%S)
BACKUP_NAME="backup_$DATE"
echo "=========================================="
echo " 文件备份脚本"
echo "=========================================="
echo "源目录: $SRC_DIR"
echo "目标目录: $DST_DIR"
echo "备份名称: $BACKUP_NAME"
echo "开始时间: $(date)"
echo "------------------------------------------"
# 执行备份
echo "正在执行备份..."
cp -r $SRC_DIR/* $DST_DIR/$BACKUP_NAME/
if [ $? -eq 0 ]; then
echo "------------------------------------------"
echo "备份成功!"
echo "备份位置: $DST_DIR/$BACKUP_NAME"
# 显示备份文件大小
echo "备份大小: $(du -sh $DST_DIR/$BACKUP_NAME | awk '{print $1}')"
else
echo "------------------------------------------"
echo "备份失败!"
exit 1
fi
echo "结束时间: $(date)"
echo "=========================================="
执行示例:
nsh> sh backup.sh /tmp/data /mnt/flash/backup
==========================================
文件备份脚本
==========================================
源目录: /tmp/data
目标目录: /mnt/flash/backup
备份名称: backup_20240101_120000
开始时间: Tue Jan 1 12:00:00 2024
------------------------------------------
正在执行备份...
------------------------------------------
备份成功!
备份位置: /mnt/flash/backup/backup_20240101_120000
备份大小: 128K
结束时间: Tue Jan 1 12:00:05 2024
==========================================
4.3 系统信息收集脚本
文件名:sysinfo.sh
功能:收集并显示系统运行状态信息,包括内存使用、进程状态、文件系统、网络配置等。
#!/bin/sh
# 系统信息收集脚本
echo "=========================================="
echo " NuttX 系统信息"
echo "=========================================="
# 系统基本信息
echo "\n【系统信息】"
echo "------------------------------------------"
echo "操作系统: $(uname -s)"
echo "内核版本: $(uname -r)"
echo "主机名称: $(uname -n)"
echo "运行时间: $(uptime)"
# CPU 信息
echo "\n【CPU 信息】"
echo "------------------------------------------"
if [ -f /proc/cpuinfo ]; then
cat /proc/cpuinfo
else
echo "CPU 信息不可用"
fi
# 内存信息
echo "\n【内存信息】"
echo "------------------------------------------"
free -h
# 进程信息
echo "\n【进程信息】"
echo "------------------------------------------"
echo "进程数量: $(ps | grep -v "PID" | wc -l)"
echo "\n详细列表:"
ps -v
# 文件系统信息
echo "\n【文件系统信息】"
echo "------------------------------------------"
mount
echo "\n磁盘使用情况:"
df -h
# 网络信息
echo "\n【网络信息】"
echo "------------------------------------------"
ifconfig
echo "\n路由表:"
route
echo "\n网络连接:"
netstat -a
# 环境变量
echo "\n【环境变量】"
echo "------------------------------------------"
set
echo "\n=========================================="
echo " 系统信息收集完成"
echo "=========================================="
4.4 日志管理脚本
文件名:logmanage.sh
功能:管理系统日志文件,支持日志查看、清理、备份和压缩功能。
#!/bin/sh
# 日志管理脚本
# 用法: logmanage.sh <命令> [参数]
# 命令: view | clean | backup | compress
LOG_DIR="/tmp/logs"
# 显示帮助信息
show_help() {
echo "日志管理脚本"
echo "用法: $0 <命令> [参数]"
echo ""
echo "命令列表:"
echo " view - 查看日志文件"
echo " clean - 清理日志文件"
echo " backup - 备份日志文件"
echo " compress - 压缩日志文件"
echo " help - 显示帮助信息"
echo ""
echo "示例:"
echo " $0 view system.log"
echo " $0 clean"
echo " $0 backup"
echo " $0 compress"
}
# 查看日志
view_log() {
if [ -z "$1" ]; then
echo "用法: $0 view <日志文件名>"
echo "可用日志文件:"
ls $LOG_DIR/*.log 2>/dev/null || echo " 无日志文件"
return
fi
LOG_FILE="$LOG_DIR/$1"
if [ -f "$LOG_FILE" ]; then
echo "查看日志: $LOG_FILE"
echo "------------------------------------------"
cat "$LOG_FILE"
else
echo "错误: 日志文件 $LOG_FILE 不存在"
fi
}
# 清理日志
clean_log() {
echo "清理日志文件..."
echo "当前日志文件:"
ls -la $LOG_DIR/*.log 2>/dev/null || echo " 无日志文件"
read -p "确定要清空所有日志文件吗? (y/n): " CONFIRM
if [ "$CONFIRM" = "y" ] || [ "$CONFIRM" = "Y" ]; then
rm -f $LOG_DIR/*.log
echo "日志文件已清理"
else
echo "取消清理"
fi
}
# 备份日志
backup_log() {
DATE=$(date +%Y%m%d_%H%M%S)
BACKUP_FILE="$LOG_DIR/log_backup_$DATE.tar"
echo "备份日志文件..."
tar cf "$BACKUP_FILE" $LOG_DIR/*.log 2>/dev/null
if [ $? -eq 0 ]; then
echo "备份成功: $BACKUP_FILE"
echo "备份大小: $(du -h "$BACKUP_FILE" | awk '{print $1}')"
else
echo "备份失败,无日志文件需要备份"
fi
}
# 压缩日志
compress_log() {
echo "压缩日志文件..."
for LOG_FILE in $LOG_DIR/*.log; do
if [ -f "$LOG_FILE" ]; then
gzip "$LOG_FILE"
echo "压缩: ${LOG_FILE}.gz"
fi
done
echo "压缩完成"
}
# 主程序
if [ $# -lt 1 ]; then
show_help
exit 1
fi
case "$1" in
view)
view_log "$2"
;;
clean)
clean_log
;;
backup)
backup_log
;;
compress)
compress_log
;;
help)
show_help
;;
*)
echo "错误: 未知命令 '$1'"
show_help
exit 1
;;
esac
4.5 网络测试脚本
文件名:nettest.sh
功能:测试网络连通性和带宽,支持 ping 测试、端口扫描、网络速度测试等功能。
#!/bin/sh
# 网络测试脚本
echo "=========================================="
echo " NuttX 网络测试工具"
echo "=========================================="
# 显示网络接口信息
echo "\n【网络接口】"
echo "------------------------------------------"
ifconfig
# Ping 测试
echo "\n【Ping 测试】"
echo "------------------------------------------"
TARGETS="127.0.0.1 192.168.1.1 8.8.8.8"
for TARGET in $TARGETS; do
echo "\n测试 $TARGET:"
ping -c 3 $TARGET
if [ $? -eq 0 ]; then
echo " ✓ 连通"
else
echo " ✗ 不通"
fi
done
# 网络连接状态
echo "\n【网络连接状态】"
echo "------------------------------------------"
netstat -a
# 路由表
echo "\n【路由表】"
echo "------------------------------------------"
route
echo "\n=========================================="
echo " 网络测试完成"
echo "=========================================="
4.6 文件系统检查脚本
文件名:fscheck.sh
功能:检查文件系统健康状态,包括磁盘空间、文件数量、目录结构等。
#!/bin/sh
# 文件系统检查脚本
echo "=========================================="
echo " 文件系统检查工具"
echo "=========================================="
# 磁盘使用情况
echo "\n【磁盘使用情况】"
echo "------------------------------------------"
df -h
# 根目录大小统计
echo "\n【根目录大小统计】"
echo "------------------------------------------"
for DIR in /bin /etc /tmp /mnt; do
if [ -d $DIR ]; then
SIZE=$(du -sh $DIR 2>/dev/null | awk '{print $1}')
COUNT=$(find $DIR -type f 2>/dev/null | wc -l)
echo "$DIR: $SIZE, 文件数: $COUNT"
fi
done
# 临时文件检查
echo "\n【临时文件检查】"
echo "------------------------------------------"
echo "/tmp 目录文件数量: $(find /tmp -type f | wc -l)"
echo "/tmp 目录大小: $(du -sh /tmp | awk '{print $1}')"
# 检查磁盘空间告警
echo "\n【磁盘空间告警】"
echo "------------------------------------------"
DISK_USAGE=$(df / | grep -v "Filesystem" | awk '{print $5}' | sed 's/%//')
if [ $DISK_USAGE -gt 80 ]; then
echo "警告: 根目录使用率达到 ${DISK_USAGE}%,请清理空间"
else
echo "正常: 根目录使用率 ${DISK_USAGE}%"
fi
# 文件系统挂载点检查
echo "\n【挂载点检查】"
echo "------------------------------------------"
mount | awk '{print $1 " -> " $3 " (" $5 ")"}'
echo "\n=========================================="
echo " 文件系统检查完成"
echo "=========================================="
五、脚本配置与启用
5.1 通过 menuconfig 配置
make menuconfig
配置路径:
Application Configuration
---> NSH Library
---> [*] Enable built-in applications
---> [*] sh command # 启用脚本支持
---> [*] source command # 启用 source 命令
---> [*] Enable NSH debug output
---> [*] Enable command line history
---> [*] Enable environment variables
---> [*] Enable file descriptor redirection
---> [*] Enable pipes
5.2 关键配置选项
| 配置选项 | 说明 | 默认值 |
|---|---|---|
CONFIG_NSH_BUILTIN_APPS |
启用内置应用 | y |
CONFIG_NSH_DISABLESCRIPT |
禁用脚本支持 | n |
CONFIG_NSH_FILEIOSIZE |
文件 I/O 缓冲区大小 | 512 |
CONFIG_NSH_ENVIRON |
启用环境变量支持 | y |
CONFIG_NSH_REDIRECT |
启用重定向支持 | y |
CONFIG_NSH_PIPE |
启用管道支持 | y |
CONFIG_NSH_MAXARGUMENTS |
最大命令行参数数量 | 16 |
CONFIG_NSH_HISTORY |
命令历史记录大小 | 16 |
5.3 自动启动脚本
方式一:通过 rcS 文件
在文件系统根目录创建 etc/rcS 文件,系统启动时会自动执行:
# 创建 rcS 文件
nsh> mkdir -p /etc
nsh> cat > /etc/rcS << EOF
#!/bin/sh
echo "执行自动启动脚本..."
/mnt/flash/scripts/init.sh
EOF
方式二:通过 Kconfig 配置
make menuconfig
Application Configuration
---> NSH Library
---> [*] Execute rcS on startup
---> Path to rcS script (Default: /etc/rcS)
六、脚本开发最佳实践
6.1 脚本编写规范
1. 始终添加 Shebang
#!/bin/sh
2. 添加脚本头部注释
#!/bin/sh
# 脚本名称: script_name.sh
# 功能描述: 简要描述脚本功能
# 作者: Your Name
# 日期: YYYY-MM-DD
# 用法: script_name.sh [参数]
3. 检查命令返回值
cmd
if [ $? -eq 0 ]; then
echo "成功"
else
echo "失败"
exit 1
fi
4. 使用绝对路径
# 推荐
/mnt/flash/scripts/init.sh
# 不推荐(依赖当前目录)
./init.sh
5. 添加错误处理
#!/bin/sh
set -e # 遇到错误立即退出
# 或手动检查
if [ ! -f "$FILE" ]; then
echo "错误: 文件不存在"
exit 1
fi
6.2 性能优化建议
1. 减少命令调用次数
# 低效
for i in $(ls *.txt); do
echo $i
done
# 高效
for i in *.txt; do
echo $i
done
2. 使用临时文件
# 使用临时文件存储中间结果
TEMP_FILE=$(mktemp)
cmd > $TEMP_FILE
process $TEMP_FILE
rm $TEMP_FILE
3. 避免不必要的输出
# 关闭不必要的输出
cmd > /dev/null 2>&1
七、常见问题与解决方案
7.1 脚本命令未找到
问题:
nsh> sh test.sh
sh: command not found
解决方案:
在 menuconfig 中启用 sh 命令:
make menuconfig
# Application Configuration -> NSH Library -> sh command
7.2 脚本执行权限问题
问题:
nsh> ./test.sh
nsh: ./test.sh: Permission denied
解决方案:
# 添加可执行权限
nsh> chmod 755 test.sh
7.3 脚本语法错误
问题:脚本执行时报语法错误
解决方案:
- 检查脚本中的命令是否在 NSH 中支持
- 避免使用 NSH 不支持的高级 Shell 语法(如
$(())算术扩展) - 确保脚本使用正确的换行符(Unix 格式)
7.4 脚本无法读取环境变量
问题:脚本中无法读取在命令行设置的环境变量
解决方案:
使用 source 命令执行脚本:
nsh> set MY_VAR=hello
nsh> source test.sh # 可以读取 MY_VAR
7.5 文件系统未挂载
问题:脚本执行时提示文件不存在
解决方案:
确保文件系统已正确挂载:
nsh> mount -t tmpfs none /tmp
nsh> mount -t romfs /dev/rom0 /mnt/flash
八、脚本执行流程图
8.1 脚本执行完整流程
8.2 脚本变量处理流程
九、结束语
NuttX 的脚本系统为嵌入式开发提供了强大的自动化能力。通过脚本文件,开发者可以实现:
- 系统初始化:自动完成目录创建、环境配置、服务启动
- 批量操作:一次性执行多个命令,提高效率
- 系统管理:日志管理、文件备份、系统监控
- 网络测试:连通性测试、性能测试
本文介绍了 NuttX 脚本系统的核心功能、常用脚本示例和开发最佳实践。希望这些内容能帮助您更好地利用脚本提升嵌入式开发效率。
下一步建议:
- 在实际项目中尝试使用脚本自动化重复任务
- 根据项目需求编写自定义脚本
- 结合 NuttX 的其他功能(如定时器、信号)实现更复杂的自动化场景
参考资料:
如果您觉得本文对您有帮助,请点赞、收藏并分享给更多朋友!如有任何问题或建议,欢迎在评论区留言讨论!
openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构
更多推荐
所有评论(0)