目录
三.假设我的程序文件名是/home/haha/shell.sh,该如何执行这个文件?
五.script的执行方式区别(source,shscript,./script)
(2)while do done,until do done(不定循环)
一.什么是shell script
Shell script是利用shell的功能所写的一个“程序”,这个程序是是使用纯文本文件,将一些shell的语法与命令(含外部命令)写在里面,搭配正则表达式,管道命令与数据流重定向等功能,以达到我们所想要的处理目的。
二.shell编写注意事项:
1.命令的执行是从上而下,从左而右地分析执行;
2.命令,参数间的多个空白都会被忽略掉;
3.空白行也将被忽略掉,并且[tab]按键所得的空白同样视为空格键;
4.如果读取到一个Enter符号(CR),就尝试开始执行该行(或改串)命令;
5.至于如果一行的内容太多,则可以使用“\[Enter]”来扩展至下一行;
6.“#”可作为批注。任何加在#后面的数据将全部被视为批注文字而被忽略。
三.假设我的程序文件名是/home/haha/shell.sh,该如何执行这个文件?
1.直接命令执行:
shell.sh文件必须要具备可读可执行(rx)的权限,然后:
(1)绝对路径:使用/home/haha/shell.sh来执行命令;
(2)相对路径:假设工作目录在/home/haha/,则使用./shell.sh来执行;
2.以bash进程来执行:
通过“bash shell.sh”或“sh shell.sh”来执行。
四.脚本的编写
示例一:
编写一个简单的script
[leiyuxing@centos6 ~]$ mkdir scripts
[leiyuxing@centos6 ~]$ cd scripts/
[leiyuxing@centos6 scripts]$ vim sh01.sh
#!/bin/bash
# program:
# This program shows "Hello leiyuxing!" in your screen.
# History:
# 2016/8/19 leiyuxing First release
PATH=/bin:/sbin:/use/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
echo -e "Hello leiyuxing! \a \n"
exit 0
程序编写说明:
1.第一行#!/bin/bash声明这个script使用的shell名称
因为我们使用的是bash,所以必须以“#!/bin/bash”来声明这个文件内的语法使用bash的语法。当这个程序被执行时,就能够加载bash的相关环境配置文件(一般来说就是non-login shell的~/.bashrc),并且执行bash来使我们下面的命令能执行。这个至关重要,如果没有设置好这一行,程序可能无法执行,因为系统可能无法判断该程序需要使用寿命shell来执行。
2.程序内容说明
整个script当中,除了第一行的“#!”是用来声明shell的之外,其他#都是“批注”的用途,
故上面的程序中第二行以下就是用来说明整个程序的基本数据。一般来说,建议你养成说明该script的内容与功能,版本信息,作者,联系方式,建立日期,历史记录等习惯,这有助于将来程序的改写与调试。
3.环境变量的声明
PATH与LANG(如果有使用到输出相关的信息时)是当中最重要的!如此一来程序可直接执行一些外部命令,二不必写绝对路径。
4.主要程序部分
echo这一行。
5.告知执行结果
一个命令的执行成功与否,可使用$?这个变量来查看,也可以利用exit 这个命令中断程序,并且传回一个数值给系统。这个程序中博主使用exit 0,这代表离开script并且回传一个0给系统,所以我执行完这个script程序后,若接着执行echo $?则可得到0的值。至此我知道了,利用exit n(n是数字)的功能,我们可以自定义错误信息,让程序变得更加聪明。
用上面的执行方法查看下结果:
[leiyuxing@centos6 scripts]$ sh sh01.sh
Hello leiyuxing!
也可使用
[leiyuxing@centos6 scripts]$ chmod a+x sh01.sh
[leiyuxing@centos6 scripts]$ ./sh01.sh
Hello leiyuxing!
示例二:
利用read命令的用途编写一个script,让用户输入first name 和last name,最后在屏幕上显示“Your full name is:”内容
[leiyuxing@centos6 scripts]$ vim sh02.sh
#!/bin/bash
# program:
# User inputs his first name and last name. program shows his full name.
# History:
# 2016/8/20 leiyuxing First release
PATH=/bin:/sbin:/use/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"//结果由屏幕输出
[leiyuxing@centos6 scripts]$ sh sh02.sh
Please input your first name: lixing
Please input your last name: leiyuxing
Your full name is : lixing leiyuxing
示例三:
随日期变化:利用日期进行文件的创建
假设我想创建三个空的文件(通过touch),文件名最开头由用户输入决定,假设用户输入filename,那今天的日期是2016/08/20,我想要以前,昨天,今天的日期来创建这些文件,即filename_20160818,filename_20160819,filename_20160820,该如何是好?
[leiyuxing@centos6 scripts]$ vim sh03.sh
#!/bin/bash
# program:
# Program creates three files, which named by user's input
# and date command
# History:
# 2016/8/20 leiyuxing First release
PATH=/bin:/sbin:/use/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: " filename #提示用户输入
#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"
验证结果:
[leiyuxing@centos6 scripts]$ sh sh03.sh
I will use 'touch' command to create 3 files.
Please input your filename: file1
[leiyuxing@centos6 scripts]$ sh sh03.sh
I will use 'touch' command to create 3 files.
Please input your filename: file2
[leiyuxing@centos6 scripts]$ sh sh03.sh
I will use 'touch' command to create 3 files.
Please input your filename: file3
[leiyuxing@centos6 scripts]$ ls
filename20160818 filename20160819 filename20160820 sh01.sh sh02.sh sh03.sh
示例四:
如果我们要用户输入两个变量,然而将两个变量的内容相乘,最后输出相乘结果
[leiyuxing@centos6 scripts]$ vim sh04.sh
#!/bin/bash
# program:
# User inputs 2 integer numbers; program will cross these two numbers.
# History:
# 2016/8/20 leiyuxing First release
PATH=/bin:/sbin:/use/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
echo -e "You SHOULD input 2 numbers,I will cross them! \n"
read -p "first number: " firstnu
read -p "second number: " secnu
total=$(($firstnu*$secnu))
echo -e "\nThe result of $firstnu x $secnu is ==>$total"
验证结果:
[leiyuxing@centos6 scripts]$ sh sh04.sh
You SHOULD input 2 numbers,I will cross them!
first number: 4
second number: 5
The result of 4 x 5 is ==>20
五.script的执行方式区别(source,shscript,./script)
1.利用直接执行方式来执行script
当子进程完成后,子进程内的各项变量或操作将会结束而不会传回到父进程中
例:
[leiyuxing@centos6 scripts]$ echo $firstname $lastname
//确认了这两个变量并不存在
[leiyuxing@centos6 scripts]$ sh sh02.sh
Please input your first name: leiyuxing//这个名字是博主自己输入的
Please input your last name: leiyushen
Your full name is : leiyuxing leiyushen //在script运行中,这两个变量生效
[leiyuxing@centos6 scripts]$ echo $firstname $lastname
//事实上,这两个变量在父进程的bash中还是不存在的!
2.利用source来执行脚本:在父进程中执行
例:
[leiyuxing@centos6 scripts]$ source sh02.sh
Please input your first name: leiyuxing
Please input your last name: leiyushen
Your full name is : leiyuxing leiyushen
[leiyuxing@centos6 scripts]$ echo $firstname $lastname
leiyuxing leiyushen//有数据产生,可以生效!
3.利用test命令的测试功能
比如我要检测dm是否存在时,使用:
[leiyuxing@centos6 ~]$ test -e /dm
发现结果不会显示任何信息
但我们可以通过$?或&&及||来显示整个结果:
[leiyuxing@centos6 ~]$ test -e /dm && echo "exitst" || echo "Not exist"
Not exist
最终的结果可以告知我们是“exist”还是“Not exist”
例:
首先判断一下,让用户输入一个文件名,我们判断:
(1)这个文件是否存在,若不存在给予一个“Filename does not exist”的信息,并中断程序;
(2)若这个文件存在,则判断它是文件还是目录,结果输出“Filename is regular file”或“Filename is directory”;
(3)判断一下,执行者的身份对这个文件或目录所拥有的权限,并输出权限数据。
[leiyuxing@centos6 scripts]$ vim sh05.sh
#!/bin/bash
# program:
# User inputs a filename, program will check the flowing:
# 1.)exist? 2.)file/directory? 3.)file permissions
# History:
# 2016/8/20 leiyuxing First release
PATH=/bin:/sbin:/use/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
#1.让用户输入文件名,并且判断用户是否真的有输入字符串
echo -e "Please input a filename, I will check the filename's type and \
permission. \n\n"
read -p "Input a filename : " filename
test -z $filename && 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="regulare 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 are : $perm"
验证结果:
[leiyuxing@centos6 scripts]$ sh sh05.sh
Please input a filename, I will check the filename's type and permission.
Input a filename : a
The filename: a is a directory
And the permissions are : readable writable executable
[leiyuxing@centos6 scripts]$ b
-bash: b: command not found
[leiyuxing@centos6 scripts]$ sh sh05.sh
Please input a filename, I will check the filename's type and permission.
Input a filename : b
The filename 'b' Do NOT exist
[leiyuxing@centos6 scripts]$ ls
a filename20160819 sh01.sh sh03.sh sh05.sh
filename20160818 filename20160820 sh02.sh sh04.sh
4.利用判断符号[]
设置如下案例:
(1)当执行一个程序的时候,这个程序会让用户选择Y或N;
(2)如果用户输入Y或y时,就显示“OK,continue”;
(3)如果用户输入n或N时,就显示“Oh,interrupt!”;
(4)如果不是Y/y/N/n之内的其他字符,就显示”I dont’t know what your choice is”。
[leiyuxing@centos6 scripts]$ vim sh06.sh
#!/bin/bash
# program:
# This program shows the user's choice
# History:
# 2016/8/20 leiyuxing First release
PATH=/bin:/sbin:/use/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 "Oh, interrupt!" && exit 0
echo "I don't know what your choice is" && exit 0
验证结果:
[leiyuxing@centos6 scripts]$ sh sh06.sh
Please input (Y/N) : Y
OK, continue
[leiyuxing@centos6 scripts]$ sh sh06.sh
Please input (Y/N) : N
Oh, interrupt
[leiyuxing@centos6 scripts]$ sh sh06.sh
Please input (Y/N) : x
I don't know what your choice is
5.shell script的默认变量($0,$1...)
假设我要执行一个可以携带参数的script,执行脚本后屏幕显示如下数据:
(1)程序的文件名;
(2)共有几个参数;
(3)若参数的个数小于2则告知用户参数数量太少;
(4)全部的参数内容;
(5)第一个参数;
(6)第二个参数。
[leiyuxing@centos6 scripts]$ vim sh07.sh
#!/bin/bash
# program:
# Program shows the script name, parameters...
# History:
# 2016/8/20 leiyuxing First release
PATH=/bin:/sbin:/use/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
echo "The script name is ==> $0"
echo "Total parameter number is ==> $#"
[ "$#" -1t 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"
验证结果:
[leiyuxing@centos6 scripts]$ sh sh07.sh theone haha quot
The script name is ==> sh07.sh //文件名
Total parameter number is ==> 3 //果然有3个参数
sh07.sh: line 11: [: -1t: binary operator expected
Your whole parameter is ==> 'theone haha quot' //参数的内容全部
The 1st parameter ==> theone //第一个参数
The 2nd parameter ==> haha //第二个参数
6.条件判断式
(1)利用if...then
格式:
If [条件判断式]; then
当条件判断式成立时,可以进行的命令工作内容;
fi <==将if反过来写,就成为fi,结束之意!
例:
[leiyuxing@centos6 scripts]$ vim sh08.sh
#!/bin/bash
# program:
# This program shows the user's choice
# History:
# 2016/8/20 leiyuxing First release
PATH=/bin:/sbin:/use/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 "Oh, interrupt!"
exit 0
fi
echo "I don't know what your choice is" && exit 0
验证结果:
[leiyuxing@centos6 scripts]$ sh sh08.sh
Please input (Y/N) : Y
OK, continue
[leiyuxing@centos6 scripts]$ sh sh08.sh
Please input (Y/N) : N
Oh, interrupt!
[leiyuxing@centos6 scripts]$ sh sh08.sh
Please input (Y/N) : Z
I don't know what your choice i
(2)利用case...esac判断
格式:
case $变量名称 in //关键字为case ,还有变量前有$
“第一个变量内容”) //每个变量内容建议用双引号括起来,关键字则为小括号 )
程序段
;;
“第二个变量内容”)
程序段
;;
*) //最后一个变量内容都会用 * 来代表所有其他值
不包括第一个变量内容和第二个变量的其他程序执行段
exit 1
;;
esac //最终的case结尾!“反过来写”
例:
[leiyuxing@centos6 scripts]$ vim sh09.sh
#!/bin/bash
# program:
# Show ”Hello" from $1... by using case ... esac
# History:
# 2016/8/20 leiyuxing First release
PATH=/bin:/sbin:/use/bin:/usr/sbin:/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
验证结果:
[leiyuxing@centos6 scripts]$ sh sh09.sh
You MUST input parameters,ex> {sh09.sh someword}
[leiyuxing@centos6 scripts]$ sh sh09.sh test
Usage sh09.sh {hello}
7.循环(loop)
(1)for...do...done(固定循环)
格式:
for var in con1 con2 con3 ...
do
程序段
Done
例:
假设我有三种动物,分别是dog,cat,pig三种,我想每一行都输出这样:“There are dogs...”之类的字样,则可以:
[leiyuxing@centos6 scripts]$ vim sh10.sh
#!/bin/bash
# program:
# Using for...loop to print 3 animals
# History:
# 2016/8/20 leiyuxing First release
PATH=/bin:/sbin:/use/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
for animal in dog cat pig
do
echo "There are ${animal}s..."
Done
验证结果:
[leiyuxing@centos6 scripts]$ sh sh10.sh
There are dogs...
There are cats...
There are pigs...
(2)while do done,until do done(不定循环)
格式:
while [ condition ] //中括号内的状态就是判断式
do //do是循环的而开始
程序段落
Done //done是循环的结束
另一种格式:
until [ condition ]
do
程序段落
done
示例一:
[leiyuxing@centos6 scripts]$ vim sh11.sh
#!/bin/bash
# program:
# Repeat question until user input correct answer.
# History:
# 2016/8/20 leiyuxing First release
PATH=/bin:/sbin:/use/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
while [ "$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."
验证结果:
[leiyuxing@centos6 scripts]$ sh sh11.sh
Please input yes/YES to stop this program: yes
OK! you input the correct answer.
[leiyuxing@centos6 scripts]$ sh sh11.sh
Please input yes/YES to stop this program: YES
OK! you input the correct answer.
示例二:
[leiyuxing@centos6 scripts]$ vim sh12.sh
#!/bin/bash
# program:
# Repeat question until user input correct answer.
# History:
# 2016/8/20 leiyuxing First release
PATH=/bin:/sbin:/use/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
until [ "$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."
验证结果:
[leiyuxing@centos6 scripts]$ sh sh12.sh
Please input yes/YES to stop this program: YES
OK! you input the correct answer.
[leiyuxing@centos6 scripts]$ sh sh12.sh
Please input yes/YES to stop this program: yes
OK! you input the correct answer.
8.利用function功能
格式:
Function fname () {
程序段
}
例:
[leiyuxing@centos6 scripts]$ vim sh13.sh
#!/bin/bash
# program:
# Use function to repeat information.
# History:
# 2016/8/20 leiyuxing First release
PATH=/bin:/sbin:/use/bin:/usr/sbin:/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
验证结果:
[leiyuxing@centos6 scripts]$ sh sh13.sh one
This program will print your selection !
Your choice is 1
[leiyuxing@centos6 scripts]$ sh sh13.sh two
This program will print your selection !
Your choice is 2
[leiyuxing@centos6 scripts]$ sh sh13.sh three
This program will print your selection !
Your choice is 3
9.shell script的追踪与调试
#sh [-nvx] scripts.sh
参数:
-n:不要执行script,仅查询语法问题;
-v:在执行script前,先将script的内容输出到屏幕上;
-x:将使用到的script的内容显示到屏幕上,这是很有用的参数!
示例一:测试sh02.sh有无语法问题
[leiyuxing@centos6 scripts]$ sh -n sh02.sh
//若语法没有问题,则不会显示任何信息!
示例二:将sh10.sh的执行过程全部列出来
[leiyuxing@centos6 scripts]$ sh -x sh10.sh
+ PATH=/bin:/sbin:/use/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:/home/leiyuxing/bin
+ export PATH
+ for animal in dog cat pig
+ echo 'There are dogs...'
There are dogs...
+ for animal in dog cat pig
+ echo 'There are cats...'
There are cats...
+ for animal in dog cat pig
+ echo 'There are pigs...'
There are pigs...