Linux: Shell指令碼程式設計規範與變數,開啓小白的shell之路

2020-08-10 23:26:46

shell指令碼程式設計規範

■Shell指令碼的概念

●將要執行的命令按順序儲存到一個文字檔案
●給該檔案可執行許可權

■Shell指令碼應用場景

●重複性操作
●互動性任務
●批次事務處理
●服務執行狀態監控
●定時任務執行
●可結合各種Shell控制語句以完成更復雜的操作

■Shell的作用——命令直譯器,「翻譯官

在这里插入图片描述
使用者的登錄shell

●登錄後預設使用的shell程式,一般爲/bin/bash

●不同shell的內部指令,執行環境等會有所區別

[root@localhost ~]# cat /etc/shells
/bin/sh
/bin/bash    一般爲這個
/sbin/nologin
/usr/bin/sh
/usr/bin/bash
/usr/sbin/nologin
/bin/tcsh
/bin/csh

編寫第一個shell指令碼

■編寫指令碼程式碼

●使用vim文字編輯器

●每行一條Linux命令,按執行順序依次編寫

●指令碼後綴爲.sh

●例如,將一下三條命令按順序用shell指令碼編寫

cd /boot
pwd
ls -lh vm*
以上是需要執行的內容


[root@localhost opt]# vi first.sh
#!/bin/bash		               shell指令碼標準格式
cd /boot
pwd
ls -lh vm*
'儲存退出'

[root@localhost opt]# ls
first.sh  rh


■賦武予可執行許可權

使指令碼具有可執行屬性

[root@localhost~]# chmod +x first.s

■執行指令碼檔案(四種方法)

方法一:sh指令碼檔案路徑

[root@localhost opt]# sh first.sh 
/boot
-rwxr-xr-x. 1 root root 5.7M Oct 23 14:07 vmlinuz-0-rescue-d078430d0d8f434fb5ad6e47678ea86f
-rwxr-xr-x. 1 root root 5.7M Aug 23  2017 vmlinuz-3.10.0-693.el7.x86_64

方法二:source指令碼檔案路徑

[root@localhost opt]# source first.sh 
/boot
-rwxr-xr-x. 1 root root 5.7M Oct 23 14:07 vmlinuz-0-rescue-d078430d0d8f434fb5ad6e47678ea86f
-rwxr-xr-x. 1 root root 5.7M Aug 23  2017 vmlinuz-3.10.0-693.el7.x86_64

方法三:sh指令碼檔案路徑

[root@localhost opt]# sh first.sh 
/boot
-rwxr-xr-x. 1 root root 5.7M Oct 23 14:07 vmlinuz-0-rescue-d078430d0d8f434fb5ad6e47678ea86f
-rwxr-xr-x. 1 root root 5.7M Aug 23  2017 vmlinuz-3.10.0-693.el7.x86_64

執行指令碼檔案(四種方法)的總結

● ./ 與sh執行指令碼,不會換路徑
●source執行指令碼,會切換路徑

■更完善的指令碼構成

指令碼宣告

註釋資訊

可執行語句

[root@localhost opt]# vim first.sh
#!/bin/bash
#This is my first shell-script		'指令碼描述資訊'
cd /boot
echo "當前所在路徑:"		'輸出友好提示資訊'
pwd
echo "以vm爲開頭的檔案是:"		'輸出友好提示資訊'
ls -lh vm*

[root@localhost opt]# ./first.sh 
當前所在路徑:
/boot
以vm爲開頭的檔案是:
-rwxr-xr-x. 1 root root 5.7M Oct 23 14:07 vmlinuz-0-rescue-d078430d0d8f434fb5ad6e47678ea86f
-rwxr-xr-x. 1 root root 5.7M Aug 23  2017 vmlinuz-3.10.0-693.el7.x86_64

■管道與重定向

■互動式硬體裝置

●標準輸入:從該裝置接收使用者輸入的數據

●標準輸出:通過該裝置向使用者輸出數據

●標準錯誤:通過該裝置報告執行出錯資訊

在这里插入图片描述

■重定向操作

在这里插入图片描述

