一: 什么是 Shell
Shell是一塊包裹著系統核心的殼,處于操作系統的最外層,與用戶直接對話,把用戶的輸入, 解釋給操作系統,然后處理操作系統的輸出結果,輸出到屏幕給與用戶看到結果。
Shell是用戶與系統交互的主要方式之一。
在這里插入圖片描述
Shell的作用是
? 解釋執行用戶輸入的命令或程序等
? 用戶輸入一條命令,Shell就解釋一條鍵盤輸入命令,Linux 給與響應的方式,稱之為交互式
在這里插入圖片描述
我們想要獲取計算機的數據,不可能每次都編寫程序,編譯后,再運行,再得到我們想要的,例如你想找到一個文件,可以先寫一段 C語言的代碼,然后調用系統函數,通過 gcc 編譯后,運行程序才能找到文件。
因此有大牛開發出了Shell解釋器,能夠讓我們方便的使用 Linux,例如只要敲下 ls - lh 這樣的字符串,Shell解釋器就會針對這句話翻譯,解釋成 ls-l -h 然后執行,通過終端輸出結果,無論是圖形化或是命令行界面。
即使我們用的圖形化,點點點的動作,區別也只是
? 命令行操作,Shell解釋執行后,輸出結果到黑屏命令行界面
? 圖形化操作,Shell接受點擊動作,輸出圖案數據
常見的 Shell 類型
?Bash (Bourne Again Shell):
最廣泛使用的 Shell,是 GNU 項目的一部分,提供了豐富的功能和強大的腳本支持。
默認的 Shell 為大多數 Linux 發行版和 macOS(直到 macOS Mojave)。
?Sh (Bourne Shell):
最早的 Unix Shell,是 Bash 的前身,功能相對簡單。
?Tcsh (C Shell):
提供了類似于 C 語言的語法,適合熟悉 C 語言的用戶。
?Zsh (Z Shell):
提供了許多高級功能,如自動補全、主題支持等,是 macOS Catalina 及以后版本的默認 Shell。
?Fish (Friendly Interactive Shell):
一個現代的 Shell,強調用戶友好性和交互性,提供了智能的自動補全和語法高亮等功能。
二: 什么是 Shell 腳本
當命令或者程序語句寫在文件中,我們執行文件,讀取其中的代碼,這個程序文件就稱之為Shell腳本
在Shell腳本里定義多條 Linux 命令以及循環控制語句,然后將這些 Linux 命令一次性執行完畢,執行腳本文件的方式稱之為,非交互式方式,
? windows 中存在*.bat 批處理腳本
? Linux 中常用*.sh 腳本文件
Shell==腳本語言屬于一種弱類型語言==,無需聲明變量類型,直接定義使用強類型語言,必須先定義變量類型,確定是數字、字符串等,之后再賦予同類型的值 centos7 系統中支持的Shell情況,有如下種類
# cat /etc/shells # /etc/shells: valid login shells /bin/sh /bin/bash /usr/bin/bash /bin/rbash /usr/bin/rbash /bin/dash /usr/bin/dash /usr/bin/tmux /usr/bin/screen
Linux 默認Shell
# echo $SHELL /bin/bash
Shell 腳本規則
在 Linux 系統中,Shell腳本或者稱之為 (bash shell程序) 通常都是 vim 編輯,由 Linux 命令、bash shell 指令、邏輯控制語句和注釋信息組成。
第一個 Shell 腳本
# vim test1.sh # cat test1.sh # 第一個 shell 腳本 這是注釋 #!/bin/bash echo"hello world!"
運行Shell腳本
# bash test1.sh hello world!
Shebang
計算機程序中Shebang指的是出現在文本文件的第一行前兩個字符#!
? 就是指明這個代碼文件用哪個解釋器去讀
在 Unix 系統中,程序會分析Shebang后面的內容,作為解釋器的指令,例如
? 以#!/bin/bash開頭的文件,程序在執行的時候會調用/bin/bash,也就是 bash 解釋器
? 以 #!/usr/bin/python 開頭的文件,代表指定python解釋器去執行
? 以 #!/usr/bin/env 解釋器名稱 ,是一種在不同平臺上都能正確找到解釋器的辦法
注意事項:
? 如果腳本未指定Shebang,腳本執行的時候,默認用當前 shell 去解釋腳本,即 $SHELL。
? 如果Shebang指定了可執行的解釋器,如 /bin/bash /usr/bin/python ,腳本在執行時,文件名會作為參數傳遞給解釋器
? 如果 #! 指定的解釋程序沒有可執行權限,則會報錯“bad interpreter: Permission denied”。
? 如果 #! 指定的解釋程序不是一個可執行文件,那么指定的解釋程序會被忽略,轉而交給當前的 SHELL 去執行這個腳本。
? 如果 #! 指定的解釋程序不存在,那么會報錯 “bad interpreter: No such file or directory”。
? #! 之后的解釋程序,需要寫其絕對路徑 (如:#!/bin/bash),它是不會自動到 $PATH 中尋找解釋器的。。
? 如果你使用 “bash test.sh” 這樣的命令來執行腳本,那么 #! 這一行將會被忽略掉,解釋器當然是用命令行中顯式指定的 bash。
腳本的常用執行方式
第一種:采用bash或sh + 腳本的相對路徑或絕對路徑(不用賦予腳本 +x 權限)
sh + 腳本的相對路徑
$ sh helloworld.sh Helloworld
sh + 腳本的絕對路徑
$ sh /home/zfox/datas/helloworld.sh helloworld
bash+腳本的相對路徑
$ bash helloworld.sh Helloworld
bash + 腳本的絕對路徑
$ bash /home/zfox/datas/helloworld.sh Helloworld
第二種:采用輸入腳本的絕對路徑或相對路徑執行腳本(必須具有可執行權限 + x)
(a)首先要賦予 helloworld.sh 腳本的 + x權限
$ chmod777helloworld.sh
(b)執行腳本
相對路徑(推薦使用)
$ ./helloworld.sh Helloworld
絕對路徑
$ /home/zfox/datas/helloworld.sh Helloworld
注意:第一種執行方法,本質是 bash解析器 幫你執行腳本,所以腳本本身不需要執行權限。第二種執行方法,本質是腳本需要自己執行,所以需要執行權限
第二個 Shell 腳本:多命令處理
(1)需求: 在/home/zfox/目錄下創建一個ljw.txt, 在ljw.txt文件中增加I love ljw
(2)案例實操:
$ touch batch.sh $ vim batch.sh
在 batch.sh 中輸入如下內容
#!/bin/bash cd /home/zfox touch ljw.txt echo"I love ljw" ljw.txt
Shell 的優勢
雖然有諸多腳本編程語言,但是對于 Linux 操作系統內部應用而言,Shell是最好的工具,Linux 底層命令都支持Shell語句,以及結合三劍客 (grep、sed、awk) 進行高級用法。
? 擅長系統管理腳本開發,如軟件啟停腳本、監控報警腳本、日志分析腳本
每個語言都有自己擅長的地方,揚長避短,達到高效運維的目的是最合適的
三: Shell 中的變量
? 變量定義與賦值,注意變量與值之間不得有空格
name="zfox" 變量名 變量類型,bash默認把所有變量都認為是字符串 bash變量是弱類型,無需事先聲明類型,是將聲明和賦值同時進行
? 變量替換寫弓|用
# name="zfox帶你學bash" # echo ${name} zfox帶你學bash # echo $name # 可以省略花括號 zfox帶你學bash
? 變量名規則
? 名稱定義要做到見名知意,切按照規則來,切不得引用保留關鍵字(help檢查保留字)
? 只能包含數字、字母、下劃線
? 不能以數字開頭
? 不能用標點符號
? 變量名嚴格區分大小寫
? 變量的作用域
? 本地變量。只針對當前的 shell 進程
系統變量
1)常用系統變量
HOME、PWD、SHELL、USER等
2)案例實操
(1)查看系統變量的值
$ echo $HOME /home/zfox
(2)顯示當前 Shell 中所有變量:set
$set BASH=/bin/bash BASH_ALIASES=() BASH_ARGC=() BASH_ARGV=()
自定義變量
1.基本語法
(1)定義變量:變量=值
(2)撤銷變量:unset 變量
(3)聲明靜態變量:readonly 變量,注意:不能unset
單引號 雙引號區別
單引號變量,不識別特殊語法
雙引號變量,能識別特殊符號
反引號,引用命令執行結果,等于 $() 用法
舉例子:
# name="奧里給" # echo ${name} 奧里給 # 單引號 # name2='${name}' # echo $name2 ${name} # 雙引號 # name2="${name}" # echo $name2 奧里給
特殊變量
? $?
? 0 成功
? 1-255 錯誤碼
Shell 的特殊變量,用在如腳本,函數傳遞參數使用,有如下特殊的,位置參數變量
$0 獲取shel1腳本文件名,以及腳本路徑 $n 獲取shel1腳本的第n個參數,n在1~9之間,如$1,$2,$9,大于9則需要寫,${10},參數空格隔開 $# 獲取執行的she11腳本后面的參數總個數 $* 獲取she11腳本所有參數,不加引號等同于 $@ 作用,加上引號"$*"作用是 接收所有參數為單個字符串,"$1 $2. $@ 不加引號,效果同上,加引號,是接收所有參數為獨立字符串,如"$1" "$2" "$3”...,空格保留
特殊變量實踐
#! bin/bash # 注意單引號和雙引號的區別 echo'特殊變量 $0 $1 $2 ... 的實踐' echo'結果: '$0$1$2 echo'############################' echo'特殊變量$# 獲取參數個數的總數' echo'結果: '$# echo'############################' echo'特殊變量$* 實踐' echo'結果: '$* echo'############################' echo'特殊變量 $@ 實踐' echo'結果: '$@
#! /bin/bash # $* 和 $@ 的區別 echo'print each param from $*' forvarin"$*" do echo"$var" done echo'print each param from $@' forvarin"$@" do echo"$var" done
$*和$@的區別你了解嗎? $*和 $@ 都表示傳遞給函數或腳本的所有參數 當 $*和 $@ 不被雙引號""包圍時,它們之間沒有任何區別,都是將接收到的每個參數看做一份數據,彼此之間以空格來分隔。 但是當它們被雙引號""包含時,就會有區別了: "$*"會將所有的參數從整體上看做一份數據,而不是把每個參數都看做一份數據。'yu chao 180 180 180 180" "$@"仍然將每個參數都看作一份數據,彼此之間是獨立的。 "chao' "180" "180" "180" 比如傳遞了5個參數,那么對于"$*"來說,這5個參數會合并到一起形成一份數據,它們之間是無法分割的;而對于"$@"來說,這5個參數是相互獨立的,它們是5份數據。 如果使用 echo 直接輸出"$*"和"$@"做對比,是看不出區別的;但如果使用for循環來逐個輸出數據,立即就能看出區別來。
Shell 變量面試題
問,如下輸入什么內容
# cat test.sh user1=`whoami` # sh test.sh # echo $user1 A.當前用戶 B.zfox c.空 答案選c
`linux命令`
在 linux 中反引號,中的命令執行結果會被保留下來
# name=`ls` # echo $name test1.sh test2.sh test3.sh
解答:
1. 每次調用 bash/sh 解釋器執行腳本,都會開啟一個子 shell,因此不保留當前的 shell 變量,通過 pstree 命令檢查進程樹
2. 調用 source 或者 點符號,在當前 shell 環境加載腳本,因此保留變量
環境變量設置
環境變量一般指的是用 export 內置命令導出的變量,用于定義 shell 的運行環境、保證 shell 命令的正確執行。
shell 通過環境變量確定登錄的用戶名、PATH路徑、文件系統等各種應用。
環境變量可以在命令行中臨時創建,但是用戶退出shell終端,變量即丟失,如要永久生效,需要修改環境變量配置文件
? 用戶個人配置文件 ~/.bash profile、 ~/.bashrc 遠程登錄用戶特有文件
? 全局配置文件 /etc/profile/etc/bashrc,且系統建議最好創建在 /etc/profile.d/,而非直接修改主文件,修改全局配置文件,影響所有登錄系統的用戶
檢查系統環境變量的命令
? set,輸出所有變量,包括全局變量、局部變量
? env,當前用戶的所有環境變量,包括全局環境變量和局部環境變量
? declare,輸出所有的變量,如同 set
? export,顯示和設置環境變量值
撤銷環境變量
? unset 變量名,刪除變量或函數
設置只讀變量
? readonly,只有shell結束,只讀變量失效
直接readonly顯示當前系統只讀變量 # readonly name="超哥" # name="chaochao" -bash只讀變量
環境變量初始化與加載順序
在這里插入圖片描述
四: Shell 子串
bsah 一些基礎的內置命令
echo eval exec export read shift
echo 命令
-n 不換行輸出 -e 解析字符串中的特殊符號 換行 回車 制表符 四個空格 退格 # echo 你真胖;echo 你還挺可愛你真胖 你還挺可愛 # 不換行打印 # echo -n 你真胖;echo 你還挺可愛 你真胖你還挺可愛 # echo -n 你真胖;echo -n 你還挺可愛你真胖你還挺可愛 # # echo -e "我看你挺 好的" 我看你挺 好的 # printf printf"你好 我是 吳彥祖" 你好 我是 吳彥祖
eval
執行多個命令
#evalls;cd/tmp del_data.sh hello.py special_var.sh t1.sh different.sh hello.sh nohup.out str1 test.txt
exec
不創建子進程,執行后續命令, 且執行完畢后,自動 exit
# exec date Fri25Apr202508:56:41AM CST Connection closed. Disconnectedfromremotehost(Ubuntu-tencnt) at 0841.
Shell 子串的花式用法
${變量} 返回變量值 ${#變量} 返回變量長度,字符長度 ${變量:start} 返回變量 offset 數值之后的字符 ${變量length} 提取 offset 之后的 length 限制的字符 ${變量#word} 從變量開頭刪除最短匹配的 word 子串 ${變量##word} 從變量開頭,刪除最長匹配的 word ${變量%word} 從變量結尾刪除最短的 word ${變量%%word} 從變量結尾開始刪除最長匹配的 word ${變量/pattern/string} 用string代替第一個匹配的 pattern ${變量//pattern/string) 用 string 代替所有的 pattern
# name="yuchao180' # echo $name yuchao180 # echo ${name} yuchao188 # echo ${#name} 9 # 截取子串的用法 # echo ${name:3} hao180 # echo ${name:5} o180 #設置起點,以及元素長度 # echo ${name4} chao
? 多種統計長度的命令
# echo $name yuchao180 # echo $name | wc -l 1 # echo $name |wc -L 9 # 解釋wc命令參數用法 -l 行數 -L 最長一行的長度 # cat test1.txt | wc -l 3 # cat test1.txt | wc -L 8
? 統計命令執行速度
字符串長度統計方式這么多,誰最快?
time命令,統計命令執行時長
for 循環的 shell 編程知識語法
fornumberin{1..100} do echo $number done 寫在一行的方法 fornumin{1..100};doecho $num; done
# 1.方法 # for n in {1..3}; do str1=`seg -s ":" 10`; echo $str1; done 1:2:3:4:5:6:7:8:9:10 1:2:3:4:5:6:7:8:9:10 1:2:3:4:5:6:7:8:9:10 # 結合 time 命令 ${#變量} 計算時間是13s # time for n in {1..10000}; do char=`seq -s "chaoge" 100`; echo ${#char} &/dev/null; done real 0m13.956s 實際運行的時間 user 0m6.005s 用戶態執行的時間 sys 0m5.868s 內核態執行的時間 # 使用 wc -L 命令計算時間 # time for n in {1..10000}; do char=`seq -s "chaoge" 100`; echo ${char} | wc-L &/dev/null; done real 0m49.262s user 0m18.843s sys 0m24.905s # expr命令的 length 函數統計 # time for n in {1..10000}; do char=`seq -s "chaoge" 100`; expr length "${char}" &/dev/null; done real 0m28.511s user 0m11.960s sys 0m12.046s
Shell編程,盡量使用 linux 內置的命令,內置的操作,和內置的函數,C語言開發,效率最高,盡可能的減少管道符的操作
字符串截取
刪除匹配到的子串
# name="I am chaoge" # echo $name I am chaoge # echo ${name2} am # echo ${name5} m cha # name2="abcABC123ABcabc" # #從開頭匹配字符刪除 # echo ${name2#a*c} ABC123ABCabc # echo ${name2##a*c} # 利用%形式,從后向前匹配截取 # name2=abcABC123ABcabc # echo ${name2%a*c} abCABC123ABC # echo ${name2%%a*c} # echo ${name2%%a*C} abcABC123ABCabc # echo ${name2%a*C} abcABC123ABCabc
替換字符串
# str1="Hello,man,i am your brother." # echo $str1 Hello,man,i am your brother. # echo ${str1/man/boy} Hello,boy,i am your brother. #多次匹配替換 # echo $str1 Hello,man,i am your brother. # echo ${str1/o/0} HellO,man,i am your brother. # echo ${str1//o/O} HellO,man,i am yOur brOther.
應用:批量修改文件名
創建一批文件
# touch chaochao_{1..5}_finished.jpg # touch chaochao_{1..5}_finished.png
去掉剩下的所有 jpg 文件的 _finished 字符
編寫 Shell 腳本如下:
#! /bin/bash forfile_namein`ls *fin*jpg`;domv $file_name `echo ${file_name//_finished/}` ; done
特殊 Shell 擴展變量
如果parameter變量值為空,返回word字符串,賦值給result變量 result=${parameter:-word} 如果para變量為空,則word替代變量值,且返回其值 result=${parameter:=word} 如果para變量為空,word當作stderr輸出,否則輸出變量值 用于設置變量為空導致錯誤時,返回的錯誤信息 result=$fparameter:?word? 如果para變量為空,什么都不做,否則word返回 result=${parameter:+word}
鏈接:https://blog.csdn.net/weixin_50776420/article/details/147463567?spm=1001.2014.3001.5501
-
操作系統
+關注
關注
37文章
7082瀏覽量
124943 -
Shell
+關注
關注
1文章
372瀏覽量
23972 -
腳本
+關注
關注
1文章
397瀏覽量
28345
原文標題:Shell腳本黑科技:5分鐘學會自動化運維,效率翻倍
文章出處:【微信號:magedu-Linux,微信公眾號:馬哥Linux運維】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
linux shell 腳本入門
嵌入式和物聯網的shell腳本學習指南之shell腳本入門免費下載

109個實用shell腳本分享
shell腳本基礎知識
Linux Shell腳本經典案例分享

評論