1. 程式人生 > 實用技巧 >第一章 shell基礎

第一章 shell基礎

一、學習shell程式設計的目的

1.將運維工作自動化
2.為了解其他更高階程式語言打基礎

二、程式設計與程式語言

1.shell是一門程式語言,作為學習shell的開始,需要事先搞明白:程式設計的目的是什麼?什麼是程式語言?什麼是程式設計?

1)程式設計的目的

#計算機的發明,是為了用機器取代/解放人力,而程式設計的目的則是將人類的思想流程按照某種能夠被計算機識別的表達方式傳遞給計算機,從而達到讓計算機能夠像人腦/電腦一樣自動執行的效果。

人---------------漢語---------------人		
人---------------程式語言-----------計算機			
銀行行長-----------------------------櫃檯人員
	接收客戶輸入的賬號
	接收客戶輸入的密碼
	判斷 輸入的賬號 等於 正確的賬號 並且 輸入的密碼 等於 正確的密碼:	
		告訴使用者登入成功
	否則
		告訴使用者登入失敗

2)什麼是程式語言

#上面提及的能夠被計算機所識別的表達方式即為程式語言,語言是溝通的介質,而程式語言是程式設計師與計算機溝通的介質。在程式設計的世界裡,計算機更像是人的奴隸,人類程式設計的目的就是命令奴隸去工作。

3)什麼是程式設計

#程式設計即程式設計師根據需求把自己的思想流程按照某種程式語言的語法風格編寫下來,產出的結果就是包含一堆字元的檔案。

#強調: 程式在未執行前跟普通檔案無異,只有程式在執行時,檔案內所寫的字元才有特定的語法意義。

4)什麼是程式

#程式設計的結果就是程式,更準確的說,程式就是一系列程式碼檔案

5)什麼是程序?

#一個程式的執行過程,或者說是作業系統幹活的過程,即作業系統拿著計算機硬體去執行應用程式的過程。

6)程式設計的步驟

#程式設計就是人把自己想讓計算機做事的步驟給翻譯下來,可以總結為兩個步驟
	1)先把自己想讓計算機做事的步驟想清楚
	2)用一種計算機能聽懂的語言把做事的步驟翻譯下來,然後存入檔案

三、程式語言分類

1)機器語言

1.定義:用二進位制指令去程式設計程式,直接控制計算機硬體
2.優點:執行效率高
3.缺點:
	1)哪怕是實現一個簡單的功能,需要用到的二進位制指令的條數都會非常多(#程式設計的複雜高,即開發效率)
	2)難以記憶,極容易出錯

2)組合語言

1.定義:用英文標籤取代二進位制指令去編寫程式,直接控制計算機硬體
2.優點:執行效率也很高,解決機器語言難記的問題
3.缺點:
	1)程式設計的複雜程度依然很高,開發效率很低。
ps: 因為上述兩類語言都是在直接與計算機硬體打交道,離計算機硬體比較近,所以有統稱為低階語言。

3)高階語言

1.定義:用人類能理解的表達方式去編寫程式,計算機無法理解,需要經過翻譯計算機才能理解。
2.優點:開發複雜度低,即開發效率高
3.缺點:速度肯定是不如低階語言,一直到今天,對速度要求極高的場景還會用到低階語言,比如作業系統的排程程式。

4)翻譯方式

1.翻譯型別:
	1)編譯型(c、go):
	編譯型語言寫出的程式碼-------------》編譯器-------------》機器指令
	2)解釋型(shell、python)
	解釋型語言寫出的程式碼-------------》直譯器-------------》機器指令 

5)語言效率

1.執行效率:
機器語言》組合語言》高階語言(編譯型》解釋型)

2.開發效率:
機器語言《組合語言《高階語言

四、計算機完整體系結構圖

五、shell介紹

1)shell的含義

1.shell有兩層意思
#1.一層指的是shell這門語言,是一種特定的語法風格,規範等。
#2.另外一層指的是專門用於解釋執行shell這門語言語法的應用程式,即shell直譯器,我們常用的是bash
	
