shell

第 2 章 SHELL 基礎知識
2.1 shell腳本
我們在上面簡單介紹了一下什么是shell腳本,現在我們來進一步的來介紹shell腳本的要求/格式/規范等內容
2.1.1 創建腳本
腳本創建工具:
創建腳本的常見編輯器是 vi/vim.

腳本命名
shell腳本的命名簡單來說就是要有意義,方便我們通過腳本名,來知道這個文件是干什么用的。

腳本內容:
各種可以執行的命令

注釋內容:
單行注釋:
除了首行的#不是注釋外,其他所有行內容,只要首個字符是#,那么就表示該行是注釋

!/bin/bash

echo '1'

echo '2' # 這一行就表示注釋

echo '3'

多行注釋:
多行注釋有兩種方法::<<! ... ! 和 :<<字符 ... 字符

!/bin/bash

echo '1'
:<<! echo '2'
echo '3'
echo '4'
!
echo '5'

2.1.2 腳本執行
shell執行的方式
Shell腳本的執行通常可以采用以下幾種方式

bash /path/to/script-name 或 /bin/bash /path/to/script-name (強烈推薦使用)
/path/to/script-name 或 ./script-name (當前路徑下執行腳本)
source script-name 或 . script-name (注意“.“點號)

執行說明:
1、腳本文件本身沒有可執行權限或者腳本首行沒有命令解釋器時使用的方法,我們推薦用bash執行。
使用頻率:☆☆☆☆☆
2、腳本文件具有可執行權限時使用。
使用頻率:☆☆☆☆
3、使用source或者.點號,加載shell腳本文件內容,使shell腳本內容環境和當前用戶環境一致。
使用頻率:☆☆☆
使用場景:環境一致性
2.1.2 腳本開發規范
1、腳本命名要有意義,文件后綴是.sh
2、腳本文件首行是而且必須是腳本解釋器

!/bin/bash

3、腳本文件解釋器后面要有腳本的基本信息等內容
腳本文件中盡量不用中文注釋;
盡量用英文注釋,防止本機或切換系統環境后中文亂碼的困擾
常見的注釋信息:腳本名稱、腳本功能描述、腳本版本、腳本作者、聯系方式等
4、腳本文件常見執行方式:bash 腳本名
5、腳本內容執行:從上到下,依次執行
6、代碼書寫優秀習慣;
1)成對內容的一次性寫出來,防止遺漏。
如:()、{}、[]、''、``、""
2)[]中括號兩端要有空格,書寫時即可留出空格[ ],然后再退格書寫內容。
3)流程控制語句一次性書寫完,再添加內容
7、通過縮進讓代碼易讀;(即該有空格的地方就要有空格)


2.2 變量
變量的學習我們主要從四個方面來學習:
變量的定義和分類
本地變量
全局變量
shell內置變量
2.2.1 什么是變量
變量是什么?
變量包括兩部分:
變量名 不變的
變量值 變化的
我們一般所說的變量指的是:變量名
2.2.2 本地變量
本地變量是什么?
本地變量就是:在當前系統的某個環境下才能生效的變量,作用范圍小。
本地變量包含兩種:普通變量和命令變量

普通變量:
普通變量的定義方式有如下三種,接下來我們就分別說一下這三種方式:

方式一:
變量名=變量值
重點:
變量值必須是一個整體,中間沒有特殊字符
方式二:
變量名='變量值'
重點:
我看到的內容,我就輸出什么內容
方式三:
變量名="變量值"
重點:
如果變量值范圍內,有可以解析的變量A,那么首先解析變量A,將A的結果和其他內容組合成一個整體,重新賦值給變量B

習慣:
數字不加引號,其他默認加雙引號

命令變量(熟練)
命令變量有兩種定義方式,接下來我們就來介紹一下這兩種方式

定義方式一:
變量名=命令
注意:
` 是反引號

定義方式二:
變量名=$(命令)

執行流程:
1、執行`或者$()范圍內的命令
2、將命令執行后的結果,賦值給新的變量名A


2.2.3 全局變量
全局變量是什么
全局變量就是:在當前系統的所有環境下都能生效的變量。

查看全局變量命令
可以通過命令查看環境變量
env 只顯示全局變量

定義全局變量
方法一:
變量=值
export 變量
方法二:(最常用)
export 變量=值

2.2.4 變量查看和取消
查看變量:
方式一:
變量名 場景: 私下里,在命令行/腳本中使用 圖省事 方式二: "變量名"
場景:
私下里,在命令行/腳本中使用
圖省事
方式三:
{變量名} 場景: echo " dsa dsafsa dsafsa{變量名} f "
使用頻率較高
方式四:
"${變量名}"
場景:
標準使用方式

取消變量
unset 變量名


2.2.5 shell內置變量
我們之前學習的本地變量,全局變量都是需要通過定義,然后才能實現相應功能的,那么有沒有一些變量我們可以直接拿過來使用實現某種具體的功能呢?有,這就是shell內置變量
和腳本文件有關
符號 意義
0 獲取當前執行的shell腳本文件名,包括腳本路徑n 獲取當前執行的shell腳本的第n個參數值,n=1..9,當n為0時表示腳本的文件名,如果n大于9就要用大 括號括起來{10}# 獲取當前shell命令行中參數的總個數
$? 獲取執行上一個指令的返回值(0為成功,非0為失敗)

重點內置變量演示效果:
$0 獲取腳本的名稱
示例:

!/bin/bash

獲取腳本的名稱

echo "我腳本的名稱是: file.sh"
echo "我腳本的名稱是:$0"

# 獲取當前腳本傳入參數的數量n 獲取當前腳本傳入的第n個位置的參數
示例:

!/bin/bash

獲取當前腳本傳入的參數數量

echo "當前腳本傳入的參數數量是: $#"

獲取指定位置的參數

echo "第一個位置的參數是: 1" echo "第二個位置的參數是:2"
echo "第三個位置的參數是: 3" echo "第四個位置的參數是:4"

$? 獲取文件執行或者命令執行的返回狀態值
示例:

bash nihao

bash: nihao: No such file or directory

echo $?

127

ls

file1.sh num.sh test.sh weizhi.sh

echo $?

0

字符串精確截取
格式:${變量名:起始位置:截取長度}

示例:
{file:0:5} 從第1個字符開始,截取5個字符{file::5} 從第1個字符開始,截取5個字符
{file:5:5} 從第6個字符開始,截取5個字符{file:5} 從第6個字符開始,截取后面所有的字符
{file:0-5} 從倒數第5個字符開始,截取后面所有的字符{file:0-6:3} 從倒數第6個字符開始,截取之后的3個字符

默認值相關
場景一:
變量a如果有內容,那么就輸出a的變量值
變量a如果沒有內容,那么就輸出默認的內容

格式:
    ${變量名:-默認值}

套餐示例:
    如果我輸入的參數為空,那么輸出內容是 "您選擇的套餐是: 套餐 1"
    如果我輸入的參數為n,那么輸出內容是 "您選擇的套餐是: 套餐 n"  

!/bin/bash

套餐選擇演示

a="1" echo "您選擇的套餐是: 套餐{a:-1}"

場景二:
無論變量a是否有內容,都輸出默認值
格式:
${變量名+默認值}
場景示例:
不管我說國家法定結婚年齡是 多少歲,都輸出 國家法定結婚年齡(男性)是 22 歲

!/bin/bash

默認值演示示例二

a="1" echo "國家法定結婚年齡(男性)是{a+22} 歲"


第 3 章 SHELL 進階
這部分的知識,我們主要是從三個方面來學習:
測試語句
表達式(條件+計算)
linux常見符號和命令
3.1 表達式
要使Shell腳本程序具備一定的“邏輯能力”,面臨的第一個問題就是:區分不同的情況以確定執行何種操作,下面我們就來學習解決這個問題---測試語句
3.1.1 測試語句
Shell環境根據命令執行后的返回狀態值($?)來判斷是否執行成功,當返回值為0,表示成功,值為其他時,表示失敗。使用專門的測試工具---test命令,可以對特定條件進行測試,并根據返回值來判斷條件是否成立(返回值0為成立)

