[toc]html
Shell 是一個用 C 語言編寫的程序,它是用戶使用 Linux 的橋樑。Shell 既是一種命令語言,又是一種程序設計語言。 shell是一種腳本語言; 可使用邏輯判斷、循環等語法; 可自定義函數; shell是系統命令的集合; shell腳本能夠實現自動化運維,能大大增長咱們的運維效率;shell
說明了shell 腳本在工做的重要性,shell腳本就是一些命令的集合,是自動化運維的重要部分編程
下面跟着步驟來一步步學習如何寫shell腳本數組
[root@localhost ~]# mkdir shell [root@localhost ~]# cd shell/ [root@localhost shell]# ls [root@localhost shell]# vi 01.sh
shell腳本一般都是.sh爲後綴名,但不是說不加.sh的腳本就不能執行,只是你們的一個習慣而已,因此若是發新了以.sh爲後綴的文件,那麼它可能就是一個shell腳本.bash
本例中,腳本文件01.sh,進入編輯狀態後,第一行要以#!/bin/bash開頭,表示該文件使用的是bash語法.而/bin/bash是Bash的解釋器命令路徑.運維
[root@localhost shell]# sh 01.sh 123 22:43:14 up 25 min, 1 user, load average: 0.00, 0.01, 0.01 USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT root pts/0 192.168.72.1 22:26 2.00s 0.08s 0.00s w 01.sh
把#!/bin/bash這一行刪除,運行命令後也能執行但這樣不符合規範.ssh
使用該方法運行shell腳本的前提是腳本自己有執行權限,須要給腳本加x權限函數
[root@localhost shell]# chmod +x 01.sh [root@localhost shell]# ./01.sh 123 23:18:34 up 1:01, 1 user, load average: 0.00, 0.01, 0.03 USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT root pts/0 192.168.72.1 22:26 2.00s 0.11s 0.01s w 01.sh
[root@localhost shell]# bash 01.sh 123 23:37:15 up 1:19, 1 user, load average: 0.00, 0.01, 0.03 USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT root pts/0 192.168.72.1 22:26 3.00s 0.20s 0.01s w 01.sh
這裏是否能夠理解有三種方法均可以執行shell腳本,可是本機驗證成功,不表明其餘機器虛擬機是否成功,後續測試post
[root@localhost shell]# vi /etc/init.d/network #! /bin/bash # # network Bring up/down networking # # chkconfig: 2345 10 90 # description: Activates/Deactivates all network interfaces configured to \ # start at boot time. #
[root@localhost shell]# sh -x 01.sh + echo 123 123 + w 23:40:21 up 1:22, 1 user, load average: 0.00, 0.01, 0.03 USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT root pts/0 192.168.72.1 22:26 5.00s 0.22s 0.01s w + ls 01.sh [root@localhost shell]# bash -x 01.sh + echo 123 123 + w 23:40:29 up 1:23, 1 user, load average: 0.00, 0.01, 0.03 USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT root pts/0 192.168.72.1 22:26 5.00s 0.21s 0.00s w + ls 01.sh
date命令用於顯示或設置系統時間與日期。 命令選項:學習
[root@xavi ~]# date //當前日期 2018年 04月 17日 星期二 22:06:22 CST [root@xavi ~]# cal //當前日曆 四月 2018 日 一 二 三 四 五 六 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 [root@xavi ~]# date +%Y //年 2018 [root@xavi ~]# date +%y //年縮寫 18 [root@xavi ~]# date +%m //月 04 [root@xavi ~]# date +%Y%m%d //年月日 20180417 [root@xavi ~]# date +%F 2018-04-17 [root@xavi ~]# date +%H //小時 22 [root@xavi ~]# date +%M //分鐘 23 [root@xavi ~]# date +%S //秒 10 [root@xavi ~]# date +%s //時間戳,時間戳是從1970年1月1日(UTC/GMT的午夜)開始所通過的秒數,不考慮閏秒 1523975099 [root@xavi ~]# date +%T //時間的完整顯示 22:27:04 [root@xavi ~]# date "+%Y-%m-%d %H:%M:%S %w" // 年月日,時分秒,星期 2018-04-17 22:20:50 2 [root@xavi ~]# date -d "-1 day" 2018年 04月 16日 星期一 22:31:20 CST [root@xavi ~]# date -d "-1 day" +%F 2018-04-16 [root@xavi ~]# date -d "-1 month" +%F 2018-03-17 [root@xavi ~]# date -d "-1 year" +%F 2017-04-17 [root@xavi ~]# date -d "-1 hour" +%T 21:44:30 [root@xavi ~]# date +%s -d "2018-04-17 22:46" // 日期轉化爲時間戳 1523976360
當腳本中使用某個字符串較頻繁而且字符串長度很長時就應該使用變量代替 使用條件語句時,常使用變量 if [ $a -gt 1 ]; then ... ; fi 引用某個命令的結果時,用變量替代 n=`wc -l 1.txt` 寫和用戶交互的腳本時,變量也是必不可少的 read -p "Input a number: " n; echo $n 若是沒寫這個n,能夠直接使用$REPLY 內置變量 $0, $1, $2… $0表示腳本自己,$1 第一個參數,$2 第二個 .... $#表示參數個數 數學運算a=1;b=2; c=$(($a+$b))或者$[$a+$b]
在命令行提示符直接執行env、set查看系統或環境變量。env顯示用戶環境變量,set顯示Shell預先定義好的變量以及用戶變量。能夠經過export導出成用戶變量。 一些寫Shell腳本時經常使用的系統變量:
普通變量定義:VAR=value 臨時環境變量定義:export VAR=value 變量引用:$VAR
下面看下他們之間區別:
Shell進程的環境變量做用域是Shell進程,當export導入到系統變量時,則做用域是Shell進程及其Shell子進程。
[root@xaviyunserver sbin]# ps axjf |grep pts 1229 1773 1773 1773 ? -1 Ss 0 0:00 \_ sshd: root@pts/0 1773 1775 1775 1775 pts/0 2631 Ss 0 0:00 \_ -bash 1775 1825 1825 1775 pts/0 2631 T 0 0:00 \_ sh test2.sh 1775 2631 2631 1775 pts/0 2631 R+ 0 0:00 \_ ps axjf 1775 2632 2631 1775 pts/0 2631 S+ 0 0:00 \_ grep --color=auto pts [root@xaviyunserver sbin]# echo $$ 1775 [root@xaviyunserver sbin]# VAR=123 [root@xaviyunserver sbin]# echo $VAR 123 [root@xaviyunserver sbin]# bash [root@xaviyunserver sbin]# echo $$ 2633 [root@xaviyunserver sbin]# ps axjf |grep pts 1229 1773 1773 1773 ? -1 Ss 0 0:00 \_ sshd: root@pts/0 1773 1775 1775 1775 pts/0 2649 Ss 0 0:00 \_ -bash 1775 1825 1825 1775 pts/0 2649 T 0 0:00 \_ sh test2.sh 1775 2633 2633 1775 pts/0 2649 S 0 0:00 \_ bash 2633 2649 2649 1775 pts/0 2649 R+ 0 0:00 \_ ps axjf 2633 2650 2649 1775 pts/0 2649 S+ 0 0:00 \_ grep --color=auto pts [root@xaviyunserver sbin]# echo $VAR [root@xaviyunserver sbin]# exit exit [root@xaviyunserver sbin]# echo $VAR 123 [root@xaviyunserver sbin]# ps -ef |grep ssh root 1229 1 0 07:58 ? 00:00:00 /usr/sbin/sshd -D
ps axjf輸出的第一列是PPID(父進程ID),第二列是PID(子進程ID) 當SSH鏈接Shell時,當前終端PPID(-bash)是sshd守護程序的PID(root@pts/0),所以在當前終端下的全部進程的PPID都是-bash的PID,好比執行命令、運行腳本。 因此當在-bash下設置的變量,只在-bash進程下有效,而-bash下的子進程bash是無效的,當export後纔有效。
[root@xaviyunserver sbin]# sh test.sh 1229 1773 1773 1773 ? -1 Ss 0 0:00 \_ sshd: root@pts/0 1773 1775 1775 1775 pts/0 2693 Ss 0 0:00 \_ -bash 1775 1825 1825 1775 pts/0 2693 T 0 0:00 \_ sh test2.sh 1775 2693 2693 1775 pts/0 2693 S+ 0 0:00 \_ sh test.sh 2693 2694 2693 1775 pts/0 2693 R+ 0 0:00 \_ ps -axjf 2693 2695 2693 1775 pts/0 2693 R+ 0 0:00 \_ sh test.sh 2693 [root@xaviyunserver sbin]# cat test.sh #!/bin/bash ps -axjf |grep pts echo $$ echo $VAR [root@xaviyunserver sbin]# sh test.sh 1229 1773 1773 1773 ? -1 Ss 0 0:00 \_ sshd: root@pts/0 1773 1775 1775 1775 pts/0 2693 Ss 0 0:00 \_ -bash 1775 1825 1825 1775 pts/0 2693 T 0 0:00 \_ sh test2.sh 1775 2693 2693 1775 pts/0 2693 S+ 0 0:00 \_ sh test.sh 2693 2694 2693 1775 pts/0 2693 R+ 0 0:00 \_ ps -axjf 2693 2695 2693 1775 pts/0 2693 R+ 0 0:00 \_ sh test.sh 2693 [root@xaviyunserver sbin]# export VAR [root@xaviyunserver sbin]# sh test.sh 1229 1773 1773 1773 ? -1 Ss 0 0:00 \_ sshd: root@pts/0 1773 1775 1775 1775 pts/0 2696 Ss 0 0:00 \_ -bash 1775 1825 1825 1775 pts/0 2696 T 0 0:00 \_ sh test2.sh 1775 2696 2696 1775 pts/0 2696 S+ 0 0:00 \_ sh test.sh 2696 2697 2696 1775 pts/0 2696 R+ 0 0:00 \_ ps -axjf 2696 2698 2696 1775 pts/0 2696 R+ 0 0:00 \_ sh test.sh 2696 123
在/etc/profile下定義的變量就是這個原理,後面有章節會講解Linux經常使用變量文件。
$1-$n,須要注意的是從第10個開始要用花括號調用,例如${10}
#!/bin/bash echo "1: $1" shift echo "2: $2" shift echo "3: $3" shift [root@xaviyunserver sbin]# sh postion.sh 1: 2: 3: [root@xaviyunserver sbin]# sh postion.sh a b c 1: a 2: c 3:
Shell中全部變量引用使用$符,後跟變量名。 有時個別特殊字符會影響正常引用,那麼須要使用${VAR},例如:
# VAR=123 # echo $VAR 123 # echo $VAR_ # Shell容許VAR_爲變量名,因此此引用認爲這是一個有效的變量名,故此返回空 # echo ${VAR} 123
# echo $VAR456 # echo ${VAR}456 123456
# VAR=`echo 123` # echo $VAR 123 # VAR=$(echo 123) # echo $VAR 123
在變量賦值時,若是值有空格,Shell會把空格後面的字符串解釋爲命令:
# VAR=1 2 3 -bash: 2: command not found # VAR="1 2 3" # echo $VAR 1 2 3 # VAR='1 2 3' # echo $VAR 1 2 3
看不出什麼區別,再舉個說明:
# N=3 # VAR="1 2 $N" # echo $VAR 1 2 3 # VAR='1 2 $N' # echo $VAR 1 2 $N
單引號是告訴Shell忽略特殊字符,而雙引號則解釋特殊符號原有的意義,好比$、!。
Shell註釋也很簡單,只要在每行前面加個#號,即表示Shell忽略解釋。
用${}引用變量,${}還有一個重要的功能,就是文本處理,單行文本基本上能夠知足你全部需求。
# VAR='hello world!' # echo $VAR hello world! # echo ${#VAR} 12
格式:
${parameter:offset} ${parameter:offset:length}
截取hello字符串: # VAR='hello world!' # echo ${VAR:0:5} hello
截取wo字符: # echo ${VAR:6:2} wo
截取world!字符串: # echo ${VAR:5} world!
截取最後一個字符: # echo ${VAR:(-1)} ! 截取最後二個字符: # echo ${VAR:(-2)} d! 截取從倒數第3個字符後的2個字符: # echo ${VAR:(-3):2} ld
格式:${parameter/pattern/string}
# VAR='hello world world!' 將第一個world字符串替換爲WORLD: # echo ${VAR/world/WORLD} hello WORLD world! 將所有world字符串替換爲WORLD: # echo ${VAR//world/WORLD} hello WORLD WORLD!
格式:
${parameter#word} # 刪除匹配前綴 ${parameter##word} ${parameter%word} # 刪除匹配後綴 ${parameter%%word}
# URL="http://www.baidu.com/baike/user.html" 以//爲分隔符截取右邊字符串: # echo ${URL#*//} www.baidu.com/baike/user.html 以/爲分隔符截取右邊字符串: # echo ${URL##*/} user.html 以//爲分隔符截取左邊字符串: # echo ${URL%%//*} http: 以/爲分隔符截取左邊字符串: # echo ${URL%/*} http://www.baidu.com/baike 以.爲分隔符截取左邊: # echo ${URL%.*} http://www.baidu.com/baike/user 以.爲分隔符截取右邊: # echo ${URL##*.} html
${VAR:-string} 若是VAR變量爲空則返回string ${VAR:+string} 若是VAR變量不爲空則返回string ${VAR:=string} 若是VAR變量爲空則從新賦值VAR變量值爲string ${VAR:?string} 若是VAR變量爲空則將string輸出到stderr
若是變量爲空就返回hello world!:
# VAR= # echo ${VAR:-'hello world!'}
hello world! 若是變量不爲空就返回hello world!:
# VAR="hello" # echo ${VAR:+'hello world!'}
hello world! 若是變量爲空就從新賦值:
# VAR= # echo ${VAR:=hello} hello # echo $VAR hello
若是變量爲空就將信息輸出stderr:
# VAR= # echo ${VAR:?value is null} -bash: VAR: value is null
${}主要用途大概就這麼多了,另外還能夠獲取數組元素。
再介紹下字符串輸出顏色,有時候關鍵地方須要醒目,顏色是最好的方式:
格式:
[ ] \033[1;31;40m # 1是顯示方式,可選。31是字體顏色。40m是字體背景顏色。
[ ] \033[0m # 恢復終端默認顏色,即取消顏色設置。
#!/bin/bash # 字體顏色,顯示方式默認爲空 for i in {31..37}; do echo -e "\033[$i;40mHello world!\033[0m" done # 背景顏色,顯示方式默認爲空 for i in {41..47}; do echo -e "\033[47;${i}mHello world!\033[0m" done # 顯示方式 for i in {1..8}; do echo -e "\033[$i;31;40mHello world!\033[0m" done