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
。 这里的选项是可以加多个调试选项。 选项不对报错:
-
bash_shell_e$ ./test_shell_e.sh
-
/bin/bash: - : invalid option
正常示例如下:
-
#!/bin/shell -evx 的执行结果
-
/bash_shell_e$ ./test_shell_e.sh
-
# ~/.bashrc: executed by bash(1) for non-login shells.
-
# see /usr/share/doc/bash/examples/startup-files (in the package bash-doc)
-
# for examples
-
# If not running interactively, don't do anything
-
case $- in
-
*i*) ;;
-
*) return;;
-
esac
-
+ case $- in
-
+ return
-
#! /bin/bash -evx
-
function get_os()
-
{
-
echo "begin to get OS ..."
-
os=`uname -a | grep Darwin`
-
if [ "$os" != "" ]]; then
-
host_os_name=OSX
-
else
-
os=`uname -a | grep x86_64`
-
if [ "$os" != "" ]; then
-
host_os_name=Linux64
-
else
-
host_os_name=Linux32
-
fi
-
fi
-
echo "get OS name: $host_os_name"
-
}
-
function do_other_things()
-
{
-
echo "do other things ..."
-
}
-
get_os
-
+ get_os
-
+ echo 'begin to get OS ...'
-
begin to get OS ...
-
++ uname -a
-
++ grep Darwin
-
+ os=
从这里结果,我们就可以知道,在执行完os=xxx
赋值这条语句就退出了,这跟我们使用echo大法
得出的结论是一致的。
2.4.2 手动显示shell脚本时加选项
即类似这样: /bin/bash -evx 启动脚本
-
bash_shell_e$ /bin/bash -vxe test_shell_e.sh
-
# ~/.bashrc: executed by bash(1) for non-login shells.
-
# see /usr/share/doc/bash/examples/startup-files (in the package bash-doc)
-
# for examples
-
# If not running interactively, don't do anything
-
case $- in
-
*i*) ;;
-
*) return;;
-
esac
-
+ case $- in
-
+ return
-
#! /bin/bash -e
-
function get_os()
-
{
-
echo "begin to get OS ..."
-
os=`uname -a | grep Darwin`
-
if [ "$os" != "" ]; then
-
host_os_name=OSX
-
else
-
os=`uname -a | grep x86_64`
-
if [ "$os" != "" ]; then
-
host_os_name=Linux64
-
else
-
host_os_name=Linux32
-
fi
-
fi
-
echo "get OS name: $host_os_name"
-
}
-
function do_other_things()
-
{
-
echo "do other things ..."
-
}
-
get_os
-
+ get_os
-
+ echo 'begin to get OS ...'
-
begin to get OS ...
-
++ uname -a
-
++ grep Darwin
-
+ os=
注意:当使用命令行传递输入选项后,脚本文件首行的选项就不生效了,这也是我实践过程中才发现的。 如下所示: 我的脚本首行是指定了-e
的,但是它依然跑成功了,因为我使用-x
启动,没有带-e
。
-
bash_shell_e$ /bin/bash -x test_shell_e.sh
-
+ case $- in
-
+ return
-
+ get_os
-
+ echo 'begin to get OS ...'
-
begin to get OS ...
-
++ uname -a
-
++ grep Darwin
-
+ os=
-
+ '[' '' '!=' '' ']'
-
++ uname -a
-
++ grep x86_64
-
+ 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'
-
+ '[' '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' '!=' '' ']'
-
+ host_os_name=Linux64
-
+ echo 'get OS name: Linux64'
-
get OS name: Linux64
-
+ do_other_things
-
+ echo 'do other things ...'
-
do other things ...
-
+ exit 0
2.4.3 通过set命令设置调试选项
使用方法如下,它可以在脚本中调试任意一个函数,用法非常灵活
-
#! /bin/bash -e
-
function get_os()
-
{
-
echo "begin to get OS ..."
-
os=`uname -a | grep Darwin`
-
if [ "$os" != "" ]; then
-
host_os_name=OSX
-
else
-
os=`uname -a | grep x86_64`
-
if [ "$os" != "" ]; then
-
host_os_name=Linux64
-
else
-
host_os_name=Linux32
-
fi
-
fi
-
echo "get OS name: $host_os_name"
-
}
-
function do_other_things()
-
{
-
echo "do other things ..."
-
}
-
# open debug option
-
set -xv
-
get_os
-
# close debug option
-
set +xv
-
# re-open debug option
-
set -xv
-
do_other_things
-
# close debug option
-
set +xv
-
exit 0
增加这些调试之后,运行结果如下:
-
bash_shell_e$ ./test_shell_e_debug.sh
-
get_os
-
+ get_os
-
+ echo 'begin to get OS ...'
-
begin to get OS ...
-
++ uname -a
-
++ grep Darwin
-
+ 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文章
366浏览量
23485 -
脚本
+关注
关注
1文章
392浏览量
14976 -
RT-Thread
+关注
关注
31文章
1308浏览量
40494
发布评论请先 登录
相关推荐
如何将RT-Thread移植到NXP MCUXPressoIDE上
![如何将<b class='flag-5'>RT-Thread</b>移植到NXP MCUXPressoIDE上](https://file1.elecfans.com/web3/M00/08/12/wKgZPGetWzWAPmQsAAAT9RkoMiQ238.png)
RT-Thread上CAN实践
![<b class='flag-5'>RT-Thread</b>上CAN实践](https://file1.elecfans.com/web2/M00/C4/8A/wKgZomX0EhWACv8DAAAUet8ikhs451.png)
课程上线 - RT-Thread应用开发实践课程上线慕课平台啦!
![课程上线 - <b class='flag-5'>RT-Thread</b>应用开发实践课程上线慕课平台啦!](https://file1.elecfans.com/web2/M00/C4/8A/wKgZomX0EhWACv8DAAAUet8ikhs451.png)
【成都】9月21日RT-Thread巡回线下培训-OpenMV机器视觉
![【成都】9月21日<b class='flag-5'>RT-Thread</b>巡回线下培训-OpenMV机器视觉](https://file1.elecfans.com/web2/M00/C4/8A/wKgZomX0EhWACv8DAAAUet8ikhs451.png)
【大连】9月7日RT-Thread巡回线下培训-OpenMV机器视觉
![【大连】9月7日<b class='flag-5'>RT-Thread</b>巡回线下培训-OpenMV机器视觉](https://file1.elecfans.com/web2/M00/C4/8A/wKgZomX0EhWACv8DAAAUet8ikhs451.png)
2024 RT-Thread全球巡回 线下培训火热来袭!
![2024 <b class='flag-5'>RT-Thread</b>全球巡回 线下培训火热来袭!](https://file1.elecfans.com/web2/M00/C4/8A/wKgZomX0EhWACv8DAAAUet8ikhs451.png)
RT-Thread 新里程碑达成——GitHub Star 破万!
![<b class='flag-5'>RT-Thread</b> 新里程碑达成——GitHub Star 破万!](https://file1.elecfans.com/web2/M00/C4/8A/wKgZomX0EhWACv8DAAAUet8ikhs451.png)
6月6日杭州站RT-Thread线下workshop,探索RT-Thread混合部署新模式!
![6月6日杭州站<b class='flag-5'>RT-Thread</b>线下workshop,探索<b class='flag-5'>RT-Thread</b>混合部署新模式!](https://file1.elecfans.com/web2/M00/C4/8A/wKgZomX0EhWACv8DAAAUet8ikhs451.png)
【上海】5月25日-基于恩智浦MCX N系列MCU结合RT-Thread的应用与实践 线下培训
![【上海】5月25日-基于恩智浦MCX N系列MCU<b class='flag-5'>结合</b><b class='flag-5'>RT-Thread</b>的应用与实践 线下培训](https://file1.elecfans.com/web2/M00/C4/8A/wKgZomX0EhWACv8DAAAUet8ikhs451.png)
新书发布——《实时操作系统应用技术:RT-Thread与ARM编程实践》
![新书发布——《实时操作系统应用技术:<b class='flag-5'>RT-Thread</b>与ARM编程实践》](https://file1.elecfans.com/web2/M00/C4/8A/wKgZomX0EhWACv8DAAAUet8ikhs451.png)
4月25日北京站RT-Thread线下workshop,探索RT-Thread混合部署新模式
![4月25日北京站<b class='flag-5'>RT-Thread</b>线下workshop,探索<b class='flag-5'>RT-Thread</b>混合部署新模式](https://file1.elecfans.com/web2/M00/C4/8A/wKgZomX0EhWACv8DAAAUet8ikhs451.png)
4月10日深圳场RT-Thread线下workshop,探索RT-Thread混合部署新模式!
![4月10日深圳场<b class='flag-5'>RT-Thread</b>线下workshop,探索<b class='flag-5'>RT-Thread</b>混合部署新模式!](https://file1.elecfans.com/web2/M00/C6/D0/wKgaomYDlJyAKUBmAAAgR-TqYwc187.png)
4月10日深圳场RT-Thread线下workshop,探索RT-Thread混合部署新模式!
![4月10日深圳场<b class='flag-5'>RT-Thread</b>线下workshop,探索<b class='flag-5'>RT-Thread</b>混合部署新模式!](https://file1.elecfans.com/web2/M00/C4/8A/wKgZomX0EhWACv8DAAAUet8ikhs451.png)
恩智浦半导体正式加入RT-Thread全球合作伙伴计划!
![恩智浦半导体正式加入<b class='flag-5'>RT-Thread</b>全球合作伙伴计划!](https://file1.elecfans.com/web2/M00/C5/31/wKgaomXyY_eAHGhqAAAkpBZI8PE901.png)
评论