測試語句形式
A: test 條件表達式
B: [ 條件表達式 ]
格式注意:
以上兩種方法的作用完全一樣,后者為常用。
但后者需要注意方括號[、]與條件表達式之間至少有一個空格。
test跟 [] 的意思一樣
條件成立,狀態返回值是0
條件不成立,狀態返回值是1

操作注意:
[]兩側為什么要有空格
root@ubuntu:~# [-x /bin/bash ]
[-x: command not found
可以看到:
兩側沒有空格,就會報錯,為什么呢?因為你不合規范

3.1.2 條件表達式
我們這部分內容主要是介紹,測試語句中的 [ 條件表達式 ] 這一部分,測試的結果使用 echo $? 來查看

邏輯表達式
邏輯表達式一般用于判斷多個條件之間的依賴關系。
常見的邏輯表達式有: && 和 ||

&&
命令1 && 命令2
如果命令1執行成功,那么我才執行命令2 -- 夫唱婦隨
如果命令1執行失敗,那么命令2也不執行
示例:

[ 1 = 1 ] && echo "條件成立"

條件成立

[ 1 = 2 ] && echo "條件成立"

||
命令1 || 命令2
如果命令1執行成功,那么命令2不執行 -- 對著干
如果命令1執行失敗,那么命令2執行
示例:

[ 1 = 2 ] || echo "條件不成立"

條件不成立

[ 1 = 1 ] || echo "條件不成立"

文件表達式

-f 判斷輸入內容是否是一個文件
示例:

[ -f weizhi.sh ] && echo "是一個文件"

是一個文件

[ -f weizhi.sddh ] || echo "不是一個文件"

不是一個文件

-d 判斷輸入內容是否是一個目錄
示例:

[ -d weizhi.sddh ] || echo "不是一個目錄"

不是一個目錄

mkdir nihao

[ -d nihao ] && echo "是一個目錄"

是一個目錄

-x 判斷輸入內容是否可執行
示例:

[ -x age.sh ] || echo "文件沒有執行權限"

文件沒有執行權限

[ -x test.sh ] && echo "文件有執行權限"

文件有執行權限

數值操作符

主要根據給定的兩個值,判斷第一個與第二個數的關系,如是否大于、小于、等于第二個數。常見選項如下:
n1 -eq n2 相等
n1 -gt n2 大于
n1 -lt n2 小于
n1 -ne n2 不等于

字符串比較

str1 == str2 str1和str2字符串內容一致
str1 != str2 str1和str2字符串內容不一致,!表示相反的意思
實踐
判斷字符是否內容一致
root@ubuntu:~# [ a == a ]
root@ubuntu:~# echo ? 0 root@ubuntu:~# [ a != a ] root@ubuntu:~# echo?
1


3.1.3 計算表達式
定義:
計算表達式,簡單來說就是對具體的內容進行算數計算

格式:
方式一:
(())(( 計算表達式 ))
方式二:
let let 計算表達式

注意:
$(())中只能用+-*/和()運算符,并且只能做整數運算

(())演示效果 格式:a=((變量名a+1))
注意:
表達式范圍內,空格不限制
計算示例
root@ubuntu:~# echo $((100/5))
20

let演示效果
格式:let 變量名a=變量名a+1
注意:
表達式必須是一個整體,中間不能出現空格等特殊字符
let示例
root@ubuntu:~# i=1
root@ubuntu:~# let i=i+7
root@ubuntu:~# echo $i
8
3.2 linux常見符號
接下來我們來介紹幾個linux的場景符號:
重定向符號、管道符、其他符號
3.2.1 重定向符號
在shell腳本中有兩種常見的重定向符號 > 和 >>

符號
作用:
表示將符號左側的內容,以覆蓋的方式輸入到右側文件中
演示:
查看文件內容
admin-1@ubuntu:~cat file.txt nihao 使用重定向符號給文件中增加內容 admin-1@ubuntu:~ echo "file1.txt" > file.txt
再次查看文件內容
admin-1@ubuntu:~$ cat file.txt
file1.txt

符號
作用:
表示將符號左側的內容,以追加的方式輸入到右側文件的末尾行中
演示:
查看文件內容
admin-1@ubuntu:~cat file.txt file1.txt 使用重定向符號給文件中增加內容 admin-1@ubuntu:~ echo "file2.txt" >> file.txt
再次查看文件內容
admin-1@ubuntu:~$ cat file.txt
file1.txt
file2.txt

3.2.2 管道符 |
定義:
| 這個就是管道符,傳遞信息使用的

使用格式:
命令1 | 命令2
管道符左側命令1 執行后的結果,傳遞給管道符右側的命令2使用

命令演示:
查看當前系統中的全局變量SHELL
admin-1@ubuntu:~$ env | grep SHELL
SHELL=/bin/bash

3.2.3 其他符號
后臺展示符號 &
定義:
& 就是將一個命令從前臺轉到后臺執行
使用格式:
命令 &
命令演示:
admin-1@ubuntu:~# sleep 4
界面卡住4秒后消失
admin-1@ubuntu:~# sleep 10 &
[1] 4198
admin-1@ubuntu:~# ps aux | grep sleep
root 4198 0.0 0.0 9032 808 pts/17 S 21:58 0:00 sleep 10
root 4200 0.0 0.0 15964 944 pts/17 S+ 21:58 0:00 grep --color=auto sleep

全部信息符號 2>&1
符號詳解:
1 表示正確輸出的信息
2 表示錯誤輸出的信息
2>&1 代表所有輸出的信息
符號示例
標準正確輸出示例
cat nihao.txt 1>> zhengque
標準錯誤輸出示例
dsfadsfadsfa 2>> errfile

綜合演練示例
腳本內容

!/bin/bash

echo '下一條錯誤命令'
dsfsafsafdsa
腳本執行效果
admin-1@ubuntu:~# bash ceshi.sh
下一條錯誤命令
ceshi.sh: line 3: dsfsafsafdsa: command not found
1 和 2 綜合演練
admin-1@ubuntu:~# bash ceshi.sh 1>> ceshi-ok 2>> ceshi-err
admin-1@ubuntu:~# cat ceshi-ok
下一條錯誤命令
admin-1@ubuntu:~# cat ceshi-err
ceshi.sh: line 3: dsfsafsafdsa: command not found
全部信息演練
admin-1@ubuntu:~# bash ceshi.sh >> ceshi-all 2>&1
admin-1@ubuntu:~# cat ceshi-all
下一條錯誤命令
ceshi.sh: line 3: dsfsafsafdsa: command not found

linux系統垃圾桶
/dev/null 是linux下的一個設備文件,
這個文件類似于一個垃圾桶,特點是:容量無限大

3.3 常見命令詳解
接下來我們介紹一些shell腳本中經常使用的linux命令:grep、sed、awk、find
3.3.1 grep命令詳解
grep命令是我們常用的一個強大的文本搜索命令。
命令格式詳解
grep [參數] [關鍵字] <文件名>
注意:
我們在查看某個文件的內容的時候,是需要有<文件名>
grep命令在結合|(管道符)使用的情況下,后面的<文件名>是沒有的
可以通過 grep --help 查看grep的幫助信息
參數詳解
-c:只輸出匹配行的計數。
-n:顯示匹配行及行號。
-v:顯示不包含匹配文本的所有行。

模板文件
admin-1@ubuntu:~cat find.txt nihao aaa nihao AAA NiHao bbb nihao CCC -c: 輸出匹配到aaa的個數 admin-1@ubuntu:~ grep -c aaa find.txt
1
-n: 輸出匹配內容,同時顯示行號
admin-1@ubuntu:~grep -n CCC find.txt 4:nihao CCC -v: 匹配到的內容部輸出,輸出不匹配的內容 admin-1@ubuntu:~ grep -v ni find.txt
NiHao bbb
小技巧:
精確定位錯誤代碼
grep -nr [錯誤關鍵字] *


3.3.2 sed命令詳解
sed 行文件編輯工具。因為它編輯文件是以行為單位的。
命令格式詳解

命令格式:
sed [參數] '<匹配條件> [動作]' [文件名]
注意:
可以通過 sed --help 查看grep的幫助信息
參數詳解:
參數為空 表示sed的操作效果,實際上不對文件進行編輯
-i 表示對文件進行編輯
注意:mac版本的bash中使用 -i參數,必須在后面單獨加個東西: -i ''

匹配條件:
匹配條件分為兩種:數字行號或者關鍵字匹配
關鍵字匹配格式:
'/關鍵字/'
注意:
隔離符號 / 可以更換成 @、#、!等符號
根據情況使用,如果關鍵字和隔離符號有沖突,就更換成其他的符號即可。

動作詳解
-a 在匹配到的內容下一行增加內容
-i 在匹配到的內容上一行增加內容
-d 刪除匹配到的內容
-s 替換匹配到的內容
注意:
上面的動作應該在參數為-i的時候使用,不然的話不會有效果
替換命令演示
關于替換,我們從三個方面來學習:
行號、列號、全體
命令格式:
sed -i [替換格式] [文件名]
注意:替換命令的寫法
's###' ---> 's#原內容##' ---> 's#原內容#替換后內容#'

常見替換格式:
模板文件內容
admin-1@ubuntu:~$ cat sed.txt
nihao sed sed sed
nihao sed sed sed
nihao sed sed sed

替換每行首個匹配內容:
sed -i 's#原內容#替換后內容#' 文件名

示例:替換首每行的第1個sed為SED
admin-1@ubuntu:~sed -i 's#sed#SED#' sed.txt admin-1@ubuntu:~ cat sed.txt
nihao SED sed sed
nihao SED sed sed
nihao SED sed sed

替換全部匹配內容:
sed -i 's#原內容#替換后內容#g' 文件名

示例:替換全部sed為des
admin-1@ubuntu:~sed -i 's#sed#SED#g' sed.txt admin-1@ubuntu:~ cat sed.txt
nihao SED SED SED
nihao SED SED SED
nihao SED SED SED

指定行號替換首個匹配內容:
sed -i '行號s#原內容#替換后內容#' 文件名

示例:替換第2行的首個SED為sed
admin-1@ubuntu:~sed -i '2s#SED#sed#' sed.txt admin-1@ubuntu:~ cat sed.txt
nihao SED SED SED
nihao sed SED SED
nihao SED SED SED

首行指定列號替換匹配內容:
sed -i 's#原內容#替換后內容#列號' 文件名

示例:替換每行的第2個SED為sed
admin-1@ubuntu:~sed -i 's#SED#sed#2' sed.txt admin-1@ubuntu:~ cat sed.txt
nihao SED sed SED
nihao sed SED sed
nihao SED sed SED

指定行號列號匹配內容:
sed -i '行號s#原內容#替換后內容#列號' 文件名

示例:替換第3行的第2個SED為sed
admin-1@ubuntu:~sed -i '3s#SED#sed#2' sed.txt admin-1@ubuntu:~ cat sed.txt
nihao SED sed SED
nihao sed SED sed
nihao SED sed sed

增加操作

作用:
在指定行號的下一行增加內容
格式:
sed -i '行號a\增加的內容' 文件名
注意:
如果增加多行,可以在行號位置寫個范圍值,彼此間使用逗號隔開,例如
sed -i '1,3a\增加內容' 文件名

演示效果:
指定行號增加內容
admin-1@ubuntu:~sed -i '2a\zengjia-2' sed.txt admin-1@ubuntu:~ cat sed.txt
nihao SED sed SED
nihao sed SED sed
zengjia-2
nihao SED sed sed
指定1~3每行都增加內容
admin-1@ubuntu:~sed -i '1,3a\tongshi-2' sed.txt admin-1@ubuntu:~ cat sed.txt
nihao SED sed SED
tongshi-2
nihao sed SED sed
tongshi-2
zengjia-2
tongshi-2
nihao SED sed sed

作用:
在指定行號的當行增加內容
格式:
sed -i '行號i\增加的內容' 文件名
注意:
如果增加多行,可以在行號位置寫個范圍值,彼此間使用逗號隔開,例如
sed -i '1,3a\增加內容' 文件名

演示效果:
指定行號增加內容
admin-1@ubuntu:~sed -i '1i\insert-1' sed.txt admin-1@ubuntu:~ cat sed.txt
insert-1
nihao SED sed SED
tongshi-2
nihao sed SED sed
tongshi-2
zengjia-2
tongshi-2
nihao SED sed sed

刪除操作

作用:
指定行號刪除
格式:
sed -i '行號d' 文件名
注意:
如果刪除多行,可以在行號位置多寫幾個行號,彼此間使用逗號隔開,例如
sed -i '1,3d' 文件名

刪除演練
刪除第4行內容
admin-1@ubuntu:~sed -i '4d' sed.txt admin-1@ubuntu:~ cat sed.txt
insert-1
nihao SED sed SED
tongshi-2
tongshi-2
zengjia-2
tongshi-2
nihao SED sed sed

刪除多行(3-5行)內容
admin-1@ubuntu:~sed -i '3,5d' sed.txt admin-1@ubuntu:~ cat sed.txt
insert-1
nihao SED sed SED
tongshi-2
nihao SED sed sed


3.3.3 awk命令詳解
awk是一個功能非常強大的文檔編輯工具,它不僅能以行為單位還能以列為單位處理文件。
命令格式:
awk [參數] '[ 動作]' [文件名]

常見參數:
-F 指定行的分隔符

常見動作:
print 顯示內容
0 顯示當前行所有內容n 顯示當前行的第n列內容,如果存在多個$n,它們之間使用逗號(,)隔開

常見內置變量
FILENAME 當前輸入文件的文件名,該變量是只讀的
NR 指定顯示行的行號
NF 輸出 最后一列的內容
OFS 輸出格式的列分隔符,缺省是空格
FS 輸入文件的列分融符,缺省是連續的空格和Tab

命令演示
模板文件內容
admin-1@ubuntu:~$ cat awk.txt
nihao awk awk awk
nihao awk awk awk

打印指定列內容
打印第1列的內容
admin-1@ubuntu:~awk '{print1}' awk.txt
nihao
nihao

指定行打印內容
打印第一行第1和第3列內容
admin-1@ubuntu:~awk 'NR==1 {print1,$3}' awk.txt
nihao awk

指定隔離分隔符,查看內容
admin-1@ubuntu:~cat linshi.txt root:x:0:0:root:/root:/bin/bash admin-1@ubuntu:~ awk -F ':' '{print 1,7}' linshi.txt
root /bin/bash

設置顯示分隔符,顯示內容
admin-1@ubuntu:~awk 'BEGIN{OFS=":"} {print NR,0}' awk.txt
1:nihao awk awk awk
2:nihao awk awk awk
3.3.4 find命令詳解
命令格式:
find [路徑] [參數] [關鍵字]
參數詳解
-name 按照文件名查找文件。
-perm 按照文件權限來查找文件。
-user 按照文件屬主來查找文件。
-group 按照文件所屬的組來查找文件。
-type 查找某一類型的文件,
諸如:
b - 塊設備文件 d - 目錄 c - 字符設備文件
p - 管道文件 l - 符號鏈接文件 f - 普通文件。
-size n:[c] 查找文件長度為n塊的文件,帶有c時表示文件長度以字節計。
-depth:在查找文件時,首先查找當前目錄中的文件,然后再在其子目錄中查找。
-mindepth n:在查找文件時,查找當前目錄中的第n層目錄的文件,然后再在其子目錄中查找。
! : 表示取反

命令演示
在當前系統中查找一個叫awk的文件
admin-1@ubuntu:~sudo find /home/admin-1/ -name "awk.txt" /home/admin-1/awk.txt 在當前系統中查找文件類型為普通文件的文件 admin-1@ubuntu:~ find /tmp -type f
/tmp/.X0-lock
/tmp/vgauthsvclog.txt.0
/tmp/unity_support_test.0
/tmp/config-err-4igbXW


第4章 流程控制
在shell的語句中,流程控制主要分為兩種:
簡單流程控制語句:選擇和循環
復雜流程控制語句:函數
4.1 簡單流程控制語句
4.1.1 單分支if語句
語法格式
if [ 條件 ]
then
指令
fi

場景:
單一條件,只有一個輸出

單分支if語句示例

!/bin/bash

單if語句的使用場景

if [ "$1" == "nan" ]
then
echo "您的性別是 男"
fi

4.1.2 雙分支if語句
語法格式
if [ 條件 ]
then
指令1
else
指令2
fi
場景:
一個條件,兩種結果

雙分支if語句示例

!/bin/bash

單if語句的使用場景

if [ "$1" == "nan" ]
then
echo "您的性別是 男"
else
echo "您的性別是 女"
fi
4.1.3 多分支if語句
語法格式
if [ 條件 ]
then
指令1
elif [ 條件2 ]
then
指令2
else
指令3
fi
場景:
n個條件,n+1個結果

多分支if語句示例

!/bin/bash

單if語句的使用場景

if [ "1" == "nan" ] then echo "您的性別是 男" elif [ "1" == "nv" ]
then
echo "您的性別是 女"
else
echo "您的性別,我不知道"
fi


多if語句生產場景: 服務的啟動
需求:
要求腳本執行需要有參數,通過傳入參數來實現不同的功能。

參數和功能詳情如下:
參數 執行效果
start 服務啟動中...
stop 服務關閉中...
restart 服務重啟中...
* 腳本 X.sh 使用方式 X.sh [ start|stop|restart ]

腳本內容
admin-1@ubuntu:/data/scripts/python-n# cat if.sh

!/bin/bash

多if語句的使用場景

if [ "1" == "start" ] then echo "服務啟動中..." elif [ "1" == "stop" ]
then
echo "服務關閉中..."
elif [ "1" == "restart" ] then echo "服務重啟中..." else echo "0 腳本的使用方式: $0 [ start | stop | restart ]"
fi

4.1.4 case選擇語句
我們發現多if語句使用的時候,代碼量很多,而且整體看起來確實有那么一丁點亂,有沒有辦法更好的實現這種效果呢?就是Case語句。

case 語句格式
case 變量名 in
值1)
指令1
;;
值2)
指令2
;;
值3)
指令3
;;
esac
注意:
首行關鍵字是case,末行關鍵字esac
選擇項后面都有 )
每個選擇的執行語句結尾都有兩個分號;