[root@localhost opt]# chattr +i /etc/passwd /etc/shadow		'鎖定使用者和密碼檔案'
[root@localhost opt]# lsattr /etc/passwd /etc/shadow		'檢視鎖定情況'
----i----------- /etc/passwd
----i----------- /etc/shadow
[root@localhost opt]# useradd lisi	                      '嘗試新增使用者'
useradd: cannot open /etc/passwd	                      '提示錯誤'
[root@localhost opt]# useradd lisi 2> /opt/error.txt	  '將錯誤資訊輸入到新的error.txt'

[root@localhost opt]# cat /opt/error.txt 	               '檢視文字內容'
useradd: cannot open /etc/passwd
 '若操作沒有錯誤,則輸出的內容沒有錯誤資訊'




■管道操作符號 ‘|’

將左側的命令輸出結果,作爲右側命令的處理物件(前後有關係時使用)

[root@localhost opt]# grep "bash$" /etc/passwd
root:x:0:0:root:/root:/bin/bash
lisi:x:1000:1000:lisi:/home/lisi:/bin/bash
[root@localhost opt]# grep "bash$" /etc/passwd | awk -F: '{print $1,$7}'		'此間的-F:也可以用空格和Tab代替'
root /bin/bash
lisi /bin/bash

[root@localhost opt]# df -hT
Filesystem     Type      Size  Used Avail Use% Mounted on
/dev/sda2      xfs        20G  4.1G   16G  21% /
devtmpfs       devtmpfs  898M     0  898M   0% /dev
tmpfs          tmpfs     912M     0  912M   0% /dev/shm
tmpfs          tmpfs     912M  9.1M  903M   1% /run
tmpfs          tmpfs     912M     0  912M   0% /sys/fs/cgroup
/dev/sda5      xfs        10G   39M   10G   1% /home
/dev/sda1      xfs       6.0G  174M  5.9G   3% /boot
tmpfs          tmpfs     183M  4.0K  183M   1% /run/user/42
tmpfs          tmpfs     183M   36K  183M   1% /run/user/1000
tmpfs          tmpfs     183M     0  183M   0% /run/user/0
[root@localhost opt]# df -hT | awk '{print $1,$2,$6}'	'檢視第1.2.6列的數據'
Filesystem Type Use%
/dev/sda2 xfs 21%
devtmpfs devtmpfs 0%
tmpfs tmpfs 0%
tmpfs tmpfs 1%
tmpfs tmpfs 0%
/dev/sda5 xfs 1%
/dev/sda1 xfs 3%
tmpfs tmpfs 1%
tmpfs tmpfs 1%
tmpfs tmpfs 0%

[root@localhost opt]# df -hT | awk -F " " '{print $1,$2,$6}'	'檢視第1.2.6列的數據'
Filesystem Type Use%
/dev/sda2 xfs 21%
devtmpfs devtmpfs 0%
tmpfs tmpfs 0%
tmpfs tmpfs 1%
tmpfs tmpfs 0%
/dev/sda5 xfs 1%
/dev/sda1 xfs 3%
tmpfs tmpfs 1%
tmpfs tmpfs 1%
tmpfs tmpfs 0%
[root@localhost opt]# df -hT | grep "sda2" | awk '{print $6}'
21%		'檢視裝置sda2第6列的數據'


●awk :大部分情況,按列讀取

大部分情況下
grep:過濾關鍵字
sed: 按行讀取
awk:按列讀取數據
$1,$2:位置變數

Shell變數的作用、型別

■變數的作用

●用來存放系統和使用者需要使用的特定參數(值)

變數名:使用固定的名稱,由系統預設或使用者定義

變數值:能夠根據使用者設定、系統環境的變化而變化

■變數的型別

●自定義變數:由使用者自己定義、修改和使用

●特殊變數:環境變數,只讀變數,位置變數,預定義變數

■定義一個新的變數與檢視變數的值

●變數名以字母或下劃線開頭,區分大小寫,建議全大寫

