寫下這篇文章,是對本身在學習和使用過程當中的總結,文筆不是很好,若是有什麼問題歡迎溝通交流php
Github地址:https://github.com/hi-dhl/fast_guidesjava
Shell是指一種應用程序,這個應用程序提供了一個界面,用戶經過這個界面訪問操做系統內核的服務, Shell腳本(shell script),是一種爲Shell編寫的腳本程序。咱們常常說的shell一般都是指shell腳本。python
Shell跟java、php、Python編程同樣,只要有一個能編寫代碼的文本編輯器和一個能解釋執行的腳本解釋器就能夠了。mysql
Mac OS,Linux 自帶了shell解釋器,Windows比較麻煩,由於Win7專業版和旗艦版默認安裝PowerShell,標準版和家庭版中就沒有安裝的,爲了方便建議安裝cygwinnginx
PHP、Python是屬於高級編程語言,可是也能夠作Shell編程,由於只要有解釋器,也能夠用做腳本編程git
以下是一個Python Shell Script示例(假設文件名叫op_python_base.py):github
#!/usr/bin/env python3 //告訴Python從系統環境中找python
# -*- coding: utf-8 -*- //設置爲UTF-8編碼
for index in range(10):
print(index);
複製代碼
源碼:op_python_basesql
以下是一個PHP Shell Script示例(假設文件名叫op_php_base.php):shell
#!/usr/bin/php
<?php
for($i=0 ;$i<10; $i++){
echo $i;
}
?>
複製代碼
源碼:op_php_baseapache
既然PHP、Python均可以用來寫腳本編程,那爲何還要學習陌生、晦澀難懂的Shell,主要有一下幾個緣由
環境兼容性,Win7專業版和旗艦版默認安裝PowerShell,標準版和家庭版中就沒有安裝的,其餘主流的操做系統都預製了Shell解釋器,因此使用sh、bash編寫,提供給其餘人使用是很是方便的,可是PHP、Python 等等須要安裝相應的環境
若是你想作一些定時任務好比說檢測進程是否存在,自動備份,或者說自動部署環境、服務器之間的數據同步等等sh、bash會是你最好的選擇
sh: Bourne shell,POSIX(Portable Operating System Interface)標準的shell解釋器,它的二進制文件路徑一般是/bin/sh
bash: Bash是Bourne shell的替代品,屬GNU Project,二進制文件路徑一般是/bin/bash
我相信寫過代碼的童鞋,應該對下面的代碼很熟悉並不陌生,(假設文件名叫op_base.sh):
#!/usr/bin/env bash
mkdir code
cd code
for ((i=0; i<3; i++)); do
touch test_${i}.txt
echo "shell很簡單" >> test_${i}.txt
done
複製代碼
第一行:從系統path中尋找指定腳本的解釋程序 第二行:建立 名叫code文件夾 第三行:進入建立的文件夾 第四行:for循環3次 第四行:建立文件 第五行:往建立的文件中寫入信息 第六行:結束循環
mkdir, touch,cd,touch,echo都是系統命令,在命令行下能夠直接執行 for, do, done 是shell腳本語言 for循環的語法
源碼:op_base.sh
新建一個文件,擴展名爲sh(sh表明shell),擴展名並不影響腳本執行,見名知意就好,若是你用php,擴展名爲php,若是你用Python,擴展名爲python
第一行通常是這樣:
#!/usr/bin/php
#!/usr/bin/env python3
#!/usr/bin/env bash 複製代碼
#!」是一個約定的標記,它告訴系統這個腳本須要什麼解釋器來執行 /env 是系統的PATH目錄中查找
chmod +x op_base.sh
./op_base.sh
複製代碼
第一行設置 op_base.sh可執行權限 第二行執行op_base.sh
/bin/sh op_base.sh
複製代碼
定義變量時,變量名前不須要加符號和Python同樣可是在PHP語言中變量須要加$,如:
my_name="jack"
my_name='jack';
複製代碼
ps: 變量名和等號之間不能有空格,變量後面不能有;
Shell中的引號和PHP相似,字符串能夠用單引號,也能夠用雙引號
單引號字符串的限制:
雙引號:
可是在Python中單引號和雙引號是沒有區別,可是Python 還有三個引號,在三個引號內字符都不會被轉義
對於已經定義過的變量,使用的適合在前面添加$
echo $my_name
echo ${my_name}
複製代碼
變量名外面的花括號是可選的,加不加都行,建議使用第二種形式
以「#」開頭的行就是註釋,會被解釋器忽略。
sh裏沒有多行註釋,只能每一行加一個#號。就像這樣:
#--------------------------------------------
# Author: jack
# weibo: OO是有情懷的PM
#
# Notes: 10分鐘入門Shell腳本編程
#
# Project home page:
# https://github.com/dpm100/fast_guides
#--------------------------------------------
複製代碼
字符串能夠用單引號,也能夠用雙引號,也能夠不用引號。單雙引號的區別跟PHP相似
Shell不像其餘語言有php、python 有不少數據類型,在Shell中經常使用的數據類型字符串數字和字符串(ps: 除了數字和字符串,也沒啥其它類型好用了,哈哈)
單引號字符串的限制:
雙引號:
my_name="jack";
my_age="20歲"
echo $my_name $my_age
echo $my_name$my_age
複製代碼
echo ${#my_name}
複製代碼
echo ${my_name:0:2}
複製代碼
源碼:op_str.sh
在Shell中,用括號來表示數組,數組元素用"空格"符號分割開。定義數組的通常形式爲:
name=(name1 name2 name3)
複製代碼
還能夠單獨定義數組的各個份量:
ary[0]=name1
ary[1]=name2
ary[3]=name3
複製代碼
ps: 能夠不使用連續的下標,並且下標的範圍沒有限制
讀取數組元素值的通常格式是:
${數組名[下標]}
複製代碼
例如:
echo ${name[0]}
複製代碼
使用@符號能夠獲取數組中的全部元素,例如:
echo ${name[@]}
複製代碼
獲取數組長度的方法與獲取字符串長度的方法相同,例如:
# 取得數組元素的個數
length=${#name[@]}
echo $length
# 或者
length=${#name[*]}
echo $length
# 取得數組單個元素的長度
lengthn=${#name[n]}
echo $length
複製代碼
源碼:op_arry.sh
和Java、PHP、Python等語言不同,sh的流程控制不可爲空,如(如下爲PHP流程控制寫法):
<?php
if (isset($_GET["q"])) {
search(q);
}
else {
// 不作任何事情
}
複製代碼
在sh/bash裏可不能這麼寫,若是else分支沒有語句執行,就不要寫這個else
if condition1
then
command1
elif condition2
then
command2
else
commandN
fi
複製代碼
例子:
#!/usr/bin/env bash
a=1
b=2
if [ $a == $b ]
then
echo "a 等於 b"
elif [ $a -gt $b ]
then
echo "a 大於 b"
elif [ $a -lt $b ]
then
echo "a 小於 b"
else
echo "沒有符合的條件"
fi
複製代碼
源碼:op_if.sh
Shell的for循環和Python 有點相似
for index in 1,2,3,4,5:
print(index);
複製代碼
for index in 1 2 3 4 5; do
echo "index="$index
done
複製代碼
for ((i=0; i<5; i++)); do
echo "i="$i
done
複製代碼
源碼:op_for.sh
while循環用於不斷執行一系列命令,也用於從輸入文件中讀取數據;命令一般爲測試條件。
int=1
while(( $int<=5 ))
do
echo $int
let "int++"
done
複製代碼
源碼:op_while.sh
sh腳本結合系統命令便有了強大的威力,在字符處理領域,有grep、awk、sed三劍客,grep負責找出特定的行,awk能將行拆分紅多個字段,sed則能夠實現更新插入刪除等寫操做。
path=/var/log
log=${path}/httpd-mysql.log
name=(apache mysql)
exs_init[0]="service httpd start"
exs_init[1]="/etc/init.d/mysqld restart"
for ((i=0; i<2; i++)); do
echo "檢查${name[i]}進程是否存在"
ps -ef|grep ${name[i]} |grep -v grep
if [ $? -eq 0 ]; then
pid=$(pgrep -f ${name[i]})
echo "`date +"%Y-%m-%d %H:%M:%S"` ${name[$i]} is running with pid $pid" >> ${log}
else
$(${exs_init[i]})
echo "`date +"%Y-%m-%d %H:%M:%S"` ${name[$i]} start success" >> ${log}
fi
done
複製代碼
解釋:檢測 nginx、mysql進程是否存在,若是不存在了會自動從新啓動。 腳本每次運行會寫日誌的,沒事能夠去看看該日誌文件,若是進程是否是真的常常性不存在,恐怕就要排查一下深層緣由了。
crontab -e
複製代碼
在文件最後添加一行:
*/5 * * * * /xxx/check_nginx.sh > /dev/null 2>&1
複製代碼
上表示每 5 分鐘,執行一下腳本 /xxx/check_nginx.sh,其中xxx表明路徑
/dev/null 2>&1 的意思是該條shell命令將不會輸出任何信息到控制檯,也不會有任何信息輸出到文件中。
# For details see man 4 crontabs
# Example of job definition:
# .---------------- minute (0 - 59)
# | .------------- hour (0 - 23)
# | | .---------- day of month (1 - 31)
# | | | .------- month (1 - 12) OR jan,feb,mar,apr ...
# | | | | .---- day of week (0 - 6) (Sunday=0 or 7) OR sun,mon,tue,wed,thu,fri,sat
# | | | | |
# * * * * * command to be executed
複製代碼
service crond restart
複製代碼