case語句示例
場景:在多if語句的基礎上對腳本進行升級
需求:
要求腳本執行需要有參數,通過傳入參數來實現不同的功能。

參數和功能詳情如下:
參數 執行效果
start 服務啟動中...
stop 服務關閉中...
restart 服務重啟中...
* 腳本 X.sh 使用方式 X.sh [ start|stop|restart ]

腳本內容:

cat case.sh

!/bin/bash

case語句使用場景

case "1" in "start") echo "服務啟動中..." ;; "stop") echo "服務關閉中..." ;; "restart") echo "服務重啟中..." ;; *) echo "0 腳本的使用方式: $0 [ start | stop | restart ]"
;;
esac


4.1.5 for循環語句
循環指定的所有元素,循環完畢之后就推出
語法格式
語法格式
for 值 in 列表
do
執行語句
done

場景:
遍歷列表

注意:
”for” 循環總是接收 “in” 語句之后的某種類型的字列表
執行次數和list列表中常數或字符串的個數相同,當循環的數量足夠了,就自動退出

示例:遍歷文件

!/bin/bash

for語句的使用示例

for i in (ls /root) do echo "{i}"
done

4.1.6 while循環語句
語法格式
while 條件
do
執行語句
done
注意:
條件的類型:
命令、[[ 字符串表達式 ]]、(( 數字表達式 ))

