0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

【RT-Thread学习笔记】结合案例学习调试shell脚本

嵌入式物联网开发 来源:嵌入式物联网开发 作者:嵌入式物联网开发 2022-07-29 03:32 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

1 问题回顾

在之前的文章 【shell编程扫盲系列】结合真实案例分析“bash shell -e”到底是啥意思? 中,我提到了我遇到一个bash shell-e引发的问题,不瞒大家说,当时我是用echo大法找到出问题的地方,加以修改才解决的。 那么,我们有没有更加优雅的调试方法,解决这类型的问题呢? 本篇文章将会给出答案。

2 shell脚本如何调试

2.1 特别说明

本文中提及的shell脚本,无特殊说明的情况下,指的是bash shell。这里做这个强调的主要原因是,不同的shell的一些基础语法可能有微小的差异,导致在bash shell中可以跑的脚本,但在别的shell上就跑不了。 这种案例可以参见:【Linux Shell】你知道bash shell和dash shell的区别吗?

2.2 shell脚本如何被启动的?

初次看shell脚本的朋友,一定有所疑问为何大部分shell脚本都是#!/bin/bash开头啊? 这里帮你解除疑问: 因为shell脚本说白了就是一系列命令行组成的一个文本文件,由于各式各样的脚本非常多,那么该用哪种脚本的语法去解析这个脚本文件呢? 这里就有2种方式:

  • 通过脚本文件的首行,使用#!/bin/bash指定,像这样就表示它是一个bash shell语法的脚本,应该用/bin/bash去解析;
  • 通过启动的时候,直接用/bin/bash xxx.sh来启动,这样就是手动指定脚本的解析器

注意:使用方式1的时候,运行脚本只需要./xxx.sh就可以了,但是方式2却不行。

2.3 shell脚本的三个调试选项

从之前的文章中,我们了解了-e选项,其实它还有其他几个跟调试相关的选项,如下所示:

  • -v (verbose 的简称) - 告诉 Shell 读取脚本时显示所有行,激活详细模式。
  • -n (noexec 或 no ecxecution 简称) - 指示 Shell 读取所有命令然而不执行它们,这个选项激活语法检查模式。
  • -x (xtrace 或 execution trace 简称) - 告诉 Shell 在终端显示所有执行的命令和它们的参数。 这个选项是启用 Shell 跟踪模式。

2.4 shell脚本的三种调试方式

2.4.1 在shell脚本的首行加选项

这个就跟-e的方式是一样的,注意加选项的时候,是连着-e起来,比如-evx,而不能这样-e-v-x。 这里的选项是可以加多个调试选项。 选项不对报错:

  1. bash_shell_e$ ./test_shell_e.sh
  2. /bin/bash: - : invalid option

正常示例如下:

  1. #!/bin/shell -evx 的执行结果
  2. /bash_shell_e$ ./test_shell_e.sh
  3. # ~/.bashrc: executed by bash(1) for non-login shells.
  4. # see /usr/share/doc/bash/examples/startup-files (in the package bash-doc)
  5. # for examples
  6. # If not running interactively, don't do anything
  7. case $- in
  8. *i*) ;;
  9. *) return;;
  10. esac
  11. + case $- in
  12. + return
  13. #! /bin/bash -evx
  14. function get_os()
  15. {
  16. echo "begin to get OS ..."
  17. os=`uname -a | grep Darwin`
  18. if [ "$os" != "" ]]; then
  19. host_os_name=OSX
  20. else
  21. os=`uname -a | grep x86_64`
  22. if [ "$os" != "" ]; then
  23. host_os_name=Linux64
  24. else
  25. host_os_name=Linux32
  26. fi
  27. fi
  28. echo "get OS name: $host_os_name"
  29. }
  30. function do_other_things()
  31. {
  32. echo "do other things ..."
  33. }
  34. get_os
  35. + get_os
  36. + echo 'begin to get OS ...'
  37. begin to get OS ...
  38. ++ uname -a
  39. ++ grep Darwin
  40. + os=

从这里结果,我们就可以知道,在执行完os=xxx赋值这条语句就退出了,这跟我们使用echo大法得出的结论是一致的。

2.4.2 手动显示shell脚本时加选项

