什麼是shell? shell是一個命令解釋器,它在操作系統的最外層,負責直接與用戶對話,把用戶的輸入解釋給操作系統,並處理各種各樣的操作系統的輸出結果,輸出到屏幕返回給用戶。這種對話方式可以是交互的方式(從鍵盤輸入命令,可以立即得到shell的回應),或非交互(執行腳本程式)的方式。下圖的黃色部分... ...
什麼是shell?
shell是一個命令解釋器,它在操作系統的最外層,負責直接與用戶對話,把用戶的輸入解釋給操作系統,並處理各種各樣的操作系統的輸出結果,輸出到屏幕返回給用戶。這種對話方式可以是交互的方式(從鍵盤輸入命令,可以立即得到shell的回應),或非交互(執行腳本程式)的方式。
下圖的黃色部分就是命令解釋器shell處於的操作系統中位置形象圖解。
什麼是shell腳本?
當linux命令或語句不在命令下執行(嚴格說,命令行執行的語句也是shell腳本),而是通過一個程式文件執行時,該程式就被稱為shell腳本或shell程式,shell程式很類似DOS系統下的批處理程式(擴展名*.bat)。用戶可以在shell腳本中敲入一系列的命令或命令語句組合。這些命令、變數和流程式控制制語句等有機的結合起來就形成了一個功能很強大的shell腳本。
下麵是在windows下利用批處理程式bat開發的備份網站及資料庫數據的腳本。
@echo off
set date=%date:`0,4%-%date:`5,2%-%date:`8,2%
mysqldump -uroot -poldboy -A -B > D:\bak\"%date%".sql
rar.exe a -k -r -s -ml D:\bak\"%date%".sql.rar D:\bak\"%date%".sql
del D:\bak\*.sql
rar.exe a -k -r -s -ml D:\bak\"%date%"htdocs.rar D:\work\htdocs
示例1:清除/var/log下messages日誌文件的簡單命令腳本。
#把所有命令放在一個文件里堆積起來就形成了腳本,下麵是一個最簡單的命令堆積形成的shell腳本
#root身份運行
#清楚日誌
cd /var/log
cat /dev/null > messages
echo "Logs cleaned up."
上述腳本存在如下問題:
1、如果不是root用戶無法執行清理日誌。
2、無流程式控制制語句,沒有判斷和邏輯。
示例2:包含命令、變數和流程式控制制語句的清除/var/log下messages日誌文件的shell腳本。
#!/bin/bash
#清除日誌腳本
LOG_DIR=/var/log
ROOT_UID=0 #$UID為0的時候,用戶才具有root用戶的許可權
#使用root運行
if [ "$UID" -ne "$ROOT_UID" ]
then
echo "Mast be root to run this script."
exit 1
fi
cd $LOG_DIR || {
echo "Cannot change to necessary directory." >&2
exit 1
}
cat /dev/null > messages && echo "Logs cleaned up."
exit 0
#退出之前返回0表示成功,返回1表示失敗。
拓展:清空日誌及文件內容的三種方法。
[root@lamp ~]# echo >test.log
[root@lamp ~]# >test.log
[root@lamp ~]# cat /dev/null > test.log
shell腳本在運維工作中的地位
shell腳本很擅長處理純文本類型的數據,而linux系統中幾乎所有的配置文件(如nfs、rsync、httpd、nginx、lvs等)、多數啟動文件都是純文本類型的文件。因此利用shell可以在linux系統中發揮巨大作用。
shell腳本語言的種類
在UNIX/LINUX中主要有兩大類shell。
Bourne shell包括sh、ksh和bash。
Bourne shell (sh)
Korn shell (ksh)
Bourne Again shell (bash)
POSIX shll (sh)
C shell包括csh和tcsh。
C shell (csh)
TEXES/TOPS C shell(tcsh)
shell腳本語言是若類型語言,較為通用的shell有標準的Bourne shell(sh)和C shell(csh)。其中Bource shell(sh)已經被bash shell取代。
查看系統的shell。
[root@lamp ~]# cat /etc/shells
/bin/sh
/bin/bash #功能更強大
/sbin/nologin
/bin/dash
/bin/tcsh
/bin/csh
常用操作系統的預設shell
Linux是bourne agaion shell(bash)。
Solaris和FreeBSD預設的是Bourne shll(sh)。
AIX下是korn shell(ksh)。
HP-UX預設的是POSIX shell(sh)。
查看CentOS預設shell。
第一種方法。
[root@lamp ~]# echo $SHELL
/bin/bash
[root@lamp ~]# echo $shell
bash
第二種方法。
[root@lamp ~]# grep root /etc/passwd
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
更改預設的shell配置文件。
[root@lamp ~]# cat /etc/default/useradd
# useradd defaults file
GROUP=100
HOME=/home
INACTIVE=-1
EXPIRE=
SHELL=/bin/bash
SKEL=/etc/skel
CREATE_MAIL_SPOOL=yes
shell腳本的建立和執行
shell腳本的建立。
在linux系統中,shell腳本(bash shll程式)通常是在編輯器(如vi/vim)中編寫,由Unix/Linux命令、bash shell命令、程式結構控制語句和註釋等內容組成,推薦使用vim編輯器編寫,可以事先做一個別名alias vi='vim'。
[root@lamp ~]# echo "alias vi='vim'" >>/etc/profile
[root@lamp ~]# tail -n 1 /etc/profile
alias vi='vim'
[root@lamp ~]# source /etc/profile
[root@lamp ~]# . /etc/profile
腳本開頭(第一行)
一個規範的shell腳本在腳本第一行會指出由哪個程式(解釋器)來執行腳本中的內容,這一行內容在linux bash編程中一般為:
#! /bin/bash
或
#! /bin/sh <==255個字元以內
其中開頭的"#!"字元又稱為幻數,在執行bash腳本的時候,內核會根據"#!"後的解釋器來確定該用哪個程式解釋這個腳本的內容。註意,這一行必須在每個腳本頂端的第一行,如果不是第一行則為腳本註釋行,例如下麵的例子。
不加上訴第一行,預設就會使用linux預設的shell。
[root@lamp ~]# cat test.sh
#!/bin/bash
echo "shell start"
#!/bin/bash #寫到這裡表示註釋
#!/bin/sh
echo "shell end"
sh和bash的區別,早期的bash與sh稍有不同,它還包含了csh和ksh的特色,但大多數腳本都可以不加修改的在sh上運行。
[root@lamp ~]# ll /bin/sh
lrwxrwxrwx. 1 root root 4 Mar 10 2017 /bin/sh -> bash
[root@lamp ~]# ll /bin/bash
-rwxr-xr-x. 1 root root 941944 Jan 12 2017 /bin/bash
sh為bash的軟連接,推薦用標準寫法#!/bin/bash。
註意,當使用/bin/sh執行腳本不正常的時候,可以使用/bin/bash執行。
bash的版本
[root@lamp ~]# bash -version
GNU bash, version 4.1.2(2)-release (x86_64-redhat-linux-gnu)
Copyright (C) 2009 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software; you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
腳本註釋
在shell腳本中,跟在(#)井號後面的內容表示註釋,用來對腳本進行註釋說明,註釋部分不會被當做程式執行,僅僅是給用戶看,系統解釋器是看不到的,更不會執行。註釋可自成一行,也可以跟在腳本命令後面與命令在同一行。開發腳本時,如果沒有註釋,團隊里的其他人就很難理解腳本究竟在做什麼,如果時間上了自己也會忘記。因此,我們要儘量養成為所開發的shell腳本書寫註釋的習慣。註釋書寫註意規範性,儘量不用中文。
shell腳本的執行
當shell腳本運行時,它會先查找系統環境變數ENV,該變數指定了環境文件(通常是.bashrc、.bash_profile、/etc/bashrc、/etc/profile等),然後從該環境變數文件開始執行腳本,當讀取了ENV的文件後,shell會開始執行shell腳本中的內容。
特殊技巧:設置crond任務時,最好把系統環境變數在定時任務腳本中重新定義,否則,一些系統環境變數將不會被載入。
shell腳本的執行通常可以採用以下幾種方式:
1、bash script-name或sh script-name(推薦使用)。
2、path/script-name或./script-name(當前路徑下執行腳本,需要腳本有執行許可權)。
3、source script-name或. scripts-name("."點號)。
4、sh<script-name或cat script-name|sh(同樣適合bash)。
執行說明
第一種方法是當腳本文件本身沒有可執行許可權(即文件x位為-號)時常使用的方法,或者文件開頭沒有指定解釋器。
第二種方法需要先將腳本文件的許可權改為可執行(即文件加X位),具體方法:chmod u+x script-name或chmod 755 script-name。然後通過腳本路徑就可以直接執行腳本。
第三種放法通常是使用source或"."點號讀入或載入指定的shell腳本文件(如test.sh),然後,依次執行指定shell腳本文件test.sh中的所有語句。
舉例說明:
[root@lamp ~]# cat >test.sh
echo 'i am shell'
輸入"echo 'i am shell'"內容後按回車,然後再按ctrl+d組合鍵即可結束編輯。
1)通過第一種方法執行
[root@lamp ~]# cat test.sh
echo 'i am shell'
[root@lamp ~]# sh test.sh
i am shell
[root@lamp ~]# bash test.sh
i am shell
2)通過第二種方法執行
[root@lamp ~]# ll test.sh
-rw-rw-r--. 1 root root 18 Jul 24 23:20 test.sh
[root@lamp ~]# ./test.sh #使用第二種方式,"./"在當前目錄下執行test.sh腳本文件,無法使用tab自動補全
-bash: ./test.sh: Permission denied
給test.sh添加可執行許可權。
[root@lamp ~]# chmod u+x test.sh
[root@lamp ~]# ./test.sh
i am shell
3)通過第三種方法執行
[root@lamp ~]# . test.sh
i am shell
[root@lamp ~]# source test.sh
i am shell
4)通過第四種方法執行
[root@lamp ~]# sh <test.sh
i am shell
[root@lamp ~]# cat test.sh|bash
i am shell
案例:已知如下命令及返回結果,請問echo $user的返回結果為()。
[root@lamp ~]# cat test.sh
user=`whoami`
[root@lamp ~]# sh test.sh
[root@lamp ~]# echo $user
答案:空。
[root@lamp ~]# . test.sh
[root@lamp ~]# echo $user
答案:root
結論:1、子shell會直接繼承父shell的變數、函數等。2、如果希望父shell調用子shell的變數、函數等,用source或"."點號執行腳本。
shell腳本開發的基本習慣
1)腳本第一行指定腳本解析器。
#!/bin/sh或#!/bin/bash
2)腳本開頭加版本版權等信息
#Date: 07:00 2018-07-26
#Mail:xxxxx@xxx
#Author:Created by golden
#Function:This scripts function is ...
#Version:1.3
提示:可以配置vim編輯文件時自動加上以上信息,方法是修改~/.vimrc配置文件。
3)腳本中不用中文註釋
儘量用英文註釋,防止本機或切換系統環境後中文亂碼的困擾。
4)腳本以.sh為擴展名命名。
5)代碼書寫優秀習慣技巧
1、成對的符號內容儘量一次寫出來,防止遺漏。
2、"[]"中括弧兩端要有空格,書寫時即可留出空格[ ],然後在退格書寫內容,先書寫一對中括弧,然後退一格,然後在輸入兩個空格,再退一格。
雙中括弧"[[]]"也是如此。
3、流程式控制制語句一次書寫完,在添加內容。
if語句格式一次完成。
if 條件內容
then
內容
fi
for迴圈格式一次完成。
for
do
內容
done
6)通過縮進讓代碼更易讀。