if … then
单层、简单条件判断式
if [ 条件判断式 ]; then
当条件判断式成立时,可以进行的指令工作内容;
fi <==将 if 反过来写,就成为 fi 啦!结束 if 之意!
括号与括号之间,则以 && 或 || 来隔开,他们的意义是:
&& 代表 AND ;
|| 代表 or ;
范例 if…then
[dmtsai@study bin]$ cp ans_yn.sh ans_yn-2.sh <==用复制来修改的比较快!
[dmtsai@study bin]$ vim ans_yn-2.sh
#!/bin/bash
#Program:
#This program shows the user’s choice
#History:
#2015/07/16 VBird First release
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
read -p "Please input ( Y/N ) : " yn
if [ “
y
n
"
=
=
"
Y
"
]
∣
∣
[
"
{yn}" == "Y" ] || [ "
yn"=="Y"]∣∣["{yn}” == “y” ]; then
echo “OK, continue”
exit 0
fi
if [ “
y
n
"
=
=
"
N
"
]
∣
∣
[
"
{yn}" == "N" ] || [ "
yn"=="N"]∣∣["{yn}” == “n” ]; then
echo “Oh, interrupt!”
exit 0
fi
echo “I don’t know what your choice is” && exit 0
多重、复杂条件判断式
#一个条件判断,分成功进行与失败进行 ( else )
if [ 条件判断式 ]; then
当条件判断式成立时,可以进行的指令工作内容;
else
当条件判断式不成立时,可以进行的指令工作内容;
fi
如果考虑更复杂的情况,则可以使用这个语法:
#多个条件判断 ( if … elif … elif … else ) 分多种不同情况执行
if [ 条件判断式一 ]; then
当条件判断式一成立时,可以进行的指令工作内容;
elif [ 条件判断式二 ]; then
elif 也是个判断式,因此出现 elif 后面都要接 then 来处理!
当条件判断式二成立时,可以进行的指令工作内容;
else
当条件判断式一与二均不成立时,可以进行的指令工作内容;
fi
利用参数的方法可以这样依序设计:
- 判断 $1 是否为 hello ,如果是的话,就显示 “Hello, how are you ?” ;
- 如果没有加任何参数,就提示使用者必须要使用的参数下达法;
- 而如果加入的参数不是 hello ,就提醒使用者仅能使用 hello 为参数。
整个程序的撰写可以是这样的:
[dmtsai@study bin]$ vim hello-2.sh
#!/bin/bash
#Program:
#Check KaTeX parse error: Expected 'EOF', got '#' at position 23: …ual to "hello" #̲History: #2015/…{1}" == “hello” ]; then
echo “Hello, how are you ?”
elif [ “KaTeX parse error: Expected '}', got 'EOF' at end of input: …rameters, ex> {{0} someword}”
else
echo “The only parameter is ‘hello’, ex> {${0} hello}”
fi
几个常见的 port 与相关网络服务的关系是:
80: WWW
22: ssh
21: ftp
25: mail
111: RPC (远端程序调用)
631: CUPS (打印服务功能)
如何通过 netstat 去侦测我的主机是否有打开这四个主要的网络服务端口 port 21, 22, 25 及 80
可以通过以下的程序:
[dmtsai@study bin]$ vim netstat.sh
#!/bin/bash
#Program:
#Using netstat and grep to detect WWW,SSH,FTP and Mail services.
#History:
#2015/07/16 VBird First release
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
#1. 先作一些告知的动作而已~
echo “Now, I will detect your Linux server’s services!”
echo -e “The www, ftp, ssh, and mail ( smtp ) will be detect! \n”
#2. 开始进行一些测试的工作,并且也输出一些信息啰!
testfile=/dev/shm/netstat_checking.txt
netstat -tuln > KaTeX parse error: Expected 'EOF', got '#' at position 12: {testfile} #̲ 先转存数据到内存当中!不用一… ( grep “:80 " KaTeX parse error: Expected 'EOF', got '#' at position 14: {testfile} ) #̲ 侦测看 port 80 在否…{testing}” != “” ]; then
echo “WWW is running in your system.”
fi
testing=$ ( grep “:22 " KaTeX parse error: Expected 'EOF', got '#' at position 14: {testfile} ) #̲ 侦测看 port 22 在否…{testing}” != “” ]; then
echo “SSH is running in your system.”
fi
testing=$ ( grep “:21 " KaTeX parse error: Expected 'EOF', got '#' at position 14: {testfile} ) #̲ 侦测看 port 21 在否…{testing}” != “” ]; then
echo “FTP is running in your system.”
fi
testing=$ ( grep “:25 " KaTeX parse error: Expected 'EOF', got '#' at position 14: {testfile} ) #̲ 侦测看 port 25 在否…{testing}” != “” ]; then
echo “Mail is running in your system.”
fi
范例 当兵到退伍的时间
日期是要用相减的方式来处置,所以我们可以通过使用 date 显示日期与时间,将他转为由 1970-01-01 累积而来的秒数, 通过秒数相减来取得剩余的秒数后,再换算为日数即可。整个脚本的制作流程有点像这样:
- 先让使用者输入他们的退伍日期;
- 再由现在日期比对退伍日期;
- 由两个日期的比较来显示 “ 还需要几天 ” 才能够退伍的字样。
[dmtsai@study bin]$ vim cal_retired.sh
#!/bin/bash
#Program:
#You input your demobilization date, I calculate how many days before you demobilize.
#History:
#2015/07/16 VBird First release
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
#1. 告知使用者这支程序的用途,并且告知应该如何输入日期格式?
echo “This program will try to calculate :”
echo “How many days before your demobilization date…”
read -p “Please input your demobilization date ( YYYYMMDD ex>20150716 ) : " date2
#2. 测试一下,这个输入的内容是否正确?利用正则表达式啰~
date_d=$ ( echo KaTeX parse error: Expected 'EOF', got '#' at position 30: …'[0-9]\{8\}' ) #̲ 看看是否有八个数字 if […{date_d}” == “” ]; then
echo “You input the wrong date format…”
exit 1
fi
#3. 开始计算日期啰~
declare -i date_dem=$ ( date --date=" d a t e 2 " + d e c l a r e − i d a t e n o w = {date2}" +%s ) # 退伍日期秒数 declare -i date_now= date2"+declare−idatenow= ( date +%s ) # 现在日期秒数
declare -i date_total_s=$ (( d a t e d e m − {date_dem}- datedem−{date_now} )) # 剩余秒数统计
declare -i date_d=$ (( KaTeX parse error: Expected 'EOF', got '#' at position 28: …s}/60/60/24 )) #̲ 转为日数 if [ "{date_total_s}" -lt “0” ]; then # 判断是否已退伍
echo "You had been demobilization before: " $ (( -1* d a t e d ) ) " a g o " e l s e d e c l a r e − i d a t e h = {date_d} )) " ago" else declare -i date_h= dated))"ago"elsedeclare−idateh= (( $ (( d a t e t o t a l s − {date_total_s}- datetotals−{date_d}6060*24 )) /60/60 ))
echo “You will demobilize after ${date_d} days and ${date_h} hours.”
fi
case … esac 判断
case $ 变量名称 in <==关键字为 case ,还有变量前有钱字号
" 第一个变量内容 " ) <==每个变量内容建议用双引号括起来,关键字则为小括号 )
程序段
;; <==每个类别结尾使用两个连续的分号来处理!
" 第二个变量内容 " )
程序段
;;
- ) <==最后一个变量内容都会用 * 来代表所有其他值
不包含第一个变量内容与第二个变量内容的其他程序执行段
exit 1
;;
esac <==最终的 case 结尾!“反过来写”思考一下!
范例
[dmtsai@study bin]$ vim hello-3.sh
#!/bin/bash
#Program:
#Show “Hello” from $1… by using case … esac
#History:
#2015/07/16 VBird First release
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
case KaTeX parse error: Expected '}', got 'EOF' at end of input: …rameters, ex> {{0} someword}"
;;
- ) # 其实就相当于万用字符,0~无穷多个任意字符之意!
echo “Usage ${0} {hello}”
;;
esac
使用者能够输入 one, two, three , 并且将使用者的变量显示到屏幕
上,如果不是 one, two, three 时,就告知使用者仅有这三种选择。
[dmtsai@study bin]$ vim show123.sh
#!/bin/bash
#Program:
#This script only accepts the flowing parameter: one, two or three.
#History:
#2015/07/17 VBird First release
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
echo “This program will print your selection !”
#read -p "Input your choice: " choice # 暂时取消,可以替换!
#case ${choice} in # 暂时取消,可以替换!
case ${1} in # 现在使用,可以用上面两行替换!
“one” )
echo “Your choice is ONE”
;;
“two” )
echo “Your choice is TWO”
;;
“three” )
echo “Your choice is THREE”
;;
- )
echo “Usage ${0} {one|two|three}”
;;
esac
function 功能(函数)
语法:
function fname () {
程序段
}
自订一个名为 printit 的函数来使用喔:
[dmtsai@study bin]$ vim show123-2.sh
#!/bin/bash
#Program:
#Use function to repeat information.
#History:
#2015/07/17 VBird First release
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
function printit () {
echo -n "Your choice is " # 加上 -n 可以不断行继续在同一行显示
}
echo “This program will print your selection !”
case ${1} in
“one” )
printit; echo ${1} | tr ‘a-z’ ‘A-Z’ # 将参数做大小写转换!
;;
“two” )
printit; echo ${1} | tr ‘a-z’ ‘A-Z’
;;
“three” )
printit; echo ${1} | tr ‘a-z’ ‘A-Z’
;;
- )
echo “Usage ${0} {one|two|three}”
;;
esac
“ function fname () { 程序段 } ” 内的 $0, $1… 等等与 shell script 的 $0 是不同的。
[dmtsai@study bin]$ vim show123-3.sh
#!/bin/bash
#Program:
#Use function to repeat information.
#History:
#2015/07/17 VBird First release
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
function printit () {
echo “Your choice is ${1}” # 这个 $1 必须要参考下面指令的下达
}
echo “This program will print your selection !”
case ${1} in
“one” )
printit 1 # 请注意, printit 指令后面还有接参数!
;;
“two” )
printit 2
;;
“three” )
printit 3
;;
- )
echo “Usage ${0} {one|two|three}”
;;
esac
while do done, until do done (不定循环)
一般来说,不定循环最常见的就是下面这两种状态了:
while [ condition ] <==中括号内的状态就是判断式
do <==do 是循环的开始!
程序段落
done <==done 是循环的结束
while 的中文是 “ 当 … 时 ” ,所以,这种方式说的是 “ 当 condition 条件成立时,就进行循环,直到 condition 的条件不成立才停止 ” 的意思。
还有另外一种不定循环的方式:
until [ condition ]
do
程序段落
done
这种方式恰恰与 while 相反,它说的是 “ 当 condition 条件成立时,就终止循环, 否则就持续进行循环的程序段。
以 while 简单的练习:
[dmtsai@study bin]$ vim yes_to_stop.sh
#!/bin/bash
#Program:
#Repeat question until user input correct answer.
#History:
#2015/07/17 VBird First release
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
while [ “
y
n
"
!
=
"
y
e
s
"
−
a
"
{yn}" != "yes" -a "
yn"!="yes"−a"{yn}” != “YES” ]
do
read -p "Please input yes/YES to stop this program: " yn
done
echo “OK! you input the correct answer.”
如果使用 until 呢?呵呵有趣啰~ 他的条件会变成这样:
[dmtsai@study bin]$ vim yes_to_stop-2.sh
#!/bin/bash
#Program:
#Repeat question until user input correct answer.
#History:
#2015/07/17 VBird First release
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
until [ “
y
n
"
=
=
"
y
e
s
"
−
o
"
{yn}" == "yes" -o "
yn"=="yes"−o"{yn}” == “YES” ]
do
read -p "Please input yes/YES to stop this program: " yn
done
echo “OK! you input the correct answer.”
for…do…done (固定循环)
语法是:
for var in con1 con2 con3 …
do
程序段
done
有三种动物,分别是 dog, cat, elephant 三种, 我想每一行都输出这样: “There are dogs…” 之类的字
样,则可以:
[dmtsai@study bin]$ vim show_animal.sh
#!/bin/bash
#Program:
#Using for … loop to print 3 animals
#History:
#2015/07/17 VBird First release
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
for animal in dog cat elephant
do
echo "There are ${animal}s… "
done
使用者输入某个目录文件名, 然后我找出某目录内的文件名的权限,该如何是好?
可以这样做啦~
[dmtsai@study bin]$ vim dir_perm.sh
#!/bin/bash
#Program:
#User input dir name, I find the permission of files.
#History:
#2015/07/17 VBird First release
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
#1. 先看看这个目录是否存在啊?
read -p “Please input a directory: " dir
if [ “
d
i
r
"
=
=
"
"
−
o
!
−
d
"
{dir}" == "" -o ! -d "
dir"==""−o!−d"{dir}” ]; then
echo “The KaTeX parse error: Expected 'EOF', got '#' at position 47: …em." exit 1 fi #̲2. 开始测试文件啰~ fil… ( ls ${dir} ) # 列出所有在该目录下的文件名称
for filename in
f
i
l
e
l
i
s
t
d
o
p
e
r
m
=
"
"
t
e
s
t
−
r
"
{filelist} do perm="" test -r "
filelistdoperm=""test−r"{dir}/KaTeX parse error: Expected 'EOF', got '&' at position 13: {filename}" &̲& perm="{perm} readable”
test -w “
d
i
r
/
{dir}/
dir/{filename}” && perm=”
p
e
r
m
w
r
i
t
a
b
l
e
"
t
e
s
t
−
x
"
{perm} writable" test -x "
permwritable"test−x"{dir}/KaTeX parse error: Expected 'EOF', got '&' at position 13: {filename}" &̲& perm="{perm} executable"
echo "The file
d
i
r
/
{dir}/
dir/{filename}'s permission is ${perm} "
done
for…do…done 的数值处理
语法如下:
for (( 初始值 ; 限制值 ; 执行步阶 ))
do
程序段
done
这种语法适合于数值方式的运算当中
以这种方式来进行 1 累加到使用者输入的循环
[dmtsai@study bin]$ vim cal_1_100-2.sh
#!/bin/bash
#Program:
#Try do calculate 1+2+…+KaTeX parse error: Expected 'EOF', got '#' at position 14: {your_input} #̲History: #2015/…{nu}; i=i+1 ))
do
s=$ ((
s
+
{s}+
s+{i} ))
done
echo “The result of ‘1+2+3+…+${nu}’ is ==> ${s}”
搭配乱数与阵列的实验
每天吃饭吃啥问题:
[dmtsai@study bin]$ vim what_to_eat.sh
#!/bin/bash
#Program:
#Try do tell you what you may eat.
#History:
#2015/07/17 VBird First release
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
eat[1]=" 卖当当漢堡包 " # 写下你所收集到的店家!
eat[2]=" 肯爷爷炸鸡 "
eat[3]=" 彩虹日式便当 "
eat[4]=" 越油越好吃大雅 "
eat[5]=" 想不出吃啥学餐 "
eat[6]=" 太师父便当 "
eat[7]=" 池上便当 "
eat[8]=" 怀念火车便当 "
eat[9]=" 一起吃方便面 "
eatnum=9 # 需要输入有几个可用的餐厅数!
check=$ (( ${RANDOM} * ${eatnum} / 32767 + 1 ))
echo “your may eat KaTeX parse error: Expected '}', got 'EOF' at end of input: {eat[{check}]}”
如果想要每次都秀出 3 个店家呢? 而且这个店家不能重复喔!重复当然就没啥意义了!
所以,你可以这样做
[dmtsai@study bin]$ vim what_to_eat-2.sh
#!/bin/bash
#Program:
#Try do tell you what you may eat.
#History:
#2015/07/17 VBird First release
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
eat[1]=" 卖当当漢堡包 "
eat[2]=" 肯爷爷炸鸡 "
eat[3]=" 彩虹日式便当 "
eat[4]=" 越油越好吃大雅 "
eat[5]=" 想不出吃啥学餐 "
eat[6]=" 太师父便当 "
eat[7]=" 池上便当 "
eat[8]=" 怀念火车便当 "
eat[9]=" 一起吃方便面 "
eatnum=9
eated=0
while [ "${eated}" -lt 3 ]; do
check=$ (( ${RANDOM} * ${eatnum} / 32767 + 1 ))
mycheck=0
if [ "${eated}" -ge 1 ]; then
for i in $ ( seq 1 ${eated} )
do
if [ ${eatedcon[$i]} == $check ]; then
mycheck=1
fi
done
fi
if [ ${mycheck} == 0 ]; then
echo "your may eat ${eat[${check}]}"
eated=$ (( ${eated} + 1 ))
eatedcon[${eated}]=${check}
fi
done
shell script 的追踪与 debug
判断shell脚本执行有没有问题
[dmtsai@study ~]$ sh [-nvx] scripts.sh
选项与参数:
-n :不要执行 script,仅查询语法的问题;
-v :再执行 sccript 前,先将 scripts 的内容输出到屏幕上;
-x :将使用到的 script 内容显示到屏幕上,这是很有用的参数!
范例一:测试 dir_perm.sh 有无语法的问题?
[dmtsai@study ~]$ sh -n dir_perm.sh
#若语法没有问题,则不会显示任何信息!
范例二:将 show_animal.sh 的执行过程全部列出来~
[dmtsai@study ~]$ sh -x show_animal.sh
- PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:/root/bin
- export PATH
- for animal in dog cat elephant
- echo 'There are dogs… ’
There are dogs… - for animal in dog cat elephant
- echo 'There are cats… ’
There are cats… - for animal in dog cat elephant
- echo 'There are elephants… ’
There are elephants…
之前一直提到的 /etc/init.d/netconsole ,这个 script 是干嘛用的? 利用 vim
去查阅最前面的几行字,他出现如下信息:
#netconsole This loads the netconsole module with the configured parameters.
#chkconfig: - 50 50
#description: Initializes network console logging
#config: /etc/sysconfig/netconsole
意思是说,这个脚本在设置网络终端机来应付登陆的意思,且配置文件在 /etc/sysconfig/netconsole 设置内! 所以,你写的脚本如果也能够很清楚的交待,那就太棒了!