1 前言
1.1 項目背景
這段時間博主在寫一些編譯構建的腳本,考慮到知識的儲備性,之前對bash shell解除最多,而且我們的編譯環境是在Linux下進行,所以我優選了bash shell腳本。
1.2 功能描述
期間我寫了一個腳本,大致的功能就是獲取當前操作系統是MacOS還是Linux,如果是Linux的話,還需要知道是Linux32還是Linux64。
2 場景分析
2.1 腳本實現
我們都知道Linux系統下有個uname命令可以輸出當前系統的詳細信息,而MacOS上由于它是Unix系統演變來的,所以它也是支持這個命令的。 經過一番研究,我就決定使用uname-a來獲取輸出信息,然后從輸出信息里面檢索關鍵字,進而判斷是什么系統。 腳本實現代碼如下:
-
#! /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 -
do_other_things -
exit 0
2.2 問題復現
從功能邏輯上分析,沒有任何問題,結果我在Linux-x64上面一跑,出乎意料了:
-
bash_shell_e$ ./test_shell_e.sh -
begin to get OS ...
感覺腳本壓根就沒跑完啊?怎么回事?
2.3 問題分析
調試代碼,先從邏輯上分析沒有問題,再使用萬能的print大法,不過再bash shell里面就要用echo了。 通過一行行echo添加log,最終定位到是:
-
os=`uname -a | grep Darwin`
執行完這句之后,后面的if語句就沒跑進去! 但是uname-a|grepDarwin在我的機器上是可以執行的,并不會報錯:
-
bash_shell_e$ uname -a | grep Darwin -
bash_shell_e$
雖然是啥也沒輸出。 我們都知道在bash shell里面是通過echo $?來判斷上一條命令執行是否成功的:
-
bash_shell_e$ echo $? -
1 -
bash_shell_e$ -
bash_shell_e$ ls -
test_shell_e.sh -
bash_shell_e$ -
bash_shell_e$ echo $? -
0
嗯哼?返回1,這個引起了我的注意,證明這條命令執行的返回是失敗的。 回頭再看看腳本的開始,我習慣上是寫
-
#! /bin/bash -e
至于為啥帶上-e,以前壓根就沒去考慮過,反正看到linux下的好多系統腳本就是這樣寫的,咱這樣是像標準看齊,沒想到還搞出問題了。
2.4 -e究竟是什么含義?
通過查了一些資料,發現這個-e不簡單,它可以對每一條執行的shell腳本,自動判斷其是否執行成功,如果執行失敗,就立即退出整個腳本的執行。 用代碼來體現就是,如果不加-e,你需要對一個命令的執行結果判斷,就應該這樣:
-
excute_shell_cmd -
if [ $? != 0 ]; then -
exit 1 -
fi
而有了-e,就只有這樣:
-
excute_shell_cmd
看,是不是大大簡潔了腳本,而不會出現滿屏的if-fi。 但是這個帶來的最大問題就是,你可能不知道哪條語句就退出了,應該這里退出腳本執行的時候,沒有任何輸出提示,就好像我的案例場景一樣。
2.4 解決辦法1
既然知道是-e選項引起的,我去掉試試看:
-
#! /bin/bash -
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 -
do_other_things -
exit 0
執行一下:
-
bash_shell_e$ ./test_shell.sh -
begin to get OS ... -
get OS name: Linux64 -
do other things ...
得到了正確的結果,在其他平臺上,也得到了正確的結果。
2.5 解決辦法2
但是,如果我不想去掉-e呢,有沒有什么辦法? 經過一番調試,我發現這樣是可以的:
-
#! /bin/bash -e -
function get_os() -
{ -
echo "begin to get OS ..." -
osx_name=Darwin -
linux64_name=x86_64 -
if [ "`uname -a | grep $osx_name`" != "" ]; then -
host_os_name=OSX -
elif [ "`uname -a | grep $linux64_name`" != "" ]; then -
host_os_name=Linux64 -
else -
host_os_name=Linux32 -
fi -
echo "get OS name: $host_os_name" -
} -
function do_other_things() -
{ -
echo "do other things ..." -
} -
get_os -
do_other_things -
exit 0
輸出結果如下:
-
bash_shell_e$ ./test_shell_ok.sh -
begin to get OS ... -
get OS name: Linux64 -
do other things ...
這里的區別在于,直接把uname-a|grepDarwin的執行結果參與if判斷,而不是用一個變量去接收返回;這樣居然就通過了。
2.6 擴展延伸
有沒有更好的方法調試shell腳本呢?而不是滿屏的echo? 這個,下次我再發文介紹些高階手段吧,敬請期待。
3 更多分享
架構師李肯
一個專注于嵌入式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文章
375瀏覽量
25375 -
腳本
+關注
關注
1文章
409瀏覽量
29193 -
Bash
+關注
關注
0文章
57瀏覽量
10751 -
RT-Thread
+關注
關注
32文章
1613瀏覽量
44869
發布評論請先 登錄
恩智浦亮相RT-Thread 20周年開發者大會
首搭RT-Thread程翧車控平臺| RT-Thread程翧 S32K344 快速原型開發平臺正式上市!| 產品動態
【RT-Thread×玄鐵 | 硬核直播】RISC-V新核E901發布!RT-Thread手把手帶你玩轉玄鐵生態! | 博觀講堂
基于RT-Thread的EK-RA2E2 設備驅動移植與應用 | 技術集結
學習強國深度報道 RT-Thread“1+X+N”戰略,國產操作系統賦能高端制造引關注|媒體視角
2025年RT-Thread開發者巡回培訓報名正式啟動!
rt-thread studio 2.2.9如何使用最新的RT-Thread v5.2.0 released?
在Ubuntu上開發基于先楫MCU的RT-Thread應用指南
【好書推薦】RT-Thread第20本相關書籍!《嵌入式實時操作系統RT-Thread原理與應用》| 技術集結
RT-Thread 遇上 Rust:安全內核 RusT-Thread 的誕生
RT-Thread榮獲2025優秀開源項目 | 新聞速遞
RT-Thread BSP全面支持玄鐵全系列RISC-V 處理器 | 技術集結
揭秘RT-Thread上的AUTOSAR CP系統
2025 RT-Thread全球技術大會議程正式發布!
RT-Thread審核團招募: 深度參與開源RTOS社區治理與演進
【RT-Thread學習筆記】bash shell -e參數
評論