場景:
只要條件滿足,就一直循環下去

while語句示例
腳本內容

!/bin/bash

while的示例

a=1
while [ "{a}" -lt 5 ] do echo "{a}"
a=$((a+1))
done

4.1.7 until循環語句
語法格式
until 條件
do
執行語句
done
注意:
條件的類型:
命令、[[ 字符串表達式 ]]、(( 數字表達式 ))

場景:
只要條件不滿足,就一直循環下去

until語句示例
腳本內容

!/bin/bash

until的示例

a=1
until [ "{a}" -eq 5 ] do echo "{a}"
a=$((a+1))
done


4.2 復雜流程控制語句
函數就是我們的復雜流程控制語句
4.2.1 函數基礎知識
函數是什么?
函數就是將某些命令組合起來實現某一特殊功能的方式,是腳本編寫中非常重要的一部分。
簡單函數格式:
定義函數:
函數名(){
函數體
}
調用函數:
函數名

傳參函數格式:
傳參數
函數名 參數
函數體調用參數:
函數名(){
函數體 $n
}
注意:
類似于shell內置變量中的位置參數
4.2.2 函數實踐
簡單函數定義和調用示例

!/bin/bash

函數使用場景一:執行頻繁的命令

dayin(){
echo "wo de mingzi shi 111"
}
dayin

函數傳參和函數體內調用參數示例

!/bin/bash

函數的使用場景二

dayin(){
echo "wo de mingzi shi $1"
}
dayin 111

函數調用腳本傳參

!/bin/bash

函數傳參演示

定義傳參數函數

dayin(){
echo "wode mignzi shi $1"
}

函數傳參

dayin $1
腳本傳多參,函數分別調用示例

!/bin/bash

函數的使用場景二

dayin(){
echo "wo de mingzi shi 1" echo "wo de mingzi shi2"
echo "wo de mingzi shi $3"
}
dayin 111 df dfs


4.3 第一階段綜合案例
需求
1、zonghe.sh 腳本執行時候需要添加參數才能執行
參數和功能詳情如下:
參數 執行效果
start 服務啟動中...
stop 服務關閉中...
restart 服務重啟中...
* 腳本幫助信息...
2、參數的數量有限制,只能是1個,多余一個會提示腳本的幫助信息
3、幫助信息使用函數來實現
信息內容:腳本 zonghe.sh 使用方式 zonghe.sh [ start|stop|restart ]
知識點分析:
1、zonghe.sh 腳本執行時候需要添加參數才能執行
腳本傳參、case語句
2、參數的數量有限制,只能是1個,多余一個會提示腳本的幫助信息
參數數量、條件表達式(驗證+數字)、if語句
3、幫助信息使用函數來實現
函數定義+調用
4、if語句和case語句嵌套
if語句在外,case語句在內
腳本編寫流程:
1、先寫主流程框架
2、完善函數功能
3、完善需求功能
代碼實踐

!/bin/bash

定義本地變量

arg="$1"

腳本幫助信息

usage(){
echo "腳本 0 的使用方式是:0 [ start|stop|restart ]"
}

函數主框架

