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