即类似这样: /bin/bash -evx 启动脚本

  1. bash_shell_e$ /bin/bash -vxe test_shell_e.sh
  2. # ~/.bashrc: executed by bash(1) for non-login shells.
  3. # see /usr/share/doc/bash/examples/startup-files (in the package bash-doc)
  4. # for examples
  5. # If not running interactively, don't do anything
  6. case $- in
  7. *i*) ;;
  8. *) return;;
  9. esac
  10. + case $- in
  11. + return
  12. #! /bin/bash -e
  13. function get_os()
  14. {
  15. echo "begin to get OS ..."
  16. os=`uname -a | grep Darwin`
  17. if [ "$os" != "" ]; then
  18. host_os_name=OSX
  19. else
  20. os=`uname -a | grep x86_64`
  21. if [ "$os" != "" ]; then
  22. host_os_name=Linux64
  23. else
  24. host_os_name=Linux32
  25. fi
  26. fi
  27. echo "get OS name: $host_os_name"
  28. }
  29. function do_other_things()
  30. {
  31. echo "do other things ..."
  32. }
  33. get_os
  34. + get_os
  35. + echo 'begin to get OS ...'
  36. begin to get OS ...
  37. ++ uname -a
  38. ++ grep Darwin
  39. + os=

注意:当使用命令行传递输入选项后,脚本文件首行的选项就不生效了,这也是我实践过程中才发现的。 如下所示: 我的脚本首行是指定了-e的,但是它依然跑成功了,因为我使用-x启动,没有带-e

  1. bash_shell_e$ /bin/bash -x test_shell_e.sh
  2. + case $- in
  3. + return
  4. + get_os
  5. + echo 'begin to get OS ...'
  6. begin to get OS ...
  7. ++ uname -a
  8. ++ grep Darwin
  9. + os=
  10. + '[' '' '!=' '' ']'
  11. ++ uname -a
  12. ++ grep x86_64
  13. + os='Linux ubuntu 5.4.0-65-generic #73-Ubuntu SMP Mon Jan 18 17:25:17 UTC 2021 x86_64 x86_64 x86_64 GNU/Linux'
  14. + '[' 'Linux ubuntu 5.4.0-65-generic #73-Ubuntu SMP Mon Jan 18 17:25:17 UTC 2021 x86_64 x86_64 x86_64 GNU/Linux' '!=' '' ']'
  15. + host_os_name=Linux64
  16. + echo 'get OS name: Linux64'
  17. get OS name: Linux64
  18. + do_other_things
  19. + echo 'do other things ...'
  20. do other things ...
  21. + exit 0

2.4.3 通过set命令设置调试选项

使用方法如下,它可以在脚本中调试任意一个函数,用法非常灵活

  1. #! /bin/bash -e
  2. function get_os()
  3. {
  4. echo "begin to get OS ..."
  5. os=`uname -a | grep Darwin`
  6. if [ "$os" != "" ]; then
  7. host_os_name=OSX
  8. else
  9. os=`uname -a | grep x86_64`
  10. if [ "$os" != "" ]; then
  11. host_os_name=Linux64
  12. else
  13. host_os_name=Linux32
  14. fi
  15. fi
  16. echo "get OS name: $host_os_name"
  17. }
  18. function do_other_things()
  19. {
  20. echo "do other things ..."
  21. }
  22. # open debug option
  23. set -xv
  24. get_os
  25. # close debug option
  26. set +xv
  27. # re-open debug option
  28. set -xv
  29. do_other_things
  30. # close debug option
  31. set +xv
  32. exit 0

增加这些调试之后,运行结果如下:

  1. bash_shell_e$ ./test_shell_e_debug.sh
  2. get_os
  3. + get_os
  4. + echo 'begin to get OS ...'
  5. begin to get OS ...
  6. ++ uname -a
  7. ++ grep Darwin
  8. + os=

从这个输出,我们也可以看到在执行完ox=xxx赋值之后,脚本就停止运行,退出了,这跟我们之前的分析是一致的。 这个方法对于调试shell的函数非常有用,值得注意的是,set-xxx需要加在执行部分,而不是声明部分。

3 经验总结

  • 调试shell脚本有3个选项,-x -n -v 用法各异,灵活使用;
  • 调试shell脚本的方式也有3种,选用自己熟悉且方便的一种即可,高效排查问题。

4 更多分享

架构师李肯