Shell 是一類應用程式的統稱,該類應用程式負責連線使用者和 Linux 核心,讓使用者能夠更加高效、安
全、低成本地使用 Linux 核心來控制計算機硬體。
具體來說,linux系統上自帶多種shell程式
通常使用者登入成功後執行的shell程式為:/bin/bash
[root@localhost ~]# chsh -l
/bin/sh
/bin/bash
/usr/bin/sh
/usr/bin/bash
/bin/tcsh
/bin/csh
[root@localhost ~]# head -1 /etc/passwd
root:x:0:0:root:/root:/bin/bash
其實,shell程式例如bash的本質就是一個直譯器,shell本身就是一門解釋型、弱型別、動態語言,與
python相對應,Python屬於解釋型、強型別、動態語言,我們平時登入成功一個使用者後進入的就是
bash直譯器的互動式環境,我們敲的命令其實都屬於shell這門語言的語法

2)為何要用shell

那還用說嗎,一些日常的運維工作自動化、配合計劃任務威力無窮,徹底解放雙手,你說它不香嗎?例
如
#自動備份
#自動部署
#監控指令碼

3)Shell VS python

1.shell語言
Shell 指令碼的優勢在於處理偏作業系統底層的業務,例如,Linux 內部的很多應用(有的是應用的一部分)都是使用 Shell 指令碼開發的,因為有 1000 多個 Linux 系統命令為它作支撐,特別是 Linux 正則表示式以及三劍客 grep、awk、sed 等命令。
對於一些常見的系統指令碼,使用 Shell 開發會更簡單、更快速,例如,讓軟體一鍵自動化安裝、優化,監控報警指令碼,軟體啟動指令碼,日誌分析指令碼等,雖然 Python 也能做到這些,但是考慮到掌握難度、開發效
率、開發習慣等因素,它們可能就不如 Shell 指令碼流行以及有優勢了。對於一些常見的業務應用,使用
Shell 更符合 Linux 運維簡單、易用、高效的三大原則。

2.python語言
Python 是近幾年非常流行的語言,它不但可以用於指令碼程式開發,也可以實現 Web 程式開發(知乎、豆
瓣、YouTube、Instagram 都是用 Python 開發),甚至還可以實現軟體的開發(大名鼎鼎的
OpenStack、SaltStack 都是 Python 語言開發)、遊戲開發、大資料開發、移動端開發。
現在越來越多的公司要求運維人員會 Python 自動化開發,Python 也成了運維人員必備的技能,每一個運
維人員在熟悉了 Shell 之後,都應該再學習 Python 語言。
Python 語言的優勢在於開發複雜的運維軟體、Web 頁面的管理工具和 Web 業務的開發(例如 CMDB 自動
化運維平臺、跳板機、批量管理軟體 SaltStack、雲端計算OpenStack 軟體)等。

六、第一個shell程式

1)編寫shell程式的兩種環境

#1.互動式環境
除錯方便,無法永久儲存程式碼

#2.寫到檔案中
我們採用解釋型語言編寫的程式碼檔案通常會被稱之為指令碼程式,可以永久儲存程式碼。

2)編寫shell指令碼程式

其實我們在互動式環境裡敲的命令直接放到一個文字檔案裡,一個簡單的shell程式就完成了
#強調: shell直譯器執行程式是解釋執行,即開啟檔案讀內容,因此檔案的字尾名沒有硬性限制,但通常定義為.sh結尾。

[root@localhost shell]# vim hello.sh
[root@localhost shell]# cat hello.sh
#!/bin/bash
#第一個shell小程式
echo "hello world!" 

1、第一行表示我們選擇使用的shell直譯器是bash,也可以用 :#!/usr/bin/env bash
	1)shell的第一行比較特殊,一般都會以#!開始來指定使用的shell解釋的型別。
	2)在linux中,除了bash shell以外,還有很多版本的shell, 例如zsh、dash等等...
	3)不過bash shell還是我們使用最多的。
2、第二行以#符號開始,表示本行是註釋,註釋是對程式碼的解釋說明,註釋的內容不會執行,對
關鍵程式碼加註釋是一種好的程式設計習慣
3、第三行中的echo是linux中的輸出命令,該行的意思很明顯的就是輸出hello world!

