0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

Linux shell腳本經(jīng)驗(yàn)分享

汽車玩家 ? 來源:面包板社區(qū) ? 作者:面包板社區(qū) ? 2020-04-04 17:28 ? 次閱讀

作為一枚Linux嵌入式程序猿,寫shell腳本也是經(jīng)常碰到的工作,在這個(gè)過程中或多或少踩過一些坑,也積累了一些經(jīng)驗(yàn),在此分享給大家,希望能對(duì)大家有點(diǎn)幫助。

1. 指定bash

我們知道在shell 腳本的第一行,都應(yīng)該指定bash,那#!之后到底應(yīng)該是什么呢?

這個(gè)問題估計(jì)不同的人的回答可能都不一樣。我見過/usr/bin/env bash,也見過/bin/bash,還有/usr/bin/bash,還有/bin/sh,還有/usr/bin/env sh。我自己也用過其中過的幾個(gè),其實(shí)在很多情況下,以上幾種寫法效果都是相同的。但是,坑我們的往往就是少數(shù)情況~

如果恰好碰到系統(tǒng)的默認(rèn)shell不是bash怎么辦?比如某Linux發(fā)行版的某個(gè)版本,默認(rèn)的 sh 就不是 bash。如果系統(tǒng)的bash不是在/usr/bin/bash怎么辦?

還有關(guān)于bash和sh的一些小區(qū)別:

假設(shè)我們寫一小段腳本,看看運(yùn)行結(jié)果!

#!/bin/sh

source mlryj.sh

echo “hello world!”

執(zhí)行結(jié)果:

Linux shell腳本經(jīng)驗(yàn)分享

然后我們將腳本改成這樣

#!/bin/bash

source mlryj.sh

echo “hello world!”

執(zhí)行結(jié)果:

Linux shell腳本經(jīng)驗(yàn)分享

從結(jié)果看,在#!/bin/sh的情況下,在mlryj.sh這個(gè)腳本不存在的情況下,source不成功,不會(huì)運(yùn)行source后面的代碼。

而在#!/bin/bash的情況下,雖然source不成功,但是還是運(yùn)行了source后面的echo語句。

為什么會(huì)這樣呢?

接下來我們看一看/bin/sh是個(gè)什么東西。

Linux shell腳本經(jīng)驗(yàn)分享

從上面可以看到,sh只是bash的一個(gè)軟鏈接,在一般的linux系統(tǒng)當(dāng)中,sh調(diào)用執(zhí)行腳本相當(dāng)于打開了bash的posix模式,也就是說 /bin/sh 相當(dāng)于 /bin/bash --posix。posix的特定規(guī)范之一是,當(dāng)某行代碼出錯(cuò)時(shí),便不繼續(xù)往下解釋。

把腳本改成如下圖所示的格式,我們得到運(yùn)行結(jié)果和#!/bin/sh是一樣的。

#!/bin/bash --posix

source mlryj.sh

echo “hello world!”

推薦大家使用 /usr/bin/env bash 和 /bin/bash。前者通過env添加一個(gè)中間層,讓env在PATH中搜索bash;后者畢竟是有官方背書的,約定俗成的bash位置。但是當(dāng)腳本出現(xiàn)了錯(cuò)誤怎么辦呢?請(qǐng)看Tip2。

2. set -e 和 set -x

好了,關(guān)于指定bash已經(jīng)完成了。接下來該開始寫shell腳本第二行、第三行。

小編建議:在你開始構(gòu)思并寫下具體的代碼邏輯之前,先插入一行“set -e”和一行“set -x”。

set -x會(huì)在執(zhí)行每一行shell腳本時(shí),把執(zhí)行的內(nèi)容輸出來。它可以讓你看到當(dāng)前執(zhí)行的情況,里面涉及的變量也會(huì)被替換成實(shí)際的值。

set -e會(huì)在執(zhí)行出錯(cuò)時(shí)結(jié)束程序,就像其他語言中的“拋出異常”一樣。

這兩個(gè)組合在一起,可以在debug的時(shí)候替自己節(jié)省許多時(shí)間。出于防御性編程的考慮,有必要在寫第一行具體的代碼之前就插入它們。捫心自問,寫代碼的時(shí)候能夠一次寫對(duì)的次數(shù)有多少?大多數(shù)代碼,在提交之前,通常都經(jīng)歷過反復(fù)調(diào)試修改的過程。與其在焦頭爛額之際才引入這兩個(gè)配置,不如一開始就給調(diào)試留下余地。在代碼終于可以提交之后,再考慮是否保留它們也不遲。

#!/bin/sh

set -x

set -e

source mlryj.sh

echo “hello world!”

運(yùn)行結(jié)果如下:

Linux shell腳本經(jīng)驗(yàn)分享

3. shellcheck

加了set -x和set -e后,現(xiàn)在我已經(jīng)有了shell開始的三行代碼,但是具體的業(yè)務(wù)邏輯一行都沒寫。是不是該開始寫了?