一个专注于嵌入式IoT领域的架构师。有着近10年的嵌入式一线开发经验,深耕IoT领域多年,熟知IoT领域的业务发展,深度掌握IoT领域的相关技术栈,包括但不限于主流RTOS内核的实现及其移植、硬件驱动移植开发、网络通讯协议开发、编译构建原理及其实现、底层汇编及编译原理、编译优化及代码重构、主流IoT云平台的对接、嵌入式IoT系统的架构设计等等。拥有多项IoT领域的发明专利,热衷于技术分享,有多年撰写技术博客的经验积累,连续多月获得RT-Thread官方技术社区原创技术博文优秀奖,荣获CSDN博客专家、CSDN物联网领域优质创作者、2021年度CSDN&RT-Thread技术社区之星、RT-Thread官方嵌入式开源社区认证专家、RT-Thread 2021年度论坛之星TOP4、华为云云享专家(嵌入式物联网架构设计师)等荣誉。坚信【知识改变命运,技术改变世界】!

本项目的所有测试代码和编译脚本,均可以在我的github仓库01workstation中找到。

欢迎关注我的github仓库01workstation,日常分享一些开发笔记和项目实战,欢迎指正问题。

同时也非常欢迎关注我的专栏:有问题的话,可以跟我讨论,知无不答,谢谢大家。

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • Shell
    +关注

    关注

    1

    文章

    373

    浏览量

    25174
  • 脚本
    +关注

    关注

    1

    文章

    407

    浏览量

    29051
  • RT-Thread
    +关注

    关注

    32

    文章

    1540

    浏览量

    44278
