命令解析器——例如bash
?
是一個(gè)程序,可以解析shell命令
?
shell基本語法
?
變量
?
環(huán)境變量
- 敲命令“env”可以取出所有環(huán)境變量
- 環(huán)境變量可以當(dāng)全局變量來使用
- set命令可以輸出當(dāng)前系統(tǒng)的全部環(huán)境變量以及函數(shù)
- unset命令用于刪除一個(gè)環(huán)境變量
?
本地變量
自定義的變量——局限在某個(gè)腳本中使用
?
1、變量定義:
- shell中的變量沒有數(shù)據(jù)類型 - 默認(rèn)值都是string類型
VAR=hello? or VAR=“hello”
注意事項(xiàng):
- 定義shell變量的時(shí)候,建議變量名大寫
- 賦值的時(shí)候=前后不能有空格
?
2、一些命令實(shí)例
將一個(gè)命令執(zhí)行之后的結(jié)果賦值給某個(gè)變量(下面兩種方式都可以)
var=`pwd`
var=$(pwd)
算術(shù)運(yùn)算(只能在整型之間做算數(shù)運(yùn)算)
var=9
var=$((var 10))
var=$[var 10]
用export命令可以把本地變量導(dǎo)出為環(huán)境變量
export VARNAME //只在當(dāng)前終端中有效
export VARNAME=value
?
?
位置變量
- $0 ????????-?? 相當(dāng)于C語言main函數(shù)的argv[0]
- $1、$2...相當(dāng)于C語言main函數(shù)的argv[1]、argv[2]...
?
特殊變量
- $#: 這個(gè)程序的參數(shù)個(gè)數(shù)
- $*: 表示參數(shù)列表"$1" "$2" ...
- $@:? 表示參數(shù)列表"$1" "$2" ...
- $$: 這個(gè)程序的PID
- $?: 執(zhí)行上一個(gè)命令的返回值
?
注意!?。〖由稀啊敝?,$*和$@會(huì)發(fā)生變化!?。?/strong>
- for循環(huán)時(shí)候"$*" 將所有的參數(shù)作為一個(gè)整體
- for循環(huán)時(shí)候"$@" 有多少個(gè)參數(shù)被拆分成幾部分
?
?
命令代換
?
將執(zhí)行完命令之后得到的數(shù)據(jù)保存到變量
VAR=`shell命令`
VAR=$(shell命令) -- 常用,推薦使用
?
算術(shù)代換
?
1、對(duì)變量取值
在變量的前邊加 $
$VAR
?
2、對(duì)變量做算術(shù)運(yùn)算
- 算術(shù)運(yùn)算: -*/
- 算術(shù)運(yùn)算操作的必須是整數(shù)
- VAR=$(($VAR*10))
- VAR=$[$VAR-10]
?
3、進(jìn)制運(yùn)算
$[base#n] 數(shù)值按照幾進(jìn)制進(jìn)行運(yùn)算
- base - 進(jìn)制
- #連接符
- n:數(shù)值
?
?
轉(zhuǎn)義字符
\
- 將有特殊意義的字符變成普通字符
- 將普通字符變成有特殊意義的字符 - 正則表達(dá)式中使用
?
單引號(hào)
VAR='$(date)'
單引號(hào)中的內(nèi)容原樣輸出
?
雙引號(hào)
VAR="$(date)"
會(huì)繼續(xù)雙引號(hào)中的命令, 輸出結(jié)果字符串
?
?
?
條件測(cè)試
?
條件測(cè)試命令
?
下面兩種方式皆可
?
比較?test , [] , [[]]
- test 和 [ 是 bash 的內(nèi)部命令
- [[ 是 bash 程序語言的關(guān)鍵字!
- 絕大多數(shù)情況下,這個(gè)三個(gè)功能通用。但是命令和關(guān)鍵字總是有區(qū)別的。
區(qū)別:
- 在 [[ 中使用 && 和 ||
- [ 中使用 -a 和 -o 表示邏輯與和邏輯或
?
?
如何判斷條件是否成立?
?
- 如果返回值為0: 成立
- 返回值為非0:??? 不成立
?
例子:
上圖中pwd執(zhí)行成功了,因此返回值是0
?
?
?
文件狀態(tài)測(cè)試
?
linux中的文件種類: 7種
- 普通文件:? f
- 目錄: d
- 符號(hào)鏈接: l
- 套接字:s
- 管道:p
- 字符設(shè)備:c
- 塊設(shè)備:b
?
-b filename
|
當(dāng)filename 存在并且是塊文件時(shí)返回真(返回0)
|
-c filename
|
當(dāng)filename 存在并且是字符文件時(shí)返回真
|
-d pathname
|
當(dāng)pathname 存在并且是一個(gè)目錄時(shí)返回真
|
-e pathname
|
當(dāng)由pathname 指定的文件或目錄存在時(shí)返回真
|
-f filename
|
當(dāng)filename 存在并且是正規(guī)(普通)文件時(shí)返回真
|
-g pathname
|
當(dāng)由pathname 指定的文件或目錄存在并且設(shè)置了SGID 位時(shí)返回真
|
-h/-L filename
|
當(dāng)filename 存在并且是符號(hào)鏈接文件時(shí)返回真 (或? filename)
|
-k pathname
|
當(dāng)由pathname 指定的文件或目錄存在并且設(shè)置了"粘滯"位時(shí)返回真
|
-p filename
|
當(dāng)filename 存在并且是命名管道時(shí)返回真
|
-r pathname
|
當(dāng)由pathname 指定的文件或目錄存在并且可讀時(shí)返回真
|
-s filename
|
當(dāng)filename 存在并且文件大小大于0 時(shí)返回真
|
-S filename
|
當(dāng)filename 存在并且是socket 時(shí)返回真
|
-t fd
|
當(dāng)fd 是與終端設(shè)備相關(guān)聯(lián)的文件描述符時(shí)返回真
|
-u pathname
|
當(dāng)由pathname 指定的文件或目錄存在并且設(shè)置了SUID 位時(shí)返回真
|
-w pathname
|
當(dāng)由pathname 指定的文件或目錄存在并且可寫時(shí)返回真
|
-x pathname
|
當(dāng)由pathname 指定的文件或目錄存在并且可執(zhí)行時(shí)返回真
|
-O pathname
|
當(dāng)由pathname 存在并且被當(dāng)前進(jìn)程的有效用戶id 的用戶擁有時(shí)返回真(字母O 大寫)
|
-G pathname
|
當(dāng)由pathname 存在并且屬于當(dāng)前進(jìn)程的有效用戶id 的用戶的用戶組時(shí)返回真
|
file1 -nt file2
|
file1 比file2 新時(shí)返回真
|
file1 -ot file2
|
file1 比file2 舊時(shí)返回真
|
f1 -ef f2
|
files f1 and f2 are hard links to the same file
|
?
例如,測(cè)試文件filename是否為目錄文件
?
?
?
常見字符串測(cè)試
?
-z string
|
字符串string 為空串(長(zhǎng)度為0)時(shí)返回真
|
-n string
|
字符串string 為非空串時(shí)返回真
|
str1 = str2
|
字符串str1 和字符串str2 相等時(shí)返回真
|
str1 == str2
|
同 =
|
str1 != str2
|
字符串str1 和字符串str2 不相等時(shí)返回真
|
?
?
?
常見的數(shù)值測(cè)試
?
- ==—— eq? —— equal
- !=——ne—— not equal
- >——gt??—— greater than
- >=——ge——greater than equal
- <——lt???——less than
- <=—— le —— less than equal
?
nt1 -eq int2
|
如果int1 等于int2,則返回真
|
int1 -ne int2
|
如果int1 不等于int2,則返回真
|
int1 -lt int2
|
如果int1 小于int2,則返回真
|
int1 -le int2
|
如果int1 小于等于int2,則返回真
|
int1 -gt int2
|
如果int1 大于int2,則返回真
|
int1 -ge int2
|
如果int1 大于等于int2,則返回真
|
?
?
?
測(cè)試時(shí)使用的邏輯操作符
?
- a - &&? : and
- o - ||: or
- 取反: !
-a
|
邏輯與,操作符兩邊均為真,結(jié)果為真,否則為假。
|
-o
|
邏輯或,操作符兩邊一邊為真,結(jié)果為真,否則為假。
|
!
|
邏輯否,條件為假,結(jié)果為真。
|
?
?
?
?shell腳本語法 - 分支
?
if/then/elif/else/fi
?
語法格式
if [ 條件判斷語句 ];then
處理語句
處理語句
elif [ 條件判斷語句 ]
then
處理語句
處理語句
else
處理語句
處理語句
fi
?
:——是一個(gè)特殊的命令,稱為空命令
- 該命令不做任何事,但Exit Status總是真。
?
if :; then
xxxx
fi
?
?
case/esac
?
基本語法
case 變量 in
yes|Yes|y|Y)
處理語句
處理語句
;;
No|no|n|N)
處理語句
處理語句
;;
*)
處理語句
;;
esac
- *類似于default
- case類似于switch
- ::類似于break
?
例子
a.sh
./a.sh aa
VAR=$1
case VAR in
a*|AA|a|A)
echo "a"
;;
b|bb|BB)
echo b
;;
*)
echo "hello"
;;
esac
?
?
?shell腳本語法 - 循環(huán)
?
for/do/done
?
語法格式
for 變量 in list(列表);do
控制語句
控制語句
done
?
例子(下面兩個(gè)for循環(huán)的結(jié)果相同)
for VAR in $(ls) ;do
echo $VAR
done
for VAR in `ls` ;do
echo $VAR
done
?
?
while/do/done
?
語法格式
while [ 條件測(cè)試語句 ];do
控制語句
控制語句
done
?
例子——輸入三次密碼,三次錯(cuò)誤退出程序
PWD=world
count=1
echo "請(qǐng)輸入密碼"
read TMP
while [ $TMP != $pwd -a $count le 3 ];do
echo "密碼錯(cuò)誤,請(qǐng)重新輸入"
read TMP
count=$[count 1]
do
?
?
break和continue
?
break 可以選擇跳出的層數(shù)
break n
?
?
?
輸入和輸出
?
echo
echo 字符串
- -e: 解析字符串中的\n字符
- -n:去掉echo默認(rèn)加上的換行符
?
例子:
?
?
?
文件重定向
?
cmd > file
?
cmd >> file
?
例子——將指令cmd的標(biāo)準(zhǔn)輸出(1)重定向到file,標(biāo)準(zhǔn)錯(cuò)誤(2)重定向到標(biāo)準(zhǔn)輸出(1)——標(biāo)準(zhǔn)輸出和標(biāo)準(zhǔn)錯(cuò)誤都寫入file文件中
cmd > file 2>&1
#等價(jià)于
cmd 1 > file 2 > &1
- 1前面加&代表1是文件描述符,不加&,則1代表一個(gè)文件
?
?
?awk
?
處理行和列,主要用于列的處理
?
1、awk缺省的行分隔符是換行
2、缺省的列分隔符是連續(xù)的空格和Tab
3、如何取出每一列
- $0: 當(dāng)前行,還沒有拆分
- $1: 第一列
- $2: 第二列
- 。。。。。
?
4、如果不是缺省分隔符的如何指定分隔符
?
5、例子——拆分/etc/passwd,找到每個(gè)用戶對(duì)應(yīng)的家目錄
awk -F: '{print $6}' /etc/passwd
?
?
一般格式
?
awk 參數(shù) '/pattern/{actions}' 目標(biāo)文件
awk 參數(shù) 'condition{actions}' 目標(biāo)文件
awk 參數(shù) 腳本文件 目標(biāo)文件
- condition -- 條件
- pattern -- 正則表達(dá)式
- actions -- 匹配成功后的一系列操作
?
例子——找出以g開頭的字符串的第三列
awk -F/ '/^g/{print $3}' test
?
?
如何定義變量
?
- 需要變量直接寫即可,默認(rèn)值0
- 定義變量的時(shí)候直接指定一個(gè)初始值——利用“-v”設(shè)定初始值
awk -v x=10 '條件/正則表達(dá)式{action} ' 文件名
?
?
?
練習(xí):從ps aux得到的數(shù)據(jù)中找出pid>1000 && pid <2000的進(jìn)程的個(gè)數(shù)
?
第一步——找出所有進(jìn)程號(hào)在1000到2000之間的進(jìn)程
ps -aux | awk '$2>1000 && $2<2000{print $2}'
?
第二步,設(shè)置變量x(x的默認(rèn)值為0),用于記錄當(dāng)前符合條件的進(jìn)程號(hào)是第幾個(gè)符合條件的
ps -aux | awk '$2>1000 && $2<2000{print $2; x=x 1; print x}'
?
第三步,添加條件END(END——代表遍歷結(jié)束)
ps -aux | awk '$2>1000 && $2<2000{x=x 1}END{print x}'
?
?
?
shell腳本例子一
#!/bin/bash
# 關(guān)閉tracker 和 storage服務(wù)
#shell腳本沒有返回值,沒有參數(shù),但是可以傳參
tracker_start()
{
#查找名為fdfs_trackerd的進(jìn)程; grep -v grep的意思是過濾掉grep進(jìn)程
#> /dev/null重定向到垃圾回收站,扔進(jìn)去之后,輸出就沒有了
ps aux | grep fdfs_trackerd | grep -v grep > /dev/null
#如果查到了該進(jìn)程,則$?的值是0
if [ $? -eq 0 ];then
echo "fdfs_trackerd 已經(jīng)在運(yùn)行中, 無需啟動(dòng)..."
else
#說明該進(jìn)程沒有被啟動(dòng)
sudo fdfs_trackerd /etc/fdfs/tracker.conf
if [ $? -ne 0 ];then
echo "tracker start failed ..."
else
echo "tracker start success ..."
fi
fi
}
storage_start()
{
ps aux | grep fdfs_storaged | grep -v grep > /dev/null
if [ $? -eq 0 ];then
echo "fdfs_storaged 已經(jīng)在運(yùn)行中, 無需啟動(dòng)..."
else
sudo fdfs_storaged /etc/fdfs/storage.conf
if [ $? -ne 0 ];then
echo "storage start failed ..."
else
echo "storage start success ..."
fi
fi
}
#如果沒傳入?yún)?shù)
if [ $# -eq 0 ];then
echo "Operation:"
echo " start storage please input argument: storage"
echo " start tracker please input argument: tracker"
echo " start storage && tracker please input argument: all"
echo " stop storage && tracker input argument: stop"
exit 0
fi
case $1 in
storage)
storage_start
;;
tracker)
#調(diào)用shell函數(shù)tracker_start
tracker_start
;;
all)
storage_start
tracker_start
;;
stop)
sudo fdfs_trackerd /etc/fdfs/tracker.conf stop
sudo fdfs_storaged /etc/fdfs/storage.conf stop
;;
*)
echo "nothing ......"
esac
?
get技能
1、? ?grep -v grep? ? ——過濾掉grep
?
2、> /dev/null——將輸出扔掉
?
?
?
shell腳本例子二
#!/bin/bash
#定義變量
START=1
STOP=1
case $1 in
start)
START=1
STOP=0
;;
stop)
START=0
STOP=1
;;
"")
STOP=1
START=1
;;
*)
STOP=0
START=0
;;
esac
# **************************** 殺死正在運(yùn)行的CGI進(jìn)程 ****************************
if [ "$STOP" -eq 1 ];then
# 登錄
kill -9 $(ps aux | grep "./bin_cgi/login" | grep -v grep | awk '{print $2}') > /dev/null 2>&1
echo "CGI 程序已經(jīng)成功關(guān)閉, bye-bye ..."
fi
# ******************************* 重新啟動(dòng)CGI進(jìn)程 *******************************
if [ "$START" -eq 1 ];then
# 登錄 -n代表不加換行
echo -n "登錄:"
spawn-fcgi -a 127.0.0.1 -p 10000 -f ./bin_cgi/login
echo "CGI 程序已經(jīng)成功啟動(dòng) ^_^..."
fi
?
?
get技能
?
1、> /dev/null 2>&1——將標(biāo)準(zhǔn)輸出和標(biāo)準(zhǔn)錯(cuò)誤全都扔掉
?
2、 echo -n ——不加換行
?
?
shell腳本例子三
#!/bin/bash
NAME=redis
FILE=redis.pid
# 判斷redis目錄是否存在, 如果不存在則創(chuàng)建
is_directory()
{
#如果傳入的第一個(gè)參數(shù)不是目錄
if [ ! -d $1 ]; then
echo "$1 目錄創(chuàng)建中..."
mkdir $1
if [ $? -ne 0 ];then
echo "$1 目錄創(chuàng)建失敗, ~~~~(>_<)~~~~"
exit 1
fi
fi
}
# 判斷redis目錄是否存在, 如果不存在則創(chuàng)建
is_regfile()
{
if [ ! -f $1 ]; then
#statements
echo "$1 file not exist..."
return 1
fi
return 0
}
# 根據(jù)參數(shù)設(shè)置redis狀態(tài)
#提示用戶需要傳入?yún)?shù)
if [[ $1 = "" ]];then
echo "please input argument:"
echo " start: start redis server"
echo " stop: stop redis server"
echo " status: show the redis server status"
exit 1
fi
# 函數(shù)調(diào)用,函數(shù)傳入的參數(shù)是$NAME
is_directory $NAME
case $1 in
start)
# 判斷 redis-server 進(jìn)程是否已經(jīng)啟動(dòng)...
ps aux | grep "redis-server" | grep -v grep > /dev/null
if [ $? -eq 0 ];then
echo "Redis server is runing ..."
else
# 刪除$FILE 文件
unlink "$NAME/$FILE"
echo "Redis starting ..."
redis-server ./conf/redis.conf
if [ $? -eq 0 ];then
echo "Redis server start success!!!"
# 休眠1s, 等待pid文件被創(chuàng)建出來, 再進(jìn)行后續(xù)判斷
sleep 1
if is_regfile "$NAME/$FILE";then
# printf是一個(gè)命令,用于在中斷進(jìn)行輸出
printf "****** Redis server PID: [ %s ] ******\n" $(cat "$NAME/$FILE")
printf "****** Redis server PORT: [ %s ] ******\n" $(awk '/^port /{print $2}' "./conf/redis.conf")
fi
fi
fi
;;
stop)
# 判斷 redis-server 進(jìn)程是否已經(jīng)啟動(dòng)...
ps aux | grep "redis-server" | grep -v grep > /dev/null
if [ $? -ne 0 ];then
echo "Redis server is not runing..."
exit 1
fi
echo "Redis stopping ..."
# 判斷pid文件是否存在
#調(diào)用函數(shù)is_regfile,傳入的參數(shù)羅列在函數(shù)調(diào)用的后面,即$NAME/$FILE
if is_regfile "$NAME/$FILE"; then
# 讀進(jìn)程文件
echo "### 通過 redis.pid文件 方式關(guān)閉進(jìn)程 ###"
PID=$(cat "$NAME/$FILE")
else
# 查找進(jìn)程ID
echo "### 通過 查找進(jìn)程ID 方式關(guān)閉進(jìn)程 ###"
PID=$(ps aux | grep "redis-server" | grep -v grep | awk '{print $2}')
fi
echo Redis server pid = $PID
kill -9 $PID
if [ $? -ne 0 ]; then
echo "Redis server stop fail ..."
else
echo "Redis server stop success!!!"
fi
;;
status)
ps aux | grep "redis-server" | grep -v grep > /dev/null
if [ $? -eq 0 ];then
echo "Redis server is running..."
else
echo "Redis server is not running ..."
fi
;;
*)
echo "do nothing ..."
;;
esac
?
?
?
來源:http://www./content-3-123051.html
|