且慢!工欲善其事,必先利其器。小編先給各位介紹一個(gè)shell腳本編寫神器:shellcheck

很慚愧,雖然這幾年寫了一些shell腳本,但是真正寫起來的時(shí)候還是有很多語法記不清楚。這時(shí)候就要依仗shellcheck了。

shellcheck除了可以提醒語法問題以外,還能檢查出shell腳本編寫常見的錯(cuò)誤代碼。相信我,使用shellcheck會(huì)給我們的shell編寫能力帶來了巨大的飛躍的。

安裝方法如下圖:

Linux shell腳本經(jīng)驗(yàn)分享

安裝完成后可以通過shellcheck -V查看當(dāng)前安裝成功的版本號(hào)。如下圖:

Linux shell腳本經(jīng)驗(yàn)分享

雖然我們技能不如別人,但是我們可以升級(jí)裝備,在裝備上趕上并超過對(duì)方??!有了shellcheck加持就好比真三中諸葛亮帶上了飛鞋,郭嘉買了孫子兵法,哈哈哈~~

4. 注意local

首先我們來看一下下面兩段代碼及運(yùn)行結(jié)果,代碼段1:

#!/bin/bash

set -x

set -e

function wgytest()

{

a=$1

echo a

}

wgytest shell

echo “hello world!”

echo $a

運(yùn)行結(jié)果如下圖所示:

Linux shell腳本經(jīng)驗(yàn)分享

代碼段2:

#!/bin/bash

set -x

set -e

function wgytest()

{

local a=$1

echo a

}

wgytest shell

echo “hello world!”

echo $a

運(yùn)行結(jié)果如下圖所示:

Linux shell腳本經(jīng)驗(yàn)分享

從上面的代碼可以看出,我們只是將函數(shù)wgytest中的變量a加了local限定詞,運(yùn)行結(jié)果可以看出,第二段代碼最后的echo并沒有輸出變量a的內(nèi)容。

這是因?yàn)樵赽ash,如果不加local限定詞,變量默認(rèn)都是全局的。在頂級(jí)作用域里,是否是全局變量并不重要。但是在函數(shù)里面,聲明一個(gè)全局變量可能會(huì)污染到其他作用域,尤其在你根本沒有注意到這一點(diǎn)的情況下。當(dāng)我們開始把重復(fù)的邏輯提煉成函數(shù),這時(shí)就有可能會(huì)掉到bash的這一個(gè)坑里。所以,對(duì)于在函數(shù)內(nèi)聲明的變量,小編的建議是記得加上local限定詞。

5. 寫在最后

以上幾條都是具體的建議,這條來點(diǎn)虛的。

雖然使用shell可以方便快捷地實(shí)現(xiàn)各種復(fù)雜的功能,但也還是不得不依靠grep、sed、awk等各種工具把它們粘合在一起。實(shí)際上由于缺乏完善的數(shù)據(jù)結(jié)構(gòu)以及一致的API,shell腳本在處理復(fù)雜的邏輯上還是顯得力不從心。如果你的任務(wù)包含較為復(fù)雜的邏輯,而且數(shù)據(jù)結(jié)構(gòu)復(fù)雜,那么建議使用python之類的語言編寫腳本。

程序猿無論寫什么代碼,都要三思而行,切忌粗心大意。畢竟許多時(shí)候,我們的一個(gè)粗心就會(huì)給整個(gè)系統(tǒng)帶來一個(gè)悲劇,其實(shí)復(fù)雜的腳本也是發(fā)端于幾行小小的命令。一開始寫腳本的人,也許以為它只是一次性任務(wù)。代碼里難免對(duì)一些外部條件有些假定,在當(dāng)時(shí)也許是正常的,但是隨著外部環(huán)境的變化,這些就成了隱藏的雷。這就需要在編寫的時(shí)候辨清哪些是會(huì)變的依賴、哪些是腳本正常運(yùn)行所不可或缺的。同時(shí)要有防御性編程的意識(shí),給自己的代碼一道護(hù)城河。

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • Linux
    +關(guān)注

    關(guān)注

    87

    文章

    11123

    瀏覽量

    207892
  • Shell
    +關(guān)注

    關(guān)注

    1

    文章

    359

    瀏覽量

    23191
