標籤:shell指令碼
本文是在學習《跟老男孩學Linux營運之shell編程實戰》這本書時記錄的知識點。看了這本書,我受益匪淺,當然這僅是我個人觀點。下面我們言歸正傳,開始瞭解一下shell指令碼吧!
shell本身是一個命令直譯器,它的作用是解釋執行使用者輸入的命令及程式等。
shell指令碼語言的種類:sh、ksh、bash、csh、tcsh,Linux中主流的shell是bash,所以本文及後續shell指令碼以bash為主。
那我們如何查看Linux系統中預設的shell?
[[email protected] ~]# cat /etc/redhat-release ==>查看Linux系統版本
CentOS release 6.8 (Final)
[[email protected] ~]# echo $SHELL ==>查看系統預設的shel
/bin/bash
指令碼的書寫規範:
1. 指令碼開頭第一行
一個規範的shell指令碼在第一行會指出由哪個程式(解譯器)來執行指令碼中的內容。
在Linux bash的編程中一般為:
#!/bin/bash
或
#!/bin/sh
提示:
sh為bash的軟串連,大多數情況下,指令碼的開頭使用“#!/bin/bash”和“#!/bin/sh”是沒有區別 的, 但更為規範的寫法是在指令碼的開頭使用“#!/bin/bash”。
由於老版本的bash中被暴露出存在較嚴重的安全性漏洞,所以我們需要檢測現有系統中的bash版本是否存在漏洞,那如何檢測是否存在漏洞呢?方法如下:
[[email protected] ~]# env x=‘() { ;;}; echo be careful‘ bash -c "echo this is a test"
this is a test
如果返回如下兩行,則表示需要儘快升級bash,不過,僅僅是用於學習和測試就無所謂了。
be careful
this is a test
提示:升級方法:yum -y update bash
提示:
(1)不同語言的指令碼的開頭第一行有所不同,具體如下:
#!/bin/sh
#!/bin/bash
#!/usr/bin/awk
#!/bin/sed
#!/usr/bin/tcl
#!/usr/bin/expect ==>expect解決互動語言開頭解譯器
#!/usr/bin/perl ==>perl語言解譯器
#!/usr/bin/env python ==>python語言解譯器
不同的指令碼一般會儲存為不同的副檔名,例如:
shell指令碼:xxx.sh
Python指令碼:xxx.py
expect指令碼:xxx.exp
(2)查看bash的版本:
[[email protected] ~]# bash --version
2.指令碼注釋:
在shell指令碼中,“#”號開頭的表示注釋,用來對指令碼進行注釋說明。
3.指令碼的執行:
當shell指令碼運行時,會先尋找系統內容變數ENV,該變數指定了環境變數檔案(載入順序通常是/etc/profile、~/.bash_profile、
~/.bashrc、/etc/bashrc等),載入完上述環境變數後,shell就開始執行shell指令碼中的內容。
shell指令碼是從上至下,從左至右一次執行每一行的命令及語句,即執行完一個命令後再執行下一個,如果在shell指令碼中遇到子指令碼,就會先執行子指令碼的內容,完成後再返回父指令碼繼續執行父指令碼內後續的命令及語句。
提示:設定Linux的crond任務時,最好能在定時任務指令碼中重新定義系統內容變數,否則,一些系統內容變數將不會被載入。
shell指令碼執行的方法:
(1)bash script-name或sh script-name :當指令檔本身沒有可執行許可權時常使用的方法或指令檔開頭沒有指定解譯器時需要使用的方法。
(2)path/script-name或./script-name:指在指令碼的當前路徑下執行指令碼(前提是指令碼需要有執行許可權)
(3)source script-name或 . script-name:這種方法通常是使用source或"."讀入或載入指定的shell指令檔(如san.sh)。依次執行指令碼san.sh中的所有語句。這些語句將在當前父shell指令碼father.sh進程中運行(其他幾種模式都會啟動新的進程執行子shell)。因此,使用source或“.”可以將san.sh指令碼中的變數值或函數等的傳回值傳遞到當前父shell指令碼father.sh中使用,這是它與其他幾種方法最大的區別。
source或“.”命令的功能:在當前shell中執行source或“.”載入並執行的相關指令檔中的命令及語句,而不是產生一個子shell來執行檔案中的命令。
(4)sh<script-name或 cat script-name|sh:同樣適用於bash,這種方法使用的比較少。
結論:
通過source或“.”載入執行過的指令碼,由於是在當前shell中執行指令碼,因此在指令碼結束後,指令碼中的變數(包括函數)值在當前shell中依然存在,而sh和bash執行指令碼都會啟動新的子shell執行,執行完成後退回到父shell,因此變數(包括函數)值等無法保留。在進行shell指令碼開發時,如果指令碼中有引用或執行其他指令碼的內容或設定檔的需求時,最好用source或“.”先載入該指令碼或設定檔,處理完後,再將它載入到指令碼的下面,就可以調用source或“.”載入的指令碼及設定檔中的變數及函數等內容了。
4.shell指令碼的基本規範及習慣:
(1)shell指令碼的第一行是指定指令碼解譯器,通常為:
#!/bin/bash
或
#!/bin/
(2)shell指令碼的開頭會加版本、著作權等資訊:
#Date:2017-04-17
#Author:Create by XiaoYu
#Description:This script function is ...
#Version:1.1
可以修改~/.vimrc設定檔配置vim編輯檔案時自動加上以上資訊的功能。
(3)在shell指令碼中盡量不用中文
在shell指令碼中盡量用英文注釋,防止亂碼問題,如果非要載入中文,請根據自身的用戶端對系統進行字元集調整,如:export LANG="zh_CN.UTF-8",並在指令碼中重新定義字元集設定,和系統保持一致。
(4)shell指令碼的命名應以.shw為副檔名。
(5)shell指令碼應存放在固定的路徑下,如:/server/scripts/
5.shell指令碼代碼書寫的良好習慣:
(1)成對的符號應盡量一次性寫出來,然後退格在符號裡增加內容,以防止遺漏。
成對的符號包括:{ }、[ ] 、‘ ’、反撇號、“ ”
(2)中括弧[ ]兩端至少要有1個空格。
(3)對於流程式控制制語句,應一次性將格式寫完,再新增內容。 如:
if語句:
if 條件內容
then
內容
fi
for迴圈:
for
do
內容
done
提示:while和until、case等語句也一樣。
(4)通過縮排,讓代碼更易讀。
(5)對於常規變數的字串定義變數值應加雙引號,並且等號前後不能有空格,需要所見即所得 (WYSIWYG)的字元引用,則用單引號,如果是命令的引用,則用反撇號。
(6)指令碼中的單引號、雙引號及反撇號必須為英文狀態下的符號。
以上為本人在讀《跟老男孩學Linux營運之shell編程實戰》這本書時的筆記,如有任何著作權問題,請聯絡[email protected]。
本文出自 “shayatou_1990” 部落格,請務必保留此出處http://shayatou1990.blog.51cto.com/12806916/1916590
《跟老男孩學Linux營運之shell編程實戰》-第一章 shell指令碼初步入門