變數名=變數值
代表將右邊的值賦予左邊
檢視變數的值:echo $變數名
例如:
[root@localhost opt]# addr=22323
[root@localhost opt]# echo $addr
22323
[root@localhost opt]# addr=10
[root@localhost opt]# echo $addr
10
[root@localhost opt]# num=$addr
[root@localhost opt]# addr=20
[root@localhost opt]# echo $num
10
[root@localhost opt]# echo $addr
20
[root@localhost opt]# num=$addr
[root@localhost opt]# echo $num
20
[root@localhost opt]# product=python
[root@localhost opt]# version=3.7
[root@localhost opt]# echo $product $version 
python 3.7
[root@localhost opt]# echo $product$version
python3.5
[root@localhost opt]# echo $product2.8
.8
[root@localhost opt]# echo $product 2.8
2.8
[root@localhost opt]# echo ${product}2.8
2.8
[root@localhost opt]# echo ${product} 2.8
2.8


■賦值時使用引號與從鍵盤輸入內容爲變數賦值

賦值時使用引號

●雙引號:允許通過$符號參照其他變數值

●單引號:禁止參照其他變數值,$視爲普通字元

●反撇號:命令替換,提取命令執行後的輸出結果

[root@localhost opt]# echo "$product"
python
[root@localhost opt]# echo "${product}3.3"	     '雙引號:允許通過$符號參照其他變數值'
python3.3
[root@localhost opt]# echo ‘$product’
‘python’
[root@localhost opt]# echo '$product'	        '單引號禁止參照其他變數值,$視爲普通字元'
$product
[root@localhost opt]# ps aux | wc -l
151
[root@localhost opt]# num=`ps aux | wc -l`	     '反撇號中識別命令,對命令結果進行解析'
[root@localhost opt]# echo $num
152
[root@localhost opt]# abc=$(ps aux | wc -l)
[root@localhost opt]# echo $abc
152

●從鍵盤輸入內容爲變數賦值

read [-p "提示資訊"] 變數名
[root@localhost opt]# vi first.sh 
#!/bin/bash
#This is my first shell-script
read -p "請輸入一個整數:" score
echo "你的成績爲:$score"
~ 
[root@localhost opt]# ./first.sh 
請輸入一個整數:80
你的成績爲:80


■設定變數的作用範圍

格式1:export變數名…

格式2: export變數名=變數值…

[root@localhost~]# echo "$Product $Version"
Benet 6.0
                                                              導出爲全域性變數
[root@localhost~]# export Product Version
[root@localhost~]# bash
[root@localhost~]# echo "$Product $Version"                   子程式參照全域性變數
Benet 6.0
[root@localhost~]# exit
                                                           

兩種格式可以混合使用

■自定義變數

●expr 變數1 運算子 變數2 [運算子 變數3] …

■常用運算子

●加法運算:+

●減法運算:-

●乘法運算:l*

●除法運算:/

●求模(取餘)運算:%

[root@localhost opt]# expr 3 + 2	         '加法運算'
5
[root@localhost opt]# expr 3 - 2	         '減法運算'
1	

[root@localhost opt]# expr 3 \* 2             '乘法運算'
6
[root@localhost opt]# expr 3 / 2	         ',除法運算'
1
[root@localhost opt]# expr 3 % 2	          '取餘運算'
1
[root@localhost opt]# expr 32 % 21
11
[root@localhost opt]# expr 32 % 5
2
[root@localhost opt]# sum=`expr 3 + 3`	      '求和變數運算'
[root@localhost opt]# echo $sum
6
[root@localhost opt]# 

特殊的Shell變數

●組態檔:letc/profile、~l.bash_profile

■環境變數

■常見的環境變數
PWD
PATH
USER
SHELL
HOME

[root@localhost~]# echo $PATH
[root@localhost~]# PATH="$PATH:/root"
[root@localhost~]# echo $PATH

●由系統提前建立,用來設定使用者的工作環境

●組態檔:letc/profile、~l.bash_profile

■只讀變數

●用於變數值不光許被修改的情況

[root@localhost~]# name=cloud
[root@localhost~]# readonly name/l         設定爲只讀變數
[root@localhost~]#echo $name
cloud
[root@localhost~]# name=yun
-bash: name: readonly variablell            只讀變數不可以被重新賦值
[root@localhost~]#
[root@localhost~]# unset namell          只讀變數不可以被刪除
-bash: unset: name:cannot unset:readonly variable

■位置變數

表示爲$n,n爲1-9之間的數位
在这里插入图片描述