收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    首搭RT-Thread程翧车控平台| RT-Thread程翧 S32K344 快速原型开发平台正式上市!| 产品动态

    在智能汽车迈向高集成与高安全的时代,VCU/ECU开发正面临效率与可靠性的双重考验。依赖单一硬件或拼凑软件方案的传统模式,已成为制约创新的瓶颈。为此,RT-Thread带来里程碑式的解决方案
    的头像 发表于 10-31 11:53 483次阅读
    首搭<b class='flag-5'>RT-Thread</b>程翧车控平台| <b class='flag-5'>RT-Thread</b>程翧 S32K344 快速原型开发平台正式上市!| 产品动态

    rt-thread studio 导入BSP 失败怎么解决?

    rt-thread studio 手动导入bsp 失败。 版本: 2.2.8 构建ID: 202405200930 导入的bsp 是直接从rt-thread 代码仓库下载的 .log
    发表于 10-11 11:07

    学习强国深度报道 RT-Thread“1+X+N”战略,国产操作系统赋能高端制造引关注|媒体视角

    近日,国产嵌入式操作系统领军企业RT-Thread睿赛德在工博会发布的“1+X+N”战略体系,获得了国家级权威媒体平台“学习强国”的重点报道。该报道从产业高度深入剖析了RT-Thread睿赛德以自主
    的头像 发表于 09-29 17:37 904次阅读
    <b class='flag-5'>学习</b>强国深度报道 <b class='flag-5'>RT-Thread</b>“1+X+N”战略,国产操作系统赋能高端制造引关注|媒体视角

    2025年RT-Thread开发者巡回培训报名正式启动!

    亲爱的RT-Thread社区成员们:新程再启,共赴热爱!2025年RT-Thread开发者巡回培训正式启动报名!今年,我们选择了西安、武汉、北京、杭州、深圳、上海、成都这7座城市,为大家带来
    的头像 发表于 09-27 10:39 1141次阅读
    2025年<b class='flag-5'>RT-Thread</b>开发者巡回培训报名正式启动!

    rt-thread studio 2.2.9如何使用最新的RT-Thread v5.2.0 released?

    rt-thread studio2.2.9如何使用最新的RT-Thread v5.2.0 released? 原先以为修改index_all.json,发现联网的时候,会自动覆盖 另lastet版本
    发表于 09-16 06:06

    在Ubuntu上开发基于先楫MCU的RT-Thread应用指南

    1、前言RT-ThreadEnv是RT-Thread推出的开发辅助工具,针对基于RT-Thread操作系统的项目工程,提供编译构建环境、图形化系统配置及软件包管理功能。其内置的menuconfig
    的头像 发表于 08-29 12:22 1228次阅读
    在Ubuntu上开发基于先楫MCU的<b class='flag-5'>RT-Thread</b>应用指南

    【好书推荐】RT-Thread第20本相关书籍!《嵌入式实时操作系统RT-Thread原理与应用》| 技术集结

    01内容简介ContentSummary本书为读者提供了一个全面、系统的RT-Thread学习指南,旨在帮助初学者及有经验的开发者掌握RT-Thread实时操作系统和STM32嵌入式微控制器的核心
    的头像 发表于 08-24 10:05 685次阅读
    【好书推荐】<b class='flag-5'>RT-Thread</b>第20本相关书籍!《嵌入式实时操作系统<b class='flag-5'>RT-Thread</b>原理与应用》| 技术集结

    揭秘!基于RT-Thread探究“优先级反转”下的任务调度究竟是什么样的?| 技术集结

    本文将基于RT-Thread结合RT-Trace调试器细化到实际任务调度的粒度,来调试并逐步讲解“优先级反转”的调度和运行逻辑。如果对
    的头像 发表于 08-17 10:07 2802次阅读
    揭秘!基于<b class='flag-5'>RT-Thread</b>探究“优先级反转”下的任务调度究竟是什么样的?| 技术集结

    RT-Thread 遇上 Rust:安全内核 RusT-Thread 的诞生

    大家好,我们是中国科学技术大学操作系统原理与设计(H)课oooooS小组。这个项目是我们的课程大作业:参考RT-Thread架构,使用Rust搭建一个原生的嵌入式操作系统内核。初识Rust是因为xk
    的头像 发表于 08-02 11:03 3207次阅读
    <b class='flag-5'>RT-Thread</b> 遇上 Rust:安全内核 RusT-<b class='flag-5'>Thread</b> 的诞生

    RT-Thread荣获2025优秀开源项目 | 新闻速递

    6月底,RT-Thread睿赛德受邀参与由上海开源信息技术协会主办的2025上海开源创新精英荟。上海市商委副主任张杰出席会议并致辞。RT-Thread嵌入式操作系统项目凭借其卓越的技术创新与开源生态
    的头像 发表于 07-04 09:04 2431次阅读
    <b class='flag-5'>RT-Thread</b>荣获2025优秀开源项目 | 新闻速递

    深度剖析 RT-Thread 线程调度流程

    RT-Thread调度第一个线程的主要流程分如下:rtthread_startup:RTT的启动函数,主要负责板级驱动,调度器,系统线程初始化,启动调度的工作
    的头像 发表于 06-25 18:24 1437次阅读
    深度剖析 <b class='flag-5'>RT-Thread</b> 线程调度流程

    揭秘RT-Thread上的AUTOSAR CP系统

    本文探讨了RT-Thread与AUTOSARCP的融合,解决车载ECU开发中实时性、安全性与灵活性的平衡问题。通过分层安全内核(rt-safetyos/autoos)和工具链整合,兼容AUTOSAR
    的头像 发表于 06-23 20:22 2944次阅读
    揭秘<b class='flag-5'>RT-Thread</b>上的AUTOSAR CP系统

    2025 RT-Thread全球技术大会议程正式发布!

    RT-ThreadGlobalTechConference(RT-ThreadGTC,RT-Thread全球技术大会)是聚焦基础软件技术创新与实践的嵌入式技术盛会,持续推动技术价值转化
    的头像 发表于 05-27 19:28 1072次阅读
    2025 <b class='flag-5'>RT-Thread</b>全球技术大会议程正式发布!

    RT-Thread审核团招募: 深度参与开源RTOS社区治理与演进

    全球开发者招募:RT-Thread审核团(ReviewTeam)正式开放申请!在开源的世界里,代码审查(CodeReview)是保证软件质量、促进技术交流的关键环节。RT-Thread作为全球领先
    的头像 发表于 05-21 18:02 1065次阅读
    <b class='flag-5'>RT-Thread</b>审核团招募: 深度参与开源RTOS社区治理与演进

    如何将RT-Thread移植到NXP MCUXPressoIDE上

    RT-Thread默认支持的IDE只有IAR 和 Keil, 那如何将RT-Thread移植到NXP MCUXPressoIDE上呢?本文内容比较简单但稍有琐碎,希望对有需要的小伙伴有所帮助。
    的头像 发表于 02-13 10:37 2440次阅读
    如何将<b class='flag-5'>RT-Thread</b>移植到NXP MCUXPressoIDE上