if [ # -eq 1 ] then case "{arg}" in
start)
echo "服務啟動中..."
;;
stop)
echo "服務關閉中..."
;;
restart)
echo "服務重啟中..."
;;
*)
usage
;;
esac
else
usage
fi
第 5 章 代碼發布
5.1 代碼發布簡介
到現在為止我們學會了多個開發項目案例,也知道工作中如何做一個項目,但是一個項目方案的如何部署到公司的線上服務器上,部署過程中都會經歷哪些事情呢?接下來我們好好的來梳理一下。
5.1.1 代碼發布介紹
什么是代碼發布?
代碼發布就是一句話:將我們的代碼放到一臺公司的互聯網服務器上。
那么我們應該怎么來理解這句話呢?我們從三個方面來理解他。

如何理解這句話?
發布什么?
代碼 經過測試,功能完善,沒有問題的代碼
發布到哪里?
服務器 所有人都能訪問的到的一臺服務器(有公網IP)
idc機房、阿里云、亞馬遜、騰訊云、華為云、....
發布的效果?
web網頁對外展示

5.1.2 發布方式
常見的代碼發布方式有兩種:手工方式和腳本方式。
這兩種方式有什么區別呢?我們接下來好好的對比分析一下。

手工發布代碼 步行

干擾因素多
不安全

腳本發布代碼 坐車

干擾因素少
安全
5.2 代碼發布流程
5.2.1 流程簡介
接下來我們來好好的說一下部署的流程:


注: 大型腳本流程
5.2.2 流程詳解
接下來我們來對每個過程進行一個仔細的敘述
部署場景:
兩臺主機做部署動作

注意:
部署的文件就是兩臺主機右上角的紅色內容

獲取代碼

代碼倉庫
    集中式的:   svn
    分布式的:   git

區別:
svn的幾乎所有操作命令,都集中在我和代碼倉庫服務器處于網絡連接狀態。
git的幾乎所有操作命令,可以在本地完成,和代碼倉庫服務器是否連接無關。

公司的代碼倉庫:
    私有倉庫    gitlab
        內部服務器或者公網服務器
        
倉庫權限
    只有項目的開發人員才有權限,項目之外的人沒有權限
    
代碼權限:
    開發、管理、查看
    
提交的方式:
    代碼版本號

打包代碼
場景演示:

目的:
    減少傳輸文件數量
    減小傳輸文件大小
    增強傳輸速率
    
常見打包方式:
    windows:
        zip、rar...
    linux:
        tar、zip...

傳輸代碼
場景效果:

傳輸方式:
    有網情況下

多種方式:
git、ftp、scp、共享掛載 cp、rsync
沒有網情況下
物理方式:
U盤或者硬盤
關閉應用
代碼所在的服務用到了什么應用,就關閉什么應用
關閉的順序:
先關閉離客戶近的,后關閉離客戶遠的

解壓代碼:
tar xf ...

放置代碼
為了避免我們在放置代碼過程中,對老文件造成影響,所以我們放置代碼一般分為兩步:備份老文件和放置新文件。
備份原文件

    放置新文件

注意:
    兩個文件的名稱是一樣的,只是內容不同
    對整個應用項目來說,兩個文件沒有區別

開啟應用
剛才關閉了什么應用就開啟什么應用
開啟的順序:
先開啟離客戶遠的,后開啟離客戶近的

檢查
查看瀏覽器效果或者netstat -tnulp查看系統開放的端口


5.2.3 技術關鍵點
文件的壓縮和解壓
文件的壓縮
壓縮格式:
tar zcvf 壓縮后的文件名 將要壓縮的文件
文件的解壓
解壓格式:
tar xf 壓縮后的文件名

命令參數詳解
z 指定壓縮文件的格式為 tar.gz
c 表示壓縮
v 顯示詳細過程
f 指定壓縮文件
x 解壓

查看壓縮文件內容
zcat 壓縮文件

文件的傳輸
scp傳輸工具:
命令格式:
scp 要傳輸的文件 要放置的位置

    將本地文件推送到遠程主機
        scp python.tar.gz root@192.168.8.15:/root/
    將遠程主機的文件拉取到本地
        scp root@192.168.8.15:/root/python.tar.gz ./

遠端主機文件放置位置的表示形式:
遠程連接的用戶@遠程主機:遠程主機的目錄路徑
遠端主機文件位置的表示形式:
遠程連接的用戶@遠程主機:遠程主機的文件路徑

文件的備份
文件的備份要有一定的標志符號,我們就使用目前通用的時間戳的形式來表示

date命令詳解:
命令格式:date [option]
常見參數:
%F 顯示當前日期格式,%Y-%m-%d
%T 顯示當前時間格式,%H:%M:%S

演示效果:
顯示當前日期

date +%F

2017-09-28
顯示當前時間

date +%T

03:06:30

根據上面的參數介紹,我們可以指定命令顯示的格式,
年月日:date +%Y%m%d
時分秒:date +%H%M%S

演示效果:
顯示當前日期

date +%Y%m%d

20170928
顯示當前時間

date +%H%M%S

030643

指定時間戳格式:
年月日時分秒:date +%Y%m%d%H%M%S

時間戳演示效果:
指定的時間戳格式

date +%Y%m%d%H%M%S

20170928030742

備份命令效果格式:
方式一:復制備份
cp nihao nihao-(date +%Y%m%d%H%M%S) 方式二:移動備份 mv nihao nihao-(date +%Y%m%d%H%M%S)
我們為了避免在放置新文件時候,出現驗證操作,我們確定采用方式二:


練習案例:
1、在主機1上創建一個目錄/data/tar-ceshi/,在目錄里面創建兩個文件,內容分別如下:
文件名 內容
file1.txt file1
file2.txt file2
2、對目錄tar-ceshi進行壓縮
3、對目錄tar-ceshi進行時間戳備份
4、將壓縮包文件傳輸到遠端主機2
5、在主機2上解壓 壓縮包文件
6、在主機2上修改壓縮包文件內容。然后再次壓縮
7、在主機1上拉取主機2的壓縮包文件
8、使用命令查看壓縮包文件的內容
命令執行效果:
主機1操作命令
1、
mkdir /data/tar-ceshi -p
cd /data
echo 'file1' > tar-ceshi/file1.txt
echo 'file1' > tar-ceshi/file1.txt
2、tar zcvf tar-ceshi.tar.gz tar-ceshi
3、mv tar-ceshi tar-ceshi-$(date +%Y%m%d%H%M%S)
4、scp tar-ceshi.tar.gz root@192.168.8.15:/tmp
主機2操作命令
5、
cd /tmp
tar xf tar-ceshi.tar.gz
6、
echo 'file3' >> tar-ceshi/file1.txt
tar zcvf tar-ceshi-1.tar.gz tar-ceshi
主機1操作命令
7、scp root@192.168.8.15:/tmp/tar-ceshi-1.tar.gz ./
8、zcat tar-ceshi-1.tar.gz
第 6 章 環境部署
環境部署這塊,我們需要有一個項目的基礎環境,然后在這個基礎環境上,再根據項目需求搭建一個能讓項目代碼正常運行的環境。所以這塊的知識,我們從三個方面來學習
基礎環境
方案分析
項目環境部署
6.1 基礎環境
6.1.1 基礎目錄環境
創建基本目錄

mkdir /data/{server,logs,backup,softs,virtual,scripts,codes} -p

ls /data/

backup logs scripts server softs virtual codes
查看
admin-1@ubuntu:/data# tree -L 1 /data/
/data/
├── backup 備份
├── codes 代碼
├── logs 日志
├── scripts 腳本
├── server 服務
├── softs 軟件
└── virtual 虛擬環境
6.1.2 主機網絡環境
問題:
我們上面進行文件傳輸的時候,發現一個問題,每次進行文件傳輸都需要進行密碼驗證,這對我們來說,有些一丁點不舒服,那么有沒有辦法,讓我痛苦一點?
答案就是:主機間免密碼認證

