利用Shell的功能所写的一个程序,使用纯文本文件,将一些shell的语法与指令(含外部指令)写在里面,搭配正则表达式、管线命令与数据流重导向功能,以达到我们所想要的处理目的
就像是DOS年代的批处理文件(.bat)
自动化管理的重要依据
追踪和管理系统的重要工作
简单入侵检测功能
连续指令单一化
简易的数据处理
跨平台支持与学习历程较短
当使用sh shell.sh 运行时,只要有r的权限即可被执行
在开头处记录:功能、版本信息、作者与联络方式、版权的宣告方式、History、脚本内较特殊的指令(使用绝对路径方式来下达的)、运行时需要的环境变量预先宣告与设定
(1)输入姓、名,完整输出
#!/bin/bash
#Program:
# show full name
#History
#2018.1.29 GYY First release
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
read -p "Please input your first name: " firstname
read -p "Please input your last name: " lastname
echo -e "\nYour full name is: ${firstname} ${lastname}"
[gyy@localhost bin]$ chmod 777 showname.sh
[gyy@localhost bin]$ ./showname.sh
Please input your first name: G
Please input your last name: YY
Your full name is: G YY
(2)随日期变化进行文件建立
#!/bin/bash
#Program:
# Program creates three files,which named by user's input and date command
#History
#2018.1.29 GYY First release
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
#1、让输入者输入文件名,并取得fileuser这个变量
echo -e “I will use ’touch‘ command to create 3 files”
read -p "Please input your filename: " fileuser
#2、为了避免使用者随意按Enter,利用变量分析档名是否有设定
filename=${fileuser:-"filename"}
#3、利用date指令来获取所需要的档名
date1=$(date --date='2 days ago' +%Y%m%d)
date2=$(date --date='1 days ago' +%Y%m%d)
date3=$(date +%Y%m%d)
file1=${filename}${date1}
file2=${filename}${date2}
file3=${filename}${date3}
#4、建立档名
touch "${file1}"
touch "${file2}"
touch "${file3}"
[gyy@localhost bin]$ chmod 777 create_3_filename.sh
[gyy@localhost bin]$ ./create_3_filename.sh
“I will use ’touch‘ command to create 3 files”
Please input your filename: GYY
[gyy@localhost bin]$ ls | grep GYY
GYY20190126
GYY20190127
GYY20190128
(3)两数相乘
#!/bin/bash
#Program:
# User inputs 2 integer numbers;program will cross these two numbers.
#History
#2018.1.29 GYY First release
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
echo -e "You should input 2 numbers, I will mutiplying them !\n"
read -p "first number : " firstnum
read -p "secong number : " secondnum
total=$((${firstnum}*${secondnum}))
echo -e "\nThe result of ${firstnum} * ${second} is ${total}"
[gyy@localhost bin]$ chmod 777 multiplying.sh
[gyy@localhost bin]$ ./multiplying.sh
You should input 2 numbers, I will mutiplying them !
first number : 4
secong number : 5
The result of 4 * is 20
(4)数值运算:透过bc计算pi
#!/bin/bash
#Program:
# User input a scale number to calculate pi number.
#History
#2018.1.29 GYY First release
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
echo -e "This program will calculate pi value. \n"
echo -e "You should input a float numer to calculate pi value.\n"
read -p "The scale numbher (10~10000)? " checking
num=${checking:-"10"}
echo -e "Starting calcuate pi value. Be patient."
time echo "scale=${num}; 4*a(1)" | bc -lq
[gyy@localhost bin]$ chmod 777 cal_pi.sh
[gyy@localhost bin]$ ./cal_pi.sh
This program will calculate pi value.
You should input a float numer to calculate pi value.
The scale numbher (10~10000)? 500
Starting calcuate pi value. Be patient.
3.141592653589793238462643383279502884197169399375105820974944592307\
81640628620899862803482534211706798214808651328230664709384460955058\
22317253594081284811174502841027019385211055596446229489549303819644\
28810975665933446128475648233786783165271201909145648566923460348610\
45432664821339360726024914127372458700660631558817488152092096282925\
40917153643678925903600113305305488204665213841469519415116094330572\
70365759591953092186117381932611793105118548074462379962749567351885\
75272489122793818301194912
real 0m0.067s
user 0m0.065s
sys 0m0.003s
(1)利用直接执行的方式来执行script
利用直接指令或利用bash(或sh)来下达脚本,该script会使用一个新的bash环境来执行脚本内的指令,即script是在子程序的bash环境内执行的,当子程序完成后,在子程序内的各项变量或动作将会结束而不会传回到父程序中
(2)利用source来执行脚本:在父程序中执行
这样变量会传回到父程序
因此,不注销系统而要让某些吸入~/.bashrc的设定生效时,需要使用 source ~/.bashrc 而不能使用bash ~/.bashrc
练习代码:
判断档名类型和权限
#!/bin/bash
#Program:
# User input a filename ,program will check the flowing:
# 1.exist? 2.file/directory 3.file permissions
#History
#2018.1.29 GYY First release
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
#1.让使用者输入档名,并且判断使用者是否真的有输入字符串
echo -e "Please input a filename,I will check filename's type and permission. \n\n"
read -p "Input a filename : " filename
test -z ${fliename} echo "You Must input a filename." && exit 0
#2.判断文件是否存在?若不存在则显示讯息并结束脚本
test ! -e ${filename} && echo "The filename '${filename}' DO NOT exist" && exit 0
#3.开始判断文件类型和属性
test -f ${filename} && filetype="regular file"
test -d ${filename} && filetype="directory"
test -r ${filename} && perm="readable"
test -w ${filename} && perm="${perm} writable"
test -x ${filename} && perm="${perm} executable"
#4.开始输出信息
echo "The filename: ${filename} is a ${filetype}"
echo "And the permissions for you are : ${perm}"
[gyy@localhost ~]$ chmod 777 file_perm.sh
[gyy@localhost ~]$ ./file_perm.sh
Please input a filename,I will check filename's type and permission.
Input a filename : /home/gyy
./file_perm.sh: line 13: test: echo: binary operator expected
The filename: /home/gyy is a directory
And the permissions for you are : readable writable executable
[]也可以进行数据的判断
中括号的两端需要有空格符来分隔
参数与test相同
示例程序:使用[]进行判断
#!/bin/bash
#Program:
# This program shows the user's choice
#History
#2018.1.29 GYY 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
[ "${yn}" == "Y" -o "${yn}" == "y" ] && echo "OK,continue" && exit 0
[ "${yn}" == "N" -o "${yn}" == "n" ] && echo "OK,interrupt!" && exit 0
echo "I don't know what you choice is " && exit 0
[gyy@localhost bin]$ chmod 777 ans_yn.sh
[gyy@localhost bin]$ ./ans_yn.sh
Please input (Y/N): n
OK,interrupt!
[gyy@localhost bin]$ ./ans_yn.sh
Please input (Y/N): y
OK,continue
[gyy@localhost bin]$ ./ans_yn.sh
Please input (Y/N): g
I don't know what you choice is
示例程序:一个参数分析脚本
#!/bin/bash
#Program:
# Program shows the script name,parameters
#History
#2018.1.29 GYY First release
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
echo "The script name is ==> ${0}"
echo "Total parameter number is ==> ${#}"
[ "$#" -lt 2 ] && echo "The number of parameter is less than 2. Stop here." && exit 0
echo "Your whole parameter is ==> '$@'"
echo "The 1st parameter ==> ${1}"
echo "The 2nd parameter ==> ${2}"
[gyy@localhost bin]$ chmod 777 how_paras.sh
[gyy@localhost bin]$ ./how_paras.sh aaa bbb ccc
The script name is ==> ./how_paras.sh
Total parameter number is ==> 3
Your whole parameter is ==> 'aaa bbb ccc'
The 1st parameter ==> aaa
The 2nd parameter ==> bbb
shift后面接数字表示拿掉前面几个参数,默认拿掉一个
示例程序:使用shift进行参数变量号码偏移
#!/bin/bash
#Program:
# Program shows the effect of shift function.
#History
#2018.1.29 GYY First release
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
echo "Total parameter number is ==> $#"
echo "Your whole parameter is ==> '$@'"
shift
echo "Total parameter number is ==> $#"
echo "Your whole parameter is ==> '$@'"
shift 3
echo "Total parameter number is ==> $#"
echo "Your whole parameter is ==> '$@'"
[gyy@localhost bin]$ chmod 777 shift_paras.sh
[gyy@localhost bin]$ ./shift_paras.sh aaa bbb ccc ddd eee fff ggg
Total parameter number is ==> 7
Your whole parameter is ==> 'aaa bbb ccc ddd eee fff ggg'
Total parameter number is ==> 6
Your whole parameter is ==> 'bbb ccc ddd eee fff ggg'
Total parameter number is ==> 3
Your whole parameter is ==> 'eee fff ggg'
if [ 条件判断式 ]; then
当条件判断式成立时,可以进行的指令工作内容
fi #将if反过来写,结束if
可以使用 && 和 ||
示例程序:使用if-then写yn判断
#!/bin/bash
#Program:
# This program shows the user's choice
#2018.1.29 GYY 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 [ "${yn}" == "Y" ] || [ "${yn}" == "y" ]; then
echo "OK,continue"
exit 0
fi
if [ "${yn}" == "N" ] || [ "${yn}" == "n" ]; then
echo "OK,interrupt!"
exit 0
fi
echo "I don't know what you choice is " && exit 0
[gyy@localhost bin]$ chmod 777 ans_yn-2.sh
[gyy@localhost bin]$ ./ans_yn-2.sh
Please input (Y/N): n
OK,interrupt!
[gyy@localhost bin]$ ./ans_yn-2.sh
Please input (Y/N): y
OK,continue
[gyy@localhost bin]$ ./ans_yn-2.sh
Please input (Y/N): g
I don't know what you choice is
加上else
还可以 elif [ 条件判断式二 ]; then
常见的port与相关网络服务的关系
示例程序:网络端口侦测脚本
#!/bin/bash
#Program:
# Using netstat and grep to detect WWW,SSH,FTP and Mail services.
#2018.1.29 GYY First release
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
echo "Now ,I will detect your Linux server's services!"
echo -e "The www, ftp, ssh, and mail(smtp) will be detect!\n"
testfile=/dev/shm/netstat_checking.txt
netstat -tuln > ${testfile}
testing=$(grep ":80" ${testfile})
if [ "${testing}" != "" ]; then
echo "WWW is running in your system."
fi
testing=$(grep ":22" ${testfile})
if [ "${testing}" != "" ]; then
echo "SSH is running in your system."
fi
testing=$(grep ":21" ${testfile})
if [ "${testing}" != "" ]; then
echo "FTP is running in your system."
fi
testing=$(grep ":25" ${testfile})
if [ "${testing}" != "" ]; then
echo "Mail is running in your system."
fi
[gyy@localhost bin]$ chmod 777 netstat.sh
[gyy@localhost bin]$ ./netstat.sh
Now ,I will detect your Linux server's services!
The www, ftp, ssh, and mail(smtp) will be detect!
SSH is running in your system.
Mail is running in your system.
case $变量 in 当中的$变量大致有两种取得方式
直接下达式(例如例程中的直接给${1})
交互式(用户输入)
/etc/init.d 中的很多启动服务就是用case…case的语句写出来的
示例程序:case...case语句使用
#!/bin/bash
#Program:
# This program shows "Hello World!" in your screen
#History:
#2019.1.28 GYY First release
PATH=/bin:/sbin:/usr/bin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
case ${1} in
"hello")
echo "hello, how are you ?"
;;
"")
echo "You Must input parameters, ex> {${0} someword}"
;;
*)
echo "Usage ${0} {hello}"
;;
esac
[gyy@localhost bin]$ chmod 777 hello2.sh
[gyy@localhost bin]$ ./hello2.sh
You Must input parameters, ex> {./hello2.sh someword}
[gyy@localhost bin]$ ./hello2.sh hello
hello, how are you ?
function也是拥有内建变量的,它的内变量与shell script很类似,函数名称为$0,后续接的变量依次为$1 $2
示例程序:function功能练习
#!/bin/bash
#Program:
# Use function to repeat information
#History:
#2019.1.28 GYY First release
PATH=/bin:/sbin:/usr/bin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
function printit(){
echo "Your choice is ${1}"
}
echo "This program will print your selection !"
case ${1} in
"one")
printit 1
;;
"two")
printit 2
;;
"three")
printit 3
;;
*)
echo "Usage ${0} {one|two|three}"
;;
esac
[gyy@localhost bin]$ chmod 777 show123.sh
[gyy@localhost bin]$ ./show123.sh two
This program will print your selection !
Your choice is 2
[gyy@localhost bin]$
两种结构
类比C前者while型 后者do…while型
示例程序:计算1-100加和
#!/bin/bash
#Program:
# Use loop to calculate "1+2+3+...+100"result
#History:
#2019.1.28 GYY First release
PATH=/bin:/sbin:/usr/bin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
#while do done
s=0
i=0
while [ "${i}" != "100" ]
do
i=$(($i+1))
s=$(($s+$i))
done
echo "The result1 of '1+2+3+...+100' is ==> $s"
#until do done
s=0
i=0
until [ "${i}" == "100" ]
do
i=$(($i+1))
s=$(($s+$i))
done
echo "The result2 of '1+2+3+...+100' is ==> $s"
[gyy@localhost bin]$ chmod 777 cal_1_100.sh
[gyy@localhost bin]$ ./cal_1_100.sh
The result1 of '1+2+3+...+100' is ==> 5050
The result2 of '1+2+3+...+100' is ==> 5050
两种结构
第一种类似于Python的for 第二种类似于C的for
示例程序1:利用for抓取用户id
#!/bin/bash
#Program:
# Use id,finger command to check system account's information.
#History:
#2019.1.28 GYY First release
PATH=/bin:/sbin:/usr/bin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
users=$(cut -d ':' -f1 /etc/passwd)
for username in ${users}
do
id ${username}
done
[gyy@localhost bin]$ chmod 777 userid.sh
[gyy@localhost bin]$ ./userid.sh
uid=0(root) gid=0(root) groups=0(root)
uid=1(bin) gid=1(bin) groups=1(bin)
uid=2(daemon) gid=2(daemon) groups=2(daemon)
uid=3(adm) gid=4(adm) groups=4(adm)
uid=4(lp) gid=7(lp) groups=7(lp)
uid=5(sync) gid=0(root) groups=0(root)
uid=6(shutdown) gid=0(root) groups=0(root)
uid=7(halt) gid=0(root) groups=0(root)
uid=8(mail) gid=12(mail) groups=12(mail)
uid=11(operator) gid=0(root) groups=0(root)
uid=12(games) gid=100(users) groups=100(users)
uid=14(ftp) gid=50(ftp) groups=50(ftp)
uid=99(nobody) gid=99(nobody) groups=99(nobody)
uid=192(systemd-network) gid=192(systemd-network) groups=192(systemd-network)
uid=81(dbus) gid=81(dbus) groups=81(dbus)
uid=999(polkitd) gid=998(polkitd) groups=998(polkitd)
uid=74(sshd) gid=74(sshd) groups=74(sshd)
uid=89(postfix) gid=89(postfix) groups=89(postfix),12(mail)
uid=1000(gyy) gid=1000(gyy) groups=1000(gyy)
uid=1001(user1) gid=1001(user1) groups=1001(user1)
uid=1002(git) gid=1002(git) groups=1002(git)
uid=998(nginx) gid=995(nginx) groups=995(nginx)
uid=27(mysql) gid=27(mysql) groups=27(mysql)
示例程序2:使用for...do...done进行数值处理
#!/bin/bash
#Program:
# Try do calculate 1+2+...+${your_input}
#History:
#2019.1.28 GYY First release
PATH=/bin:/sbin:/usr/bin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
read -p "Please input a number, I will count for 1+2+...+your_input: " nu
s=0
for(( i=1; i<=${nu}; i=i+1 ))
do
s=$((${s}+${i}))
done
echo "The result of '1+2+3+...+${nu}' is ==> ${s}"
[gyy@localhost bin]$ chmod 777 cal_1_100-2.sh
[gyy@localhost bin]$ ./cal_1_100-2.sh
Please input a number, I will count for 1+2+...+your_input: 10
The result of '1+2+3+...+10' is ==> 55
使用-x可以将指令的执行过程显示出来,如此可以判断程序具体执行到了哪一步
示例:代码追踪
[gyy@localhost bin]$ sh -n cal_1_100-2.sh
[gyy@localhost bin]$ sh -x cal_1_100-2.sh
+ PATH=/bin:/sbin:/usr/bin:/usr/local/bin:/usr/local/sbin:/home/gyy/bin
+ export PATH
+ read -p 'Please input a number, I will count for 1+2+...+your_input: ' nu
Please input a number, I will count for 1+2+...+your_input: 5
+ s=0
+ (( i=1 ))
+ (( i<=5 ))
+ s=1
+ (( i=i+1 ))
+ (( i<=5 ))
+ s=3
+ (( i=i+1 ))
+ (( i<=5 ))
+ s=6
+ (( i=i+1 ))
+ (( i<=5 ))
+ s=10
+ (( i=i+1 ))
+ (( i<=5 ))
+ s=15
+ (( i=i+1 ))
+ (( i<=5 ))
+ echo 'The result of '\''1+2+3+...+5'\'' is ==> 15'
The result of '1+2+3+...+5' is ==> 15