大家好,是矜辰所致,嵌入式 Linux入 門(mén)第五課,本課開(kāi)始簡(jiǎn)單學(xué)習(xí)一下 Shell 腳本編程。
前言
雖然對(duì)于做嵌入式 Linux 來(lái)說(shuō),Shell 腳本使用相對(duì)來(lái)說(shuō)不需要那么深入,一般使用的腳本也不會(huì)太復(fù)雜,但是我們也經(jīng)常需要用到,所以還是需要特別學(xué)習(xí)一下。
何為腳本?腳本有很多名字,比如可稱(chēng)為自動(dòng)化程序,它的目的都是減少人工操作,提高效率,腳本語(yǔ)言是像劇本一樣教計(jì)算機(jī)辦某個(gè)事情的語(yǔ)言。
我們?cè)谇懊娴奈恼轮幸呀?jīng)學(xué)習(xí)過(guò) Linux Shell ,我們知道Shell 既是一種命令語(yǔ)言,又是一種程序設(shè)計(jì)語(yǔ)言,本文我們就來(lái)認(rèn)識(shí)學(xué)習(xí)一種為 Shell 編寫(xiě)的腳本程序,Shell 腳本(shell script)。
博主當(dāng)初在學(xué)習(xí) Shell 腳本的時(shí)候,其實(shí)也是有點(diǎn)坎坷,最主要的是當(dāng)時(shí)的心態(tài)問(wèn)題,心中認(rèn)為嵌入式開(kāi)發(fā) Shell 腳本會(huì)簡(jiǎn)單的就好,但是因?yàn)橛羞@種心態(tài),導(dǎo)致學(xué)習(xí)的時(shí)候不是那么用心,以至于入門(mén)就花了好長(zhǎng)一段時(shí)間,所以學(xué)習(xí)還是得擺正心態(tài),用心!
嵌入式 Linux 入門(mén)系列博文:
嵌入式 Linux 入門(mén)(一、Linux 基本介紹及文件結(jié)構(gòu))
嵌入式 Linux 入門(mén)(二、Linux 文件系統(tǒng)、文件類(lèi)型及權(quán)限管理)
嵌入式 Linux 入門(mén)(三、Linux Shell 及常用命令說(shuō)明)
嵌入式 Linux 入門(mén)(四、Linux 下的編輯器 — 讓人愛(ài)恨交加的 vi )
一、Shell 腳本基礎(chǔ)說(shuō)明
所謂腳本,就是一個(gè)文件,文件里面存放的是 特定格式的指令,系統(tǒng)可以 使用腳本解析器翻譯指令并執(zhí)行 。
在我們熟悉的 Windows 中,我們會(huì)有 bat 文件,這可以認(rèn)為是 Windows 中的腳本,通過(guò)代碼來(lái)實(shí)現(xiàn)一系列的任務(wù)。
比如在以前學(xué)習(xí) STM32 的時(shí)候正點(diǎn)原子源碼中的工程清理腳本:
1.1 什么是 Shell 腳本
在 linux 中,我們所說(shuō)的 Shell 腳本: 由 Shell 命令 以及 相關(guān)的語(yǔ)法語(yǔ)句 組合組成的一個(gè)文件。
Shell 腳本通過(guò)解釋器解釋運(yùn)行,不用編譯即。
上面說(shuō)的 Shell 命令,就是我們?cè)谇懊嫖恼?嵌入式 Linux 入門(mén)(三、Linux Shell 及常用命令說(shuō)明) 學(xué)習(xí)過(guò)的 Shell 命令。
上面說(shuō)的 相關(guān)的語(yǔ)法語(yǔ)句,就是我們本文需要學(xué)習(xí)的 Shell 腳本的語(yǔ)法。在 Shell 腳本中,也有變量,流程控制語(yǔ)句等,他們和 Shell 命令結(jié)合起來(lái)就形成了一個(gè)功能強(qiáng)大的shell 腳本。
Shell 腳本是一個(gè)文件,由 Shell 命令 和 相關(guān)語(yǔ)法語(yǔ)句 組成!
1.2 Shell 腳本的意義
我們開(kāi)頭就說(shuō)過(guò),腳本的目的都是減少人工操作,提高效率。
Shell 腳本的意義簡(jiǎn)單概括為以下幾點(diǎn):
- 重復(fù)步驟的執(zhí)行;
- 批量事物的處理;
- 定時(shí)任務(wù)執(zhí)行;
4、方便管理員進(jìn)行文件管理,Linux下一切接文件,所以可以理解為方便管理員進(jìn)行所有東西的管理,包括安裝,部署,啟動(dòng),備份,監(jiān)控,分析等等功能 。
在我們開(kāi)發(fā) STM32 的時(shí)候,也可以使用 GCC 環(huán)境,那么就有一個(gè) Makefile 文件,Makefile 就是一種類(lèi)似于 Shell 腳本的 “腳本” (Makefile 與 Shell 腳本語(yǔ)法有不同)。
使用 Makefile 我們可以簡(jiǎn)單的使用一個(gè) make 命令經(jīng)常程序的編譯工作,大大提高了我們的開(kāi)發(fā)效率。(Makefile 的內(nèi)容,我們?cè)诤竺嬉矔?huì)有文章說(shuō)明)。
1.3 Shell 命令的本質(zhì)
本小結(jié)是為了讓我們加深對(duì) Shell 命令的理解。
首先要說(shuō)明幾個(gè)概念 : Shell 的 內(nèi)置命令 與 外部命令 。
Shell 內(nèi)置命令
Shell 內(nèi)置命令是內(nèi)嵌在shell中的,是shell的一部分,這些命令由 shell 程序識(shí)別并在 shell 程序內(nèi)部完成運(yùn)行,當(dāng)系統(tǒng)加載 shell 時(shí)被加載并駐留在內(nèi)存中。
比如 linux 的一些簡(jiǎn)單命令 cd,pwd 等。
Shell 外部命令
外部命令其實(shí)是 linux 的 程序,其命令執(zhí)行過(guò)程是由shell程序控制的,在需要時(shí)才將其調(diào)用內(nèi)存,當(dāng)一個(gè)外部命令被執(zhí)行時(shí),一個(gè)新的進(jìn)程即被創(chuàng)建同時(shí)命令被執(zhí)行,外部命令是對(duì)應(yīng)著一個(gè)程序,可以理解為 Shell 調(diào)用了其他程序的運(yùn)行。
shell 程序管理外部命令執(zhí)行的路徑查找、加載存放,并控制命令的執(zhí)行。注意,程序功能強(qiáng)大程序量也會(huì)很大。
外部命令是在 bash 之外額外安裝的,通常放/bin,/usr/bin,/sbin,/usr/sbin 文件夾中。
判斷內(nèi)部命令還是外部命令:
我們可以使用 type
命令判斷命令是內(nèi)置還是外部的,如下圖:
☆ 那么問(wèn)題就來(lái)了 ,一個(gè)程序是如何成為一個(gè) Shell 命令的呢?☆
直接簡(jiǎn)單點(diǎn)說(shuō)明:
當(dāng)一個(gè)命令被敲下, Shell 首先回到內(nèi)存中去尋找它的內(nèi)置命令,當(dāng)遍歷所有內(nèi)置命令沒(méi)有找到的時(shí)候,它會(huì)去設(shè)置好的 環(huán)境變量 中尋找外部命令,其實(shí)就是尋找所對(duì)應(yīng)的應(yīng)用程序,如果找到對(duì)應(yīng)的應(yīng)用程序,它會(huì)創(chuàng)建一個(gè)新的進(jìn)程,然后在進(jìn)程里面執(zhí)行這個(gè)應(yīng)用程序。 如果內(nèi)外命令都沒(méi)有找到,就會(huì)報(bào)錯(cuò)。
在上面的句子中,外部命令是在設(shè)置的環(huán)境變量中查找的,那么如何查看環(huán)境變量呢?
我們可以使用echo
命令 直接打印環(huán)境變量,使用語(yǔ)句echo $PATH
,如下圖:
一個(gè)有趣的測(cè)試
我們上面知道了 Shell 外部命令是通過(guò)設(shè)置好的環(huán)境變量(就是一些目錄)中的一些應(yīng)用程序。
所以我們是不是可以自己做一個(gè) Shell 命令呢?
我們使用 vi 編輯器寫(xiě)一個(gè)簡(jiǎn)單的 hello world 程序,如下圖:
完成上面步驟我們看到, hello 現(xiàn)在可以運(yùn)行,可以認(rèn)為是一個(gè)應(yīng)用程序,結(jié)果是輸出 hello,world!
重點(diǎn)來(lái)了,首先我們這里要運(yùn)行,是需要用 “.” 指定為當(dāng)前路徑,./hello表示當(dāng)前路徑下的 hello 程序,我們也只能在這個(gè)路徑中運(yùn)行 hello 程序。 但是 Shell 命令,不受路徑的約束,我們想要把 hello 這個(gè)程序變成 Shell 命令,我們嘗試把 hello 放到環(huán)境變量的路徑中去。
如上圖,我們把一個(gè) c 語(yǔ)言的 hello 程序變成了一個(gè) shell 命令。
通過(guò)上面的測(cè)試,詳細(xì)大家應(yīng)該更加理解 Shell 命令的本質(zhì)。
1.4 Shell 腳本解釋器
Shell 腳本解釋器?本小結(jié)就是說(shuō)明一下,shell 腳本解釋器的種類(lèi)。
在我們前面講解 Shell 命令的文章中介紹 Shell 的時(shí)候有說(shuō)過(guò): Shell 有很多種實(shí)現(xiàn),我們最常用為 bash。
我們?cè)購(gòu)?fù)習(xí)說(shuō)明一下 Shell,Shell 介于操作系統(tǒng)內(nèi)核與用戶(hù)之間,負(fù)責(zé)接收用戶(hù)輸入的操作指令并進(jìn)行解釋?zhuān)瑢⑿枰獔?zhí)行的操作傳遞給內(nèi)核執(zhí)行,最后輸出執(zhí)行結(jié)果, Shell 是一個(gè) 命令解釋器 。
綜上我們可以總結(jié)出, 在 Linux 下面有多種命令解釋器,bash (Bourne Again Shell)是我們最常用的命令解釋器。
原因好像是因?yàn)?bash 易用以及免費(fèi),使用不同的 Shell 時(shí),其內(nèi)部指令、命令行提示符等方面會(huì)存在一些區(qū)別。
我們?cè)?嵌入式 Linux 入門(mén)(二、Linux 文件系統(tǒng)、文件類(lèi)型及權(quán)限管理) 中說(shuō)明用戶(hù)的時(shí)候,已經(jīng)知道了用戶(hù)使用的是哪種 Shell ,但是我們有更加直接的方式,直接使用命令echo $SHELL
:
我們說(shuō)系統(tǒng)中的 Shell 有很多種,那么到底有哪些呢?
在我們使用的 Ubuntu 中,可以通過(guò)查看 /etc/shells 文件了解當(dāng)前系統(tǒng)下所有支持的 shell,如下圖:
本文腳本編程,是針對(duì)于我們最常用的 bash 來(lái)說(shuō)明的。
1.5 編譯型語(yǔ)言 和 解釋型語(yǔ)言
簡(jiǎn)單說(shuō)明一下 編譯型語(yǔ)言 和解釋型語(yǔ)言,區(qū)別一下我們熟悉的 C 語(yǔ)言 于本文學(xué)習(xí)的 Shell 腳本語(yǔ)言。
本小結(jié)參考文章:編譯型語(yǔ)言和解釋型語(yǔ)言的區(qū)別
編譯型語(yǔ)言
- 編譯型語(yǔ)言要求必須提前將所有源代碼一次性轉(zhuǎn)換成二進(jìn)制指令,也就是生成一個(gè)可執(zhí)行程序(Windows 下的 .exe),比如C語(yǔ)言、C++、Golang、Pascal(Delphi)、匯編等
- 使用的轉(zhuǎn)換工具稱(chēng)為編譯器
對(duì)于編譯型語(yǔ)言,開(kāi)發(fā)完成以后需要將所有的源代碼都轉(zhuǎn)換成可執(zhí)行程序,只要我們擁有可執(zhí)行程序,就不再需要源代碼和編譯器了,可以隨時(shí)運(yùn)行。
編譯型語(yǔ)言可以脫離開(kāi)發(fā)環(huán)境運(yùn)行。
編譯型語(yǔ)言一般是不能跨平臺(tái)的。
首先,可執(zhí)行程序不能跨平臺(tái),pc 端的程序不能在 arm 芯片上運(yùn)行,windows 下的程序不能在 linux 上運(yùn)行;
其次,源代碼不能跨平臺(tái),這個(gè)有些是可以跨平臺(tái),有些是不可以。
解釋型語(yǔ)言
- 解釋型語(yǔ)言可以一邊執(zhí)行一邊轉(zhuǎn)換,需要哪些源代碼就轉(zhuǎn)換哪些源代碼,不會(huì)生成可執(zhí)行程序,比如 Python、JavaScript、PHP、Shell、MATLAB 等
- 使用的轉(zhuǎn)換工具稱(chēng)為解釋器。
對(duì)于解釋型語(yǔ)言,每次執(zhí)行程序都需要一邊轉(zhuǎn)換一邊執(zhí)行,用到哪些源代碼就將哪些源代碼轉(zhuǎn)換成機(jī)器碼,用不到的不進(jìn)行任何處理。每次執(zhí)行程序時(shí)可能使用不同的功能,這個(gè)時(shí)候需要轉(zhuǎn)換的源代碼也不一樣。
因?yàn)槊看螆?zhí)行程序都需要重新轉(zhuǎn)換源代碼,所以解釋型語(yǔ)言的執(zhí)行效率天生就低于編譯型語(yǔ)言,甚至存在數(shù)量級(jí)的差距。計(jì)算機(jī)的一些底層功能,或者關(guān)鍵算法,一般都使用 C/C++ 實(shí)現(xiàn),只有在應(yīng)用層面(比如網(wǎng)站開(kāi)發(fā)、批處理、小工具等)才會(huì)使用解釋型語(yǔ)言。
在運(yùn)行解釋型語(yǔ)言的時(shí)候,我們始終都需要源代碼和解釋器,所以說(shuō)它無(wú)法脫離開(kāi)發(fā)環(huán)境。
相比于編譯型語(yǔ)言,解釋型語(yǔ)言幾乎都能跨平臺(tái)。
這里要注意一下,解釋型語(yǔ)言的跨平臺(tái),是指源代碼跨平臺(tái),而不是解釋器跨平臺(tái)。
解釋器用來(lái)將源代碼轉(zhuǎn)換成機(jī)器碼,它就是一個(gè)可執(zhí)行程序,是絕對(duì)不能跨平臺(tái)的。
官方需要針對(duì)不同的平臺(tái)開(kāi)發(fā)不同的解釋器,同樣的代碼在不同平臺(tái)的執(zhí)行結(jié)果才是相同的。在不同的平臺(tái)下,解釋器會(huì)將相同的源代碼轉(zhuǎn)換成不同的機(jī)器碼,解釋器幫助我們屏蔽了不同平臺(tái)之間的差異。
.
對(duì)于編譯型語(yǔ)言,只需要提供可執(zhí)行文件就可以運(yùn)行,源代碼可以不提供,所以編譯型語(yǔ)言的可以不開(kāi)源。
對(duì)于解釋型語(yǔ)言,需要所有的源代碼才能運(yùn)行,所以解釋型語(yǔ)言的程序一般是開(kāi)源的。
額外提一句,最近幾年很火的 Python 屬于典型的解釋型語(yǔ)言,運(yùn)行 Python 程序需要解釋器的支持,只要你在不同的平臺(tái)安裝了不同的解釋器,你的代碼就可以隨時(shí)運(yùn)行,不用擔(dān)心任何兼容性問(wèn)題,也就是說(shuō),Python 的可移植性是很強(qiáng)的。
我們開(kāi)發(fā) STM32 使用的C 語(yǔ)言 是編譯型語(yǔ)言,本文說(shuō)明的 Shell 腳本語(yǔ)言是 解釋型語(yǔ)言。
通過(guò)上面的介紹,讓我們更好的理解了上一小節(jié)說(shuō)的 Shell 腳本解釋器為什么有不同種類(lèi),同時(shí)也能讓我們對(duì)編程語(yǔ)言能夠一個(gè)新的認(rèn)識(shí)或者理解。
二、第一個(gè) shell 腳本
2.1 寫(xiě)一個(gè) Shell 腳本
講了這么多,我們來(lái)寫(xiě)第一個(gè) Shell 腳本,使用 vi 編輯器創(chuàng)建一個(gè)腳本文件:
#! 用來(lái)聲明腳本由什么shell解釋?zhuān)駝t使用默認(rèn)shell
# 號(hào)代表注釋當(dāng)前行
擴(kuò)展名并不影響腳本執(zhí)行,腳本后綴名可以任意修改,仍然可以正常運(yùn)行。只不過(guò)我們寫(xiě)腳本的時(shí)候一般都需要見(jiàn)名知意,所以對(duì)給對(duì)于的后綴名: shell 腳本后綴為 .sh,Python 后綴名為 .py 。
2.2 Shell 腳本的啟動(dòng)方式
在上面我們寫(xiě)完了一個(gè) Shell 腳本,我們嘗試用以往的程序啟動(dòng)命令 "./" 運(yùn)行試試:
發(fā)現(xiàn)無(wú)法運(yùn)行,那么 Shell 腳本到底是如何啟動(dòng)的呢?
當(dāng)程序運(yùn)行
首先我們先說(shuō)我們熟悉的方式,就是上面這種方式,當(dāng)做程序運(yùn)行,但是上面實(shí)際上是失敗了,這是為什么呢?
我們看一下文件屬性,如下圖,新創(chuàng)建的 hello.sh 腳本并沒(méi)有執(zhí)行權(quán)限:
那么我們就給他執(zhí)行權(quán)限,在以前我們講解過(guò),給一個(gè)文件權(quán)限是用 chmod 命令,我們還說(shuō)過(guò)可以使用chmod 777
直接給一個(gè)文件最大權(quán)限,今天我們說(shuō)另外一種方式使用 chmod +x
添加執(zhí)行權(quán)限 ,如下圖:
添加了執(zhí)行權(quán)限以后,我們就可以把腳本當(dāng)成一個(gè)程序一樣執(zhí)行,如下圖:
指定解釋器運(yùn)行
在上文我們介紹過(guò),Linux 中也有很多種 Shell 解釋器,我們可以直接使用解釋器來(lái)運(yùn)行 Shell 腳本,如下圖:
直接指定解釋器執(zhí)行不需要為腳本賦予執(zhí)行權(quán)限,有和沒(méi)有權(quán)限都可以。
當(dāng)然,除了 bash 我們使用其他的解釋器也是可以的,如下圖:
source 和 .
直接使用命令source
和 .
執(zhí)行 Shell 腳本,此種方式也不需要執(zhí)行權(quán)限,如下圖:
那么初學(xué)者會(huì)疑問(wèn),source
和 .
是什么?
當(dāng)你不知道是什么的時(shí)候,不妨根據(jù)文章前面提到的判斷內(nèi)建命令還是外部命令的方式嘗試一下!如下圖:
測(cè)試過(guò)后,我們知道了, source
和 .
是 shell 的內(nèi)置命令,那么是命令就好說(shuō)了,記住就行了。
source
是一個(gè) linux 命令,通常使用 .
來(lái)代替,使用方式如下:
source filename # filename必須是可執(zhí)行的腳本文件
或
. filename # “.”號(hào)后面還有一個(gè)空格
額外說(shuō)明一下:
前兩種方式:當(dāng)成程序運(yùn)行和指定解釋器運(yùn)行 shell 腳本時(shí)都是在當(dāng)前 shell 環(huán)境下又開(kāi)了一個(gè)子 shell 環(huán)境,當(dāng)腳本執(zhí)行完后,子 shell 環(huán)境立刻就會(huì)關(guān)閉。而使用source
命令是在當(dāng)前 shell 環(huán)境下執(zhí)行的。
結(jié)語(yǔ)
本來(lái)是想一篇文章把 Shell 腳本說(shuō)完,但是作為入門(mén)文章,在基礎(chǔ)知識(shí)的說(shuō)明上寫(xiě)了很多的東西,其中也不乏有一些需要理解測(cè)試的內(nèi)容,所以還是把 Shell 腳本編程分成兩篇文章。
此篇主要在于基礎(chǔ)的介紹說(shuō)明,下一篇文章主要介紹 Shell 腳本的語(yǔ)法。
本文雖然只是理論的介紹說(shuō)明,但是不乏有很多值得品味的小細(xì)節(jié),對(duì)于入門(mén)者來(lái)說(shuō)看完以后值得好好的想一想,試一試,希望大家都能有所收獲!
本文先到這里,謝謝大家!
審核編輯:湯梓紅
-
嵌入式
+關(guān)注
關(guān)注
5121文章
19421瀏覽量
312640 -
Linux
+關(guān)注
關(guān)注
87文章
11411瀏覽量
212237 -
編程
+關(guān)注
關(guān)注
88文章
3671瀏覽量
94653 -
Shell
+關(guān)注
關(guān)注
1文章
369瀏覽量
23799 -
腳本
+關(guān)注
關(guān)注
1文章
395瀏覽量
28276
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
Linux Shell腳本入門(mén)到實(shí)戰(zhàn)詳解
嵌入式Linux開(kāi)發(fā)工具-shell編程介紹
shell腳本的相關(guān)資料分享
linux shell 腳本入門(mén)
嵌入式和物聯(lián)網(wǎng)的shell腳本學(xué)習(xí)指南之shell腳本入門(mén)免費(fèi)下載

Linux Shell腳本編程基礎(chǔ)和相關(guān)資料合集免費(fèi)下載

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

嵌入式Linux開(kāi)發(fā)工具——shell編程

Linux Shell腳本經(jīng)典案例分享

Linux從零到精通:最簡(jiǎn)單的Shell腳本入門(mén)教程

評(píng)論