知識點:
什么是主機間免密碼認證?
就是我和另外一臺主機做任何事情,不需要輸入密碼認證,非常很方便。

方案詳解
我們要做主機間免密碼認證需要做三個動作
1、本機生成密鑰對
2、對端機器使用公鑰文件認證
3、驗證

方案實施
1、生成秘鑰對
ssh-keygen -t rsa
-t 指定秘鑰的類型
rsa 秘鑰類型

        秘鑰目錄:/root/.ssh/
            私鑰      id_rsa                  鑰匙
            公鑰      id_rsa.pub          鎖
            
    2、編輯認證文件
        admin-1@ubuntu:~/.ssh# cat /root/.ssh/authorized_keys 
        ssh-rsa AAAAB3N...PVp admin-1@ubuntu
        注意:
            認證文件內容和8.15機器的公鑰文件內容一致
            保證文件內容是一整行
            
    3、編輯ssh配置文件
        admin-1@ubuntu:~/.ssh# cat /etc/ssh/sshd_config
        ...
            AuthorizedKeysFile  %h/.ssh/authorized_keys
        注意: 
            直接取消該行的注釋即可
            
    4、配置文件生效
        重啟ssh服務
        /etc/init.d/ssh restart
        
    5、驗證操作
        ssh root@192.168.8.15
        
    1和5是在8.14上操作
    2-4是在8.15上操作

6.2 方案分析
6.2.1 需求
需求:
部署一個環境,支持我們的django項目正常運行
6.2.2 需求分析
分析:
2、python環境 ---> 3、python虛擬環境
1、django環境部署
4、django軟件安裝
5、項目基本操作
6、應用基本操作
7、view和url配置
8、問題:只有本機能訪問
9、方案代理---- 10、nginx
11、nginx實現代理
13、pcre軟件安裝
12、nginx軟件安裝
14、nginx基本操作
15、nginx代理的配置
16、目錄結構
17、查看配置文件
18、找到對應的代理配置項
19、啟動django
20、啟動nginx
21、整個項目調試
6.2.3 部署方案
環境部署方案
一、django環境部署
1.1 python虛擬環境
1.2 django環境部署
1.2.1 django軟件安裝
1.2.2 項目基本操作
1.2.3 應用基本操作
1.2.4 view和url配置
二、nginx代理django
2.1 nginx軟件安裝
2.1.1 pcre軟件安裝
2.1.2 nginx軟件安裝
2.1.3 nginx基本操作
2.2 nginx代理配置
2.2.1 目錄結構查看
2.2.2 配置文件查看
2.2.3 編輯代理配置項
三、項目調試
3.1 啟動軟件
3.1.1 啟動django
3.1.2 啟動nginx
3.2 整個項目調試

6.3 項目環境部署
6.3.1 python虛擬環境
軟件安裝
安裝虛擬環境軟件
apt-get install python-virtualenv -y
虛擬環境基本操作
創建
virtualenv -p /usr/bin/python3.5 venv
進入
source venv/bin/activate
退出
deactivate
刪除
rm -rf venv
6.3.2 django環境
django軟件安裝
注意:先進入虛擬環境
解壓
cd /data/soft
tar xf Django-1.10.7.tar.gz
查看
cd Django-1.10.7
cat INSTALL or README
安裝
python setup.py install

拓展知識點:
python類型軟件的安裝流程
普通:
解壓 安裝
特殊:
解壓 編譯 安裝

        編譯:python setup.py build

django項目操作
創建項目
cd /data/server
django-admin startproject itcast
django應用操作
創建應用
cd /data/server/itcast
python manage.py startapp test1
注冊應用

vim itcast/settings.py

INSTALL_APP = [
。。。
'test1',
]
view和url配置
需求:
訪問django的頁面請求為:127.0.0.1:8000/hello/,頁面返回效果為:itcast v1.0
分析:
views文件定制邏輯流程函數
urls文件定制路由跳轉功能

view 配置文件生效

admin-1@ubuntu:/data/soft# cat /data/server/itcast/test1/views.py
from django.shortcuts import render
from django.http import HttpResponse

Create your views here.

def hello(resquest):
return HttpResponse("itcast V1.0")

url文件配置

admin-1@ubuntu:/data/soft# cat /data/server/itcast/itcast/urls.py
...
from test1.views import *

urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^hello/$', hello),
]

啟動django:

cd /data/server/itcast
python manage.py runserver


6.3.3 nginx環境
pcre軟件安裝
解壓
cd /data/soft/
tar xf pcre-8.39.tar.gz
查看幫助
cd pcre-8.39
INSTALL 或者 README
配置
./configure
編譯
make
安裝
make install

拓展知識點:
linux中軟件安裝的一般流程
解壓
tar
解壓文件,獲取真正的配置文件
配置
configure
根據默認的配置項或者更改配置項,生成編譯配置文件(Makefile)
編譯
make
根據 Makefile 內容,編譯生成指定的軟件所需要的所有文件
安裝
make install
將編譯生成的所有文件,轉移到軟件指定安裝的目錄下面
--prefix
nginx軟件安裝
解壓
cd /data/soft/
tar xf nginx-1.10.2.tar.gz
配置
cd nginx-1.10.2/
./configure --prefix=/data/server/nginx --without-http_gzip_module
編譯
make
安裝
make install

nginx簡單操作
檢查
/data/server/nginx/sbin/nginx -t
開啟
/data/server/nginx/sbin/nginx
關閉
/data/server/nginx/sbin/nginx -s stop
重載
/data/server/nginx/sbin/nginx -s reload

常見問題
突發問題:
admin-1@ubuntu:/data/server/nginx# ./sbin/nginx -t
./sbin/nginx: error while loading shared libraries: libpcre.so.1: cannot open shared object file: No such file or directory

    分析:
        1、先看報錯
        2、思考,是否報錯真實有效
            分析: 誰錯了
            
        3、查找文件
            全名找不到,我們使用正則
        4、找到文件,我沒有問題
            nginx默認找庫文件的路徑有問題
        5、解決

解決:
admin-1@ubuntu:/data/soft/nginx-1.10.2# ldd /data/server/nginx/sbin/nginx
linux-vdso.so.1 => (0x00007ffdb9154000)
libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007fa59379b000)
libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007fa59357e000)
libcrypt.so.1 => /lib/x86_64-linux-gnu/libcrypt.so.1 (0x00007fa593345000)
libpcre.so.1 => not found
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fa592f7c000)
/lib64/ld-linux-x86-64.so.2 (0x0000564bfef41000)
查找文件:
admin-1@ubuntu:/data/soft/nginx-1.10.2# find / -name "libpcre.so.1"
/data/soft/pcre-8.39/.libs/libpcre.so.1
/usr/local/lib/libpcre.so.1
...
鏈接該文件
admin-1@ubuntu:/data/soft/nginx-1.10.2# ln -s /usr/local/lib/libpcre.so.1 /lib/x86_64-linux-gnu/
再次檢查一下nginx的配置文件
admin-1@ubuntu:/data/soft/nginx-1.10.2# /data/server/nginx/sbin/nginx -t
nginx: the configuration file /data/server/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /data/server/nginx/conf/nginx.conf test is successful


6.3.4 nginx代理django
nginx配置簡介
nginx的目錄結構
admin-1@ubuntu:/data/server/nginx# tree -L 2 /data/server/nginx/
/data/server/nginx/
├── ...
├── conf 配置文件目錄
│ ...
│ ├── nginx.conf 默認的配置文件
│ ...
├── ...
├── html 網頁文件
│ ├── 50x.html
│ └── index.html
├── logs 日志目錄
│ ├── access.log
│ └── error.log
├── ...
├── sbin 執行文件目錄
│ └── nginx
├── ...

nginx配置文件介紹
全局配置段
http配置段
server配置段 項目或者應用
location配置段 url配置