3)各種語言的hello word!

#C++
#include <iostream>
int main(void)
{
std::cout<<"Hello world";
}

#C
#include <stdio.h>
int main(void)
{
printf("\nhello world!");
return 0;
}

#JAVA
public class HelloWorld{
// 程式的入口
public static void main(String args[]){
// 向控制檯輸出資訊
System.out.println("Hello World!");
}
}

#PHP
<?php
echo "hello world!";
?>

#Ruby
日本人開發的,砸日本車的時候,順手就把你拖出去打死了,祭天
puts "Hello world."

#GO
package main
import "fmt"
func main(){
 fmt.Printf("Hello World!\n God Bless You!");
}

4)執行shell指令碼程式

shell程式通常會被稱為指令碼程式,因為shell屬於解釋型語言,而我們採用解釋型語言編寫的程式碼檔案
通常都會被稱之為指令碼程式,執行它有幾種方式:

#方式一 以絕對路徑的方式去執行shell指令碼,此時採用的是檔案頭指定的直譯器來解釋執行檔案內程式碼
1.許可權:
	1)對沿途資料夾有x許可權
	2)對目標檔案有r和x許可權
	
[root@egon ~~]# ll -d /a
d--------x. 3 root root 15 11? 15 11:05 /a
[root@egon ~~]# ll -d /a/b
d--------x. 2 root root 18 11? 15 11:06 /a/b
[root@egon ~~]# ll /a/b/hello.sh
-rw-r--r-x. 1 root root 10 11? 15 11:06 /a/b/hello.sh
[root@egon ~~]# su - egon
[egon@egon ~~]$ /a/b/hello.sh
hello world!
[egon@egon ~~]$

#方式二 以相對路徑的方式去執行shell指令碼,需要加./作為字首,此時採用的仍然是檔案頭指定的直譯器來解釋執行檔案內程式碼
1.許可權
	1)對沿途資料夾有x許可權
	2)對目標檔案有r和x許可權
	
[root@egon ~~]# ll -d /a
d--------x. 3 root root 15 11? 15 11:05 /a
[root@egon ~~]# ll -d /a/b
d--------x. 2 root root 18 11? 15 11:06 /a/b
[root@egon ~~]# ll /a/b/hello.sh
-rw-r--r-x. 1 root root 10 11? 15 11:06 /a/b/hello.sh
[root@egon ~~]# su - egon
[egon@egon ~~]$ /a/b/hello.sh # 絕對路徑的方式
hello world!
[egon@egon ~~]$ cd /a
[egon@egon /a/a]$ ./b/hello.sh # 相對路徑的方式,加./作為字首
hello world!
[egon@egon /a/a]$

#方式三 直譯器+檔案路徑(絕對路徑或相對路徑都可以),此時採用的是我們指定的直譯器來解釋執行檔案內程式碼。
1.許可權
	1)對沿途資料夾有x許可權
	2)對目標檔案有r許可權即可

	因為我們執行的是直譯器,當前使用者對直譯器有執行許可權就可以了,這個許可權預設就有,而直譯器需要讀檔案內容來執行,所以需要對目標檔案有r許可權。

[root@egon ~~]# chmod -R o=x /a
[root@egon ~~]# chmod o=r /a/b/hello.sh
[root@egon ~~]# su - egon
[egon@egon ~~]$ cd /a
[egon@egon /a/a]$ bash b/hello.sh
hello world!
[egon@egon /a/a]$

#方式四 上述三種方式都是在shell子程序中執行程式,而方式四則是在當前shell程序中執行。
1.許可權:
	1)對沿途資料夾有x許可權
	2)對目標檔案有r許可權即可
	
	上述三種方式都是在當前shell環境下開啟了一個新的shell直譯器環境/子shell來執行程式,指令碼程
序在子shell中執行完畢後,子shell環境隨即關閉,然後返回到父級shell即當前shell環境中,如果
就想在當前shell環境中執行,需要這麼做

[egon@localhost shell]$ cd /home/egon/shell/
[egon@localhost shell]$ ll hello.sh # 當前使用者egon對改檔案沒有執行許可權
-rw-r--r--. 1 root root 60 8? 14 18:33 hello.sh

