10分鐘入門Shell腳本編程

前言

寫下這篇文章,是對本身在學習和使用過程當中的總結,文筆不是很好,若是有什麼問題歡迎溝通交流php

Github地址:https://github.com/hi-dhl/fast_guidesjava

Shell是什麼

Shell是指一種應用程序,這個應用程序提供了一個界面,用戶經過這個界面訪問操做系統內核的服務, Shell腳本(shell script),是一種爲Shell編寫的腳本程序。咱們常常說的shell一般都是指shell腳本。python

環境和工具

Shell跟java、php、Python編程同樣,只要有一個能編寫代碼的文本編輯器和一個能解釋執行的腳本解釋器就能夠了。mysql

Mac OS,Linux 自帶了shell解釋器,Windows比較麻煩,由於Win7專業版和旗艦版默認安裝PowerShell,標準版和家庭版中就沒有安裝的,爲了方便建議安裝cygwinnginx

PHP、Python 也能夠做爲Shell編程

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

爲何要學習Shell

既然PHP、Python均可以用來寫腳本編程,那爲何還要學習陌生、晦澀難懂的Shell,主要有一下幾個緣由

  • 環境兼容性,Win7專業版和旗艦版默認安裝PowerShell,標準版和家庭版中就沒有安裝的,其餘主流的操做系統都預製了Shell解釋器,因此使用sh、bash編寫,提供給其餘人使用是很是方便的,可是PHP、Python 等等須要安裝相應的環境

  • 若是你想作一些定時任務好比說檢測進程是否存在,自動備份,或者說自動部署環境、服務器之間的數據同步等等sh、bash會是你最好的選擇

sh與bash

sh: Bourne shell,POSIX(Portable Operating System Interface)標準的shell解釋器,它的二進制文件路徑一般是/bin/sh

bash: Bash是Bourne shell的替代品,屬GNU Project,二進制文件路徑一般是/bin/bash

第一個shell腳本

咱們先來看一個例子

我相信寫過代碼的童鞋,應該對下面的代碼很熟悉並不陌生,(假設文件名叫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

編寫Shell

新建一個文件,擴展名爲sh(sh表明shell),擴展名並不影響腳本執行,見名知意就好,若是你用php,擴展名爲php,若是你用Python,擴展名爲python

第一行通常是這樣:

#!/usr/bin/php
#!/usr/bin/env python3
#!/usr/bin/env bash 複製代碼

#!」是一個約定的標記,它告訴系統這個腳本須要什麼解釋器來執行 /env 是系統的PATH目錄中查找

運行 Shell 腳本有兩種方法:

做爲可執行程序

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 數組

定義數組

在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

Shell 流程控制

和Java、PHP、Python等語言不同,sh的流程控制不可爲空,如(如下爲PHP流程控制寫法):

<?php
if (isset($_GET["q"])) {
    search(q);
}
else {
    // 不作任何事情
}
複製代碼

在sh/bash裏可不能這麼寫,若是else分支沒有語句執行,就不要寫這個else

if

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

for 循環

Shell的for循環和Python 有點相似

Python的for循環
for index in 1,2,3,4,5:
    print(index);
複製代碼
Shell的for循環,第一種寫法
for index in 1 2 3 4 5; do
    echo "index="$index
done
複製代碼
Shell的for循環,第二種寫法
for ((i=0; i<5; i++)); do
    echo "i="$i
done
複製代碼

源碼:op_for.sh

while 語句

while循環用於不斷執行一系列命令,也用於從輸入文件中讀取數據;命令一般爲測試條件。

int=1
while(( $int<=5 ))
do
    echo $int
    let "int++"
done
複製代碼

源碼:op_while.sh

Shell結合系統命令

sh腳本結合系統命令便有了強大的威力,在字符處理領域,有grep、awk、sed三劍客,grep負責找出特定的行,awk能將行拆分紅多個字段,sed則能夠實現更新插入刪除等寫操做。

例如定時檢測nginx、mysql是否被關閉

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進程是否存在,若是不存在了會自動從新啓動。 腳本每次運行會寫日誌的,沒事能夠去看看該日誌文件,若是進程是否是真的常常性不存在,恐怕就要排查一下深層緣由了。

源碼:check_nginx.sh

編輯 /etc/crontab 文件

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
複製代碼
相關文章
相關標籤/搜索