nginx代理配置
案例需求:
訪問地址 192.168.8.14/hello/ 跳轉到 127.0.0.1:8000/hello/的django服務來處理hello請求

代理是什么?
哥,這事交給我就行了,您就甭操心了。
編輯配置文件實現代理功能
配置內容
62: location /hello/ {
63: proxy_pass http://127.0.0.1:8000;
64: }
注釋:
當我訪問地址是
配置文件生效
/data/server/nginx/sbin/nginx -t
/data/server/nginx/sbin/nginx -s reload


第 7 章 手工代碼發布
7.1 方案分析
發布需求:
手工方式部署代碼

發布方案:
    獲取代碼

sed -i 's#文件原始的內容#替換后的內容#g' 要更改到文件名

    打包代碼


    傳輸代碼

    關閉應用
    解壓代碼
    放置代碼
        備份老文件

        放置新文件

    開啟應用
    檢查

注意:
獲取代碼和打包代碼在代碼倉庫主機上進行操作
其他操作,都在線上服務器進行操作

7.2 方案實施
獲取代碼
mkdir /data/codes -p
cd /data/codes
sed -i 's#1.0#1.1#' django/views.py
sed -i 's#原內容#替換后內容#g' 文件

打包代碼
cd /data/codes/
tar zcf django.tar.gz django

注意:
前面兩步在代碼倉庫主機上操作

傳輸代碼
cd /data/codes/
scp root@192.168.8.15:/data/codes/django.tar.gz ./
關閉應用
關閉nginx應用
/data/server/nginx/sbin/nginx -s stop

關閉django應用
    根據端口查看進程號,
        lsof -Pti :8000
    殺死進程號
        kill 56502

一條命令搞定它:
kill $(lsof -Pti :8000)

解壓代碼
cd /data/codes
tar xf django.tar.gz

放置代碼
備份老文件
需求:備份的格式:
文件名-時間戳
時間戳:年月日時分秒
date +%Y%m%d%H%M%S
mv /data/server/itcast/test1/views.py /data/backup/views.py-$(date +%Y%m%d%H%M%S)
放置新文件
cd /data/codes
mv django/views.py /data/server/itcast/test1/

開啟應用
開啟django應用
source /data/virtual/venv/bin/activate
cd /data/server/itcast/
python manage.py runserver >> /dev/null 2>&1 &
deactivate
開啟nginx應用
/data/server/nginx/sbin/nginx

檢查
netstat -tnulp | grep ':80'


注: 大型腳本之命令填充
第 8 章 腳本發布代碼
關于腳本發布代碼部分呢,我們將這個代碼部署流程拆分成兩部分:簡單腳本(遠端主機上執行)和大型腳本(線上機器執行),這樣我們能從兩個方面來學習生產中的腳本如何編寫。首先來說簡單腳本的編寫
8.1 簡單腳本編寫
簡單腳本我們從四個方面來學習:
1、命令羅列實現功能
2、固定內容變量實現
3、功能函數實現
4、遠程執行命令
8.1.1 命令羅列
目的:
實現代碼倉庫主機上的操作命令功能即可

實現簡單的功能--- 簡單的命令羅列

!/bin/bash

功能:打包代碼

腳本名:tar_code.sh

作者:itcast

版本:V 0.1

聯系方式:www.itcast.cn

cd /data/codes
[ -f django.tar.gz ] && rm -f django.tar.gz
tar zcf django.tar.gz django
腳本編寫完成后,進行測試:
sed -i 's#1.1#1.2#' /data/codes/django/views.py
bash /data/scripts/tar_code.sh
查看壓縮文件內容
zcat django.tar.gz
8.1.2 固定內容變量化
問題:
腳本里面的手寫的固定的內容太多了,更改時候費勁

腳本優化之 固定內容變量化

!/bin/bash

功能:打包代碼

腳本名:tar_code.sh

作者:itcast

版本:V 0.2

聯系方式:www.itcast.cn

FILE='django.tar.gz'
CODE_DIR='/data/codes'
CODE_PRO='django'

cd "{CODE_DIR}" [ -f "{FILE}" ] && rm -f "{FILE}" tar zcf "{FILE}" "${CODE_PRO}"
腳本編寫完成后,進行測試:
sed -i 's#1.2#1.3#' /data/codes/django/views.py
bash /data/scripts/tar_code.sh
查看壓縮文件內容
zcat django.tar.gz
8.1.3 功能函數化
需求:
三條命令其實是一個組合,實現的是一個功能
腳本優化之 功能函數化

!/bin/bash

功能:打包代碼

腳本名:tar_code.sh

作者:itcast

版本:V 0.3

聯系方式:www.itcast.cn

FILE='django.tar.gz'
CODE_DIR='/data/codes'
CODE_PRO='django'

code_tar(){
cd "{CODE_DIR}" [ -f "{FILE}" ] && rm -f "{FILE}" tar zcf "{FILE}" "${CODE_PRO}"
}
code_tar
腳本編寫完成后,進行測試:
sed -i 's#1.2#1.3#' /data/codes/django/views.py
bash /data/scripts/tar_code.sh
查看壓縮文件內容
zcat /data/codes/django.tar.gz
8.1.4 遠程執行
遠程命令執行
格式:
ssh 遠程主機登錄用戶名@遠程主機ip地址 "執行命令"
效果
admin-1@ubuntu:/data/server/itcast# ssh root@192.168.8.15 "ifconfig eth0"
eth0 Link encap:Ethernet HWaddr 00:0c:29:f7:ca:d4
inet addr:192.168.8.15 Bcast:192.168.56.255 Mask:255.255.255.0
...

遠程執行腳本測試
遠程更新文件內容
ssh root@192.168.8.15 "sed -i /'s#1.4#1.5#' /data/codes/django/views.py"
遠程查看腳本
ssh root@192.168.8.15 "ls /data/scripts"
遠程執行腳本
ssh root@192.168.8.15 "/bin/bash /data/scripts/tar_code.sh"
遠程檢查更新效果
ssh root@192.168.8.15 "zcat /data/codes/django.tar.gz"
8.2 大型腳本編寫
本地是指線上服務器主機(192.168.8.14)
我們先來回顧一下代碼發布流程圖
編寫大型腳本有一個流程:
一、腳本框架
二、命令填充
三、完善功能
增加日志功能
增加鎖文件功能
增加主函數邏輯
增加參數安全措施

8.2.1 腳本框架
為什么?
1、命令多
2、功能多
3、不好組合

需求:
先將腳本所涉及的所有業務流程跑通

方案:
使用函數來體現

腳本實施:

!/bin/bash

功能:打包代碼

腳本名:deploy.sh

作者:itcast

版本:V 0.1

聯系方式:www.itcast.cn

獲取代碼

get_code(){
echo "獲取代碼"
}

打包代碼

tar_code(){
echo "打包代碼"
}

傳輸代碼

scp_code(){
echo "傳輸代碼"
}

關閉應用

stop_serv(){
echo "關閉應用"
echo "關閉nginx應用"
echo "關閉django應用"
}

解壓代碼

untar_code(){
echo "解壓代碼"
}

放置代碼

fangzhi_code(){
echo "放置代碼"
echo "備份老文件"
echo "放置新文件"
}

開啟應用

start_serv(){
echo "開啟應用"
echo "開啟django應用"
echo "開啟nginx應用"
}

檢查

check(){
echo "檢查項目"
}

部署函數

deploy_pro(){
get_code
tar_code
scp_code
stop_serv
untar_code
fangzhi_code
start_serv
check
}

主函數

main(){
deploy_pro
}

執行主函數

main
8.2.2 命令填充
需求:
在流程跑通的情況下,執行完整的代碼部署過程
方案:
在腳本框架中,填寫執行成功的命令

腳本實施:

!/bin/bash

功能:打包代碼

腳本名:deploy.sh

作者:itcast

