1 問題回顧
在之前的文章 【shell編程掃盲系列】結合真實案例分析“bash shell -e”到底是啥意思? 中,我提到了我遇到一個bash shell-e
引發(fā)的問題,不瞞大家說,當時我是用echo大法
找到出問題的地方,加以修改才解決的。 那么,我們有沒有更加優(yōu)雅的調試方法,解決這類型的問題呢? 本篇文章將會給出答案。
2 shell腳本如何調試
2.1 特別說明
本文中提及的shell腳本
,無特殊說明的情況下,指的是bash shell
。這里做這個強調的主要原因是,不同的shell
的一些基礎語法可能有微小的差異,導致在bash shell中可以跑的腳本,但在別的shell上就跑不了。 這種案例可以參見:【Linux Shell】你知道bash shell和dash shell的區(qū)別嗎?
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 讀取所有命令然而不執(zhí)行它們,這個選項激活語法檢查模式。 -
-x
(xtrace 或 execution trace 簡稱) - 告訴 Shell 在終端顯示所有執(zhí)行的命令和它們的參數(shù)。 這個選項是啟用 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 的執(zhí)行結果
-
/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=
從這里結果,我們就可以知道,在執(zhí)行完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=
注意:當使用命令行傳遞輸入選項后,腳本文件首行的選項就不生效了,這也是我實踐過程中才發(fā)現(xiàn)的。 如下所示: 我的腳本首行是指定了-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命令設置調試選項
使用方法如下,它可以在腳本中調試任意一個函數(shù),用法非常靈活
-
#! /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=
從這個輸出,我們也可以看到在執(zhí)行完ox=xxx
賦值之后,腳本就停止運行,退出了,這跟我們之前的分析是一致的。 這個方法對于調試shell的函數(shù)非常有用,值得注意的是,set-xxx
需要加在執(zhí)行部分,而不是聲明部分。
3 經驗總結
- 調試shell腳本有3個選項,-x -n -v 用法各異,靈活使用;
- 調試shell腳本的方式也有3種,選用自己熟悉且方便的一種即可,高效排查問題。
4 更多分享
架構師李肯
一個專注于嵌入式IoT領域的架構師。有著近10年的嵌入式一線開發(fā)經驗,深耕IoT領域多年,熟知IoT領域的業(yè)務發(fā)展,深度掌握IoT領域的相關技術棧,包括但不限于主流RTOS內核的實現(xiàn)及其移植、硬件驅動移植開發(fā)、網絡通訊協(xié)議開發(fā)、編譯構建原理及其實現(xiàn)、底層匯編及編譯原理、編譯優(yōu)化及代碼重構、主流IoT云平臺的對接、嵌入式IoT系統(tǒng)的架構設計等等。擁有多項IoT領域的發(fā)明專利,熱衷于技術分享,有多年撰寫技術博客的經驗積累,連續(xù)多月獲得RT-Thread官方技術社區(qū)原創(chuàng)技術博文優(yōu)秀獎,榮獲CSDN博客專家、CSDN物聯(lián)網領域優(yōu)質創(chuàng)作者、2021年度CSDN&RT-Thread技術社區(qū)之星、RT-Thread官方嵌入式開源社區(qū)認證專家、RT-Thread 2021年度論壇之星TOP4、華為云云享專家(嵌入式物聯(lián)網架構設計師)等榮譽。堅信【知識改變命運,技術改變世界】!
本項目的所有測試代碼和編譯腳本,均可以在我的github倉庫01workstation中找到。
歡迎關注我的github倉庫01workstation,日常分享一些開發(fā)筆記和項目實戰(zhàn),歡迎指正問題。
同時也非常歡迎關注我的專欄:有問題的話,可以跟我討論,知無不答,謝謝大家。
-
Shell
+關注
關注
1文章
365瀏覽量
23354 -
腳本
+關注
關注
1文章
389瀏覽量
14858 -
RT-Thread
+關注
關注
31文章
1285瀏覽量
40079
發(fā)布評論請先 登錄
相關推薦
評論