[root@localhost opt]# vim demo.sh 
#!/bin/bash
#This is my first shell-script
sum=0
sum=`expr $1 + $2`
echo "總和爲:$sum"

[root@localhost opt]# ./demo.sh 20 30
總和爲:50
[root@localhost opt]# vim demo.sh 
#!/bin/bash
#This is my first shell-script
sum=0
sum=`expr $1 + $2`
echo "總和爲:$sum"
echo "執行的指令碼是$0"

[root@localhost opt]# ./demo.sh 22 33
總和爲:55
執行的指令碼是./demo.sh
[root@localhost opt]# !vim
#!/bin/bash
#This is my first shell-script
sum=0
sum=`expr $1 + $2`
echo "總和爲:$sum"
echo "執行的指令碼是:$0"
echo "執行的指令碼個數是:$#"		'$#:命令列中位置變數的個數'
~     
[root@localhost opt]# ./demo.sh 13 30
總和爲:43
執行的指令碼是:./demo.sh
執行的指令碼個數是:2
[root#!/bin/bash
#This is my first shell-script
sum=0
sum=`expr $1 + $2`
echo "總和爲:$sum"
echo "執行的指令碼是:$0"
echo "執行的指令碼個數是:$#"
echo "詳細內容時:$*"

@localhost opt]# !vim
#!/bin/bash
#This is my first shell-script
sum=0
sum=`expr $1 + $2`
echo "總和爲:$sum"
echo "執行的指令碼是:$0"
echo "執行的指令碼個數是:$#"
echo "詳細內容是:$*"

[root@localhost opt]# ./demo.sh 13 30 
總和爲:43
執行的指令碼是:./demo.sh
執行的指令碼個數是:2
詳細內容是:13 30
[root@localhost opt]# ./demo.sh 13 30 22 22 22
總和爲:43
執行的指令碼是:./demo.sh
執行的指令碼個數是:5
詳細內容是:13 30 22 22 22

[root@localhost opt]# !vim
#!/bin/bash
#This is my first shell-script
sum=0
sum=`expr $1 + $2`
echo "是否執行成功:$?"
echo "總和爲:$sum"		
echo "執行的指令碼是:$0"
echo "執行的指令碼個數是:$#"
echo "詳細內容是:$*"

[root@localhost opt]# ./demo.sh 13 30 
是否執行成功:0	'0:表示執行成功,非0值:表示執行失敗'
總和爲:43
執行的指令碼是:./demo.sh
執行的指令碼個數是:2
詳細內容是:13 30

[root@localhost opt]# !vim
#!/bin/bash
#This is my first shell-script
sum=0
sum=`expr $1 / $2`	'改變成除法'
echo "是否執行成功:$?"	'此變數要放在第一行,輸出上一行命令執行後返回的狀態'
echo "總和爲:$sum"
echo "執行的指令碼是:$0"
echo "執行的指令碼個數是:$#"
echo "詳細內容是:$*"

[root@localhost opt]# ./demo.sh 10 0
expr: division by zero	
是否執行成功:2	'顯示失敗'
總和爲:
執行的指令碼是:./demo.sh
執行的指令碼個數是:2
詳細內容是:10 0


■預定義變數

●$#:命令列中位置變數的個數

●$*:所有位置變數的內容

●$?:上一條命令執行後返回的狀態,當返回狀態值爲0時表示正常,非0值表示執行異常或出錯

●$0:當前執行的進程/程式名

分析指令碼

[root@localhost opt]# vi first.sh
#!/bin/bash
TARFILE=beifen-`date +%s`.tgz  
'設定變數名稱,+%s表示從1970至今經過的秒數,所以檔名不會出現重複的情況,就不會有被覆蓋的風險'


tar zcvf $TARFILE $* &> /dev/null	'tar工具壓縮輸出到 /dev/null'

echo "已執行$0個指令碼"	'當前執行的進程名'

echo "共完成$#個物件的備份"	'位置變數的個數'

echo "具體內容包括:$*"	'所有位置變數的內容'
~    

[root@localhost opt]# ./first.sh /etc/passwd /etc/shadow
已執行./ddd.sh個指令碼
共完成2個物件的備份
具體內容包括:/etc/passwd /etc/shadow

'/dev/null:黑洞,數據到這裏就消失了,無法找回'