# 下面兩種方式都一樣
[root@egon ~~]# chmod -R o=x /a
[root@egon ~~]# chmod o=r /a/b/hello.sh
[root@egon ~~]# su - egon
[egon@egon ~~]$ . /a/b/hello.sh # . 後跟空格,然後再跟絕對路徑
hello world!
[egon@egon ~~]$ cd /a/b/
[egon@egon /a/b/a/b]$ . hello.sh # . 後跟空格,然後再跟相對路徑
hello world!
[egon@egon /a/b/a/b]$ source hello.sh # 跟上述方式一樣
hello world!

在當前shell中執行指令碼與在子shell中執行指令碼的區別在於作用域,後續我們會詳細介紹
# 一個shell環境就是一個單獨的全域性作用域,不同的shell環境,無法訪問彼此shell環境中的變數
[egon@localhost ~]$ x=111
[egon@localhost ~]$ cat /home/egon/shell/hello.sh
#!/bin/bash
echo "hello world!" 
echo $x # 我們在這裡訪問一下全域性變數x
[egon@localhost ~]$ source /home/egon/shell/hello.sh # 在當前shell環境執行,可
以訪問到x
hello world!
111 # 取到了x的值
[egon@localhost ~]$ bash /home/egon/shell/hello.sh # 在子shell環境執行,不能訪問到x
hello world!
# 此處列印空

5)除錯shell程式

1.除錯方式1:以除錯的方式執行

[root@egon test]# sh -vx login.sh  # 不加-v選項,只會顯示程式中執行的程式碼,不會顯示註釋資訊

2.除錯方式2:只調試語法是否有問題,比如if判斷少了fi結尾

[root@egon test]# sh -n login.sh

3.除錯方式3:僅除錯指令碼的一部分,用set -x與set +x包含,執行過程中只打印它們包含的程式碼段的執行情況

[root@jh test]# cat login.sh
#!/usr/bin/env bash
set -x
read -p "請輸入您的名字: " name
read -p "請輸入您的密碼: " pwd
set +x
if [[ "$name" == "jh" && "$pwd" == "123" ]];then
echo "登入成功"
else
echo "賬號或密碼錯誤"
fi
[root@jh test]# . login.sh

6)註釋是程式碼之母

以#號開頭的內容不會執行,註釋的作用有二

1.註釋掉暫時不想執行的程式碼
2.為關鍵程式碼添加註解說明,增強程式的可讀性和可維護性
	1)可以加在被註釋程式碼的正上方單獨一行,或者被註釋程式碼的正後方,例如 # 註釋。。。
	2)不用全部加註釋,只需要在自己覺重要或不好理解的部分加註釋即可
	3)註釋可以用中文或者英文,但不要用拼音

七、shell編寫規範與建議

1)指令碼編寫規範

1、指令碼存放目錄需要統一

2、shell指令碼的結尾以.sh

3、指令碼開頭要有直譯器
如 #!/bin/bash 或者 #!/usr/bin/env bash

4、指令碼開頭注意加時間、作者、聯絡郵箱、指令碼作用等資訊
如 # Author egon 2020-8-30 version 1 des:xxxxx

5、關鍵程式碼應該用#號加上註釋

2)程式碼編寫好習慣

1、成對的符號儘量一次性寫出來,防止遺漏
例如大括號{},中括號[],小括號(),單引號’’,雙引號””,反引號``等

2、括號的保留空格習慣
中括號[ ]兩端需要留有空格,不然會報錯。書寫時即可留出空格然後書寫內容。如果不知道大括號{},中括號[],小括號(),到底哪種括號需要兩端留空格,可以在書寫這些括號的時候兩端都保留空格來進行書寫,這樣可以有效避免因空格導致的各種錯誤。

3、流程控制語句一次性書寫完再新增內容
例1:if語句格式一次書寫完成
if 條件內容
then
條件成立後執行的程式碼
fi
例2:for迴圈格式一次書寫完成
for條件內容
do
條件成立後執行的程式碼
done
提示:while、until、case等語句也是一樣

4、程式碼縮排提高可讀性