收藏 人收藏

    評(píng)論

    相關(guān)推薦

    shell腳本執(zhí)行的三種方式及區(qū)別

    Linux系統(tǒng)中,Shell腳本是一種非常實(shí)用的工具,用于自動(dòng)化執(zhí)行一系列命令。Shell腳本可以大大提高工作效率,簡(jiǎn)化復(fù)雜的任務(wù)。在這篇
    的頭像 發(fā)表于 08-30 15:24 ?235次閱讀

    執(zhí)行shell腳本的方式包括什么

    執(zhí)行Shell腳本的方式有很多種,以下是一些常見的方法: 直接運(yùn)行腳本文件 在命令行中,可以直接使用腳本文件的路徑來運(yùn)行腳本。例如: ./s
    的頭像 發(fā)表于 08-30 15:17 ?153次閱讀

    shell腳本編寫之本地腳本的編寫和執(zhí)行

    用來指定使用的shell應(yīng)用;echo "my first shell !"為腳本中編寫的命令代碼。2、執(zhí)行在執(zhí)行腳本時(shí),腳本
    發(fā)表于 08-28 09:36

    Shell腳本檢查工具ShellCheck介紹

    ShellCheck是一個(gè)用于bash/sh shell腳本的靜態(tài)分析工具,可以輔助檢查腳本語法錯(cuò)誤,給出建議增強(qiáng)腳本健壯性。
    的頭像 發(fā)表于 12-27 13:43 ?1596次閱讀
    <b class='flag-5'>Shell</b><b class='flag-5'>腳本</b>檢查工具ShellCheck介紹

    100個(gè)Linux Shell腳本總結(jié)

    不知道大家有沒有發(fā)現(xiàn),會(huì)編寫shell腳本的運(yùn)維,工資不會(huì)低,并且他的工作會(huì)很輕松!今天浩道跟大家分享每一個(gè)Linux運(yùn)維應(yīng)知必會(huì)的100個(gè)shell
    的頭像 發(fā)表于 12-05 09:28 ?941次閱讀

    linux命令行與shell編程實(shí)戰(zhàn)

    Linux命令行與Shell編程實(shí)戰(zhàn)主要涉及以下內(nèi)容: Linux命令行基礎(chǔ):學(xué)習(xí)Linux命令行的基本操作,如文件管理、進(jìn)程管理、網(wǎng)絡(luò)配置等。熟悉使用命令行能夠提高工作效率,提升自己
    的頭像 發(fā)表于 11-08 10:57 ?622次閱讀

    linux命令和shell編程有什么聯(lián)系

    的命令,并提供了許多功能和特性,如變量、控制結(jié)構(gòu)、函數(shù)等,這些功能和特性使得Shell編程成為可能。 其次,Linux命令是Shell編程的重要組成部分。通過使用Linux命令,用戶可
    的頭像 發(fā)表于 11-08 10:53 ?768次閱讀

    shell命令和linux命令一樣嗎

    Shell命令和Linux命令并不完全一樣。 首先,Shell是一種命令行解釋器,它是用來解釋和執(zhí)行用戶輸入的命令的。Shell既是一種命令語言,也是一種程序設(shè)計(jì)語言。它可以由一系列的
    的頭像 發(fā)表于 11-08 10:51 ?2435次閱讀

    shell并行執(zhí)行java腳本

    Shell是一種用于解釋執(zhí)行命令的腳本語言,而Java是一種跨平臺(tái)的面向?qū)ο缶幊陶Z言。在某些情況下,我們可能需要在Shell腳本中執(zhí)行Java程序。本文將介紹如何在
    的頭像 發(fā)表于 11-08 10:29 ?531次閱讀

    shell并行調(diào)用腳本

    Shell腳本中,可以使用一些技巧來實(shí)現(xiàn)并行調(diào)用。以下是幾種常見的方法: 使用后臺(tái)進(jìn)程:在Shell腳本中,可以使用"command2 上述腳本
    的頭像 發(fā)表于 11-08 10:23 ?797次閱讀

    如何利用shell進(jìn)行腳本程序的設(shè)計(jì)?

    利用Shell進(jìn)行腳本程序的設(shè)計(jì)可以按照以下步驟進(jìn)行: 選擇Shell解釋器:在Unix和Linux系統(tǒng)中,通常會(huì)默認(rèn)安裝一個(gè)或多個(gè)Shell
    的頭像 發(fā)表于 11-08 10:17 ?432次閱讀

    shell腳本編寫程序

    當(dāng)編寫Shell腳本時(shí),你需要按照以下步驟進(jìn)行: 打開一個(gè)文本編輯器,例如vi、nano或gedit。 創(chuàng)建一個(gè)新文件,并將其保存為以.sh為擴(kuò)展名的文件, 例如script.sh 。 在文件的第一
    的頭像 發(fā)表于 11-08 10:12 ?761次閱讀

    shell腳本基本命令

    Shell腳本是一種可執(zhí)行文件,它包含了一組用某種特定語言編寫的命令,這些命令可以被解釋器(如bash)執(zhí)行。以下是一些常見的shell腳本基本命令: echo命令:用于輸出字符串。例
    的頭像 發(fā)表于 11-08 10:08 ?1718次閱讀

    BASH shell腳本篇—文件處理介紹

    在Bash Shell腳本中,可以使用多種方法來對(duì)文件進(jìn)行操作,包括讀取文件或?qū)懭胛募?/div>
    的頭像 發(fā)表于 10-23 16:51 ?480次閱讀

    Linux指令與Shell編程范例的速查手冊(cè)

    理問題,而最常用、最基本的編程工具就是Shell腳本。 Shell腳本類似于傳統(tǒng)的DOS與Windows中的.bat文件,可直接引入外部的命令,并使用基本的編程語法,如判斷和遞歸處理。
    發(fā)表于 09-22 08:01