版本:V 0.2

聯系方式:www.itcast.cn

獲取代碼

get_code(){
echo "獲取代碼"
}

打包代碼

tar_code(){
echo "打包代碼"
ssh root@192.168.8.15 "/bin/bash /data/scripts/tar_code.sh"
}

傳輸代碼

scp_code(){
echo "傳輸代碼"
cd /data/codes
[ -f django.tar.gz ] && rm -f django.tar.gz
scp root@192.168.8.15:/data/codes/django.tar.gz ./
}

關閉應用

stop_serv(){
echo "關閉應用"
echo "關閉nginx應用"
/data/server/nginx/sbin/nginx -s stop
echo "關閉django應用"
kill $(lsof -Pti :8000)
}

解壓代碼

untar_code(){
echo "解壓代碼"
cd /data/codes
tar xf django.tar.gz
}

放置代碼

fangzhi_code(){
echo "放置代碼"
echo "備份老文件"
mv /data/server/itcast/test1/views.py /data/backup/views.py-$(date +%Y%m%d%H%M%S)
echo "放置新文件"
mv /data/codes/django/views.py /data/server/itcast/test1/
}

開啟應用

start_serv(){
echo "開啟應用"
echo "開啟django應用"
source /data/virtual/venv/bin/activate
cd /data/server/itcast/
python manage.py runserver >> /dev/null 2>&1 &
deactivate
echo "開啟nginx應用"
/data/server/nginx/sbin/nginx
}

檢查

check(){
echo "檢查項目"
netstat -tnulp | grep ':80'
}

...
8.2.3 增加日志功能
需求:
1、追蹤記錄
2、數據說話

方案:
增加日志功能
1、日志文件
/data/logs/deploy.log
2、日志格式
日期 時間 腳本名稱 步驟

知識點:
文件內容追加: >>
日期:date +%F
時間:date +%T
腳本:$0

腳本實施:

!/bin/bash

...
LOG_FILE='/data/logs/deploy.log'

增加日志功能

write_log(){
DATE=(date +%F) TIME=(date +%T)
buzhou="1" echo "{DATE} {TIME}0 : {buzhou}" >> "{LOG_FILE}"
}

獲取代碼

get_code(){
...
write_log "獲取代碼"
}

打包代碼

tar_code(){
...
write_log "打包代碼"
}

傳輸代碼

scp_code(){
...
write_log "傳輸代碼"
}

關閉應用

stop_serv(){
...
write_log "關閉應用"
...
write_log "關閉nginx應用"
...
write_log "關閉django應用"
}

解壓代碼

untar_code(){
...
write_log "解壓代碼"
}

放置代碼

fangzhi_code(){
...
write_log "放置代碼"
...
write_log "備份老文件"
...
write_log "放置新文件"
}

開啟應用

start_serv(){
...
write_log "開啟應用"
...
write_log "開啟django應用"
...
write_log "開啟nginx應用"
}

檢查

check(){
...
write_log "檢查項目"
}

...

8.2.4 增加鎖文件功能
需求:
同一時間段內,只允許有一個用戶來執行這個腳本
如果腳本執行的時候,有人在執行,那么輸出報錯:
腳本 deploy.sh 正在運行,請稍候...

設計:
    1、鎖文件       /tmp/deploy.pid

2、存在鎖文件時候,輸出報錯信息
3、腳本執行的時候,需要創建鎖文件
4、腳本執行結束的時候,需要刪除鎖文件

知識點:
條件和結果: 雙分支if語句
文件表達式: -f file_name
驗證表達式: [ 表達式 ]
創建和刪除命令:touch、rm -f

腳本實施

!/bin/bash

...
PID_FILE='/tmp/deploy.pid'
...

增加鎖文件功能

add_lock(){
echo "增加鎖文件"
touch "${PID_FILE}"
write_log "增加鎖文件"
}

刪除鎖文件功能

del_lock(){
echo "刪除鎖文件"
rm -f "${PID_FILE}"
write_log "刪除鎖文件"
}

部署函數

deploy_pro(){
add_lock
...
del_lock
}

腳本報錯信息

err_msg(){
echo "腳本 $0 正在運行,請稍候..."
}

主函數

main(){
if [ -f "${PID_FILE}" ]
then
err_msg
else
deploy_pro
fi
}

執行主函數

main

8.2.5 腳本流程知識點填充
需求:
如果我給腳本輸入的參數是deploy,那么腳本才執行,否則的話,提示該腳本的使用幫助信息,然后退出
提示信息:腳本 deploy.sh 的使用方式: deploy.sh [ deploy ]
分析:
1、腳本傳參,就需要在腳本內部進行調用參數
2、腳本的幫助信息
3、腳本內容就需要對傳參的內容進行判斷

知識點:
1、shell內置變量:$n
2、幫助信息: 簡單函數定義和調用
3、內容判斷: 多if語句或者case語句

方案:
1、腳本的傳參
腳本執行:bash deploy.sh deploy
位置參數的調用: 1 2、腳本的幫助信息 定義一個usage函數,然后調用。 提示信息格式: 腳本 deploy.sh 的使用方式: deploy.sh [ deploy ] 3、內容判斷 main函數體調用函數傳參:1
在main函數中,結合case語句,對傳入的參數進行匹配
如果傳入參數內容是"deploy",那么就執行代碼部署流程
如果傳入參數內容不是"deploy",那么輸出腳本的幫助信息
if語句和case語句的結合
if語句在外,case語句在內
case語句在外,if語句在內

腳本實施

!/bin/bash

...

腳本幫助信息

usage(){
echo "腳本 0 的使用方式:0 [deploy]"
exit
}

主函數

main(){
case "1" in "deploy") if [ -f "{PID_FILE}" ]
then
err_msg
else
deploy_pro
fi
;;
*)
usage
;;
esac
}

執行主函數

main $1
8.2.6 輸入參數安全優化
需求:
對腳本傳入的參數的數量進行判斷,如果參數數量不對,提示腳本的使用方式,然后退出

分析:
1、腳本參數數量判斷
2、條件判斷
數量對,那么執行主函數
數量不對,那么調用腳本幫助信息
知識點:
1、腳本參數數量判斷
shell內置變量: # 條件表達式: [# -eq 1 ]
2、條件判斷:
雙分支if語句
方案:
1、雙分支if語句 + main函數調用

腳本實施

!/bin/bash

...

執行主函數

if [ # -eq 1 ] then main1
else
usage
fi
8.3腳本調試功能
我們介紹腳本調試的時候呢,主要分三種方式來介紹:

-n 檢查腳本中的語法錯誤
-v 先顯示腳本所有內容,然后執行腳本,結果輸出,如果執行遇到錯誤,將錯誤輸出。
-x 將執行的每一條命令和執行結果都打印出來

8.4 生產腳本編寫總結
8.4.1 簡單腳本編寫總結
1、手工執行的命令一定要可執行
2、命令簡單羅列
3、固定的內容變量化
4、功能函數化
8.4.2 復雜腳本編寫總結
1、手工執行的命令一定要可執行
2、根據發布流程編寫腳本的框架
3、將手工執行的命令填充到對應的框架函數內部
4、增加日志功能,方便跟蹤腳本歷史執行記錄
5、主函數中邏輯流程控制好
6、設計安全的方面:
增加鎖文件,保證代碼發布的過程中不受干擾,
輸入參數數量
輸入參數匹配
腳本幫助信息
7、調試腳本

8.4.3 注意事項:
1、命令一定要保證能正常執行
2、成對的符號,要成對寫,避免丟失
3、函數調用,
寫好函數后,一定要在主函數中進行調用
4、避免符號出現中文
5、命令變量的寫法一定要規范
6、固定的內容一定要變量實現,方便以后更改
7、日志的輸出
8、腳本的傳參和函數的傳參要區別對待

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容