基础知识
使用绝对路径 和相对路径都是 在子shell中执行
./ds.sh 相对路径
/root/ds.sh 绝对路径
ds.sh 吧/root 放入环境变量中
[dmtsai@study bin]$ echo ${firstname} ${lastname}
<==确认了,这两个变量并不存在喔!
[dmtsai@study bin]$ sh showname.sh
Please input your first name: VBird <==这个名字是鸟哥自己输入的
Please input your last name: Tsai
Your full name is: VBird Tsai <==看吧!在 script 运行中,这两个变量有生效
[dmtsai@study bin]$ echo ${firstname} ${lastname}
<==事实上,这两个变量在父程序的 bash 中还是不存在的!
使用source 执行脚本 其实实在父shell中执行的
当然 使用 . showname.sh 也是和 source showname.sh 是一样的
和bash环境中一样 sourve 和 . (小数点) 的作用是一样的
dmtsai@study bin]$ source showname.sh
Please input your first name: VBird
Please input your last name: Tsai
Your full name is: VBird Tsai
[dmtsai@study bin]$ echo ${firstname} $
shell脚本的调试和测试(debug)
[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....
在加号后面的数据其实都是指令
串,由于 sh -x 的方式来将指令执行过程也显示出来, 如此使用者可以判断程序码执行到
哪一段时会出现相关的信息!这个功能非常的棒!通过显示完整的指令串, 你就能够依
据输出的错误信息来订正你的脚本了!
鸟哥本章重点
shell script 是利用 shell 的功能所写的一个“程序 (program)”,这个程序是使用纯文
本文件,将一些 shell 的语法与指令(含外部指令)写在里面, 搭配正则表达式、管
线命令与数据流重导向等功能,以达到我们所想要的处理目的
shell script 用在系统管理上面是很好的一项工具,但是用在处理大量数值运算上, 就
不够好了,因为 Shell scripts 的速度较慢,且使用的 CPU 资源较多,造成主机资源的
分配不良。
在 Shell script 的文件中,指令的执行是从上而下、从左而右的分析与执行;
shell script 的执行,至少需要有 r 的权限,若需要直接指令下达,则需要拥有 r 与 x
的权限;
良好的程序撰写习惯中,第一行要宣告 shell (#!/bin/bash) ,第二行以后则宣告程
序用途、版本、作者等
对谈式脚本可用 read 指令达成;
要创建每次执行脚本都有不同结果的数据,可使用 date 指令利用日期达成;
script 的执行若以 source 来执行时,代表在父程序的 bash 内执行之意!
若需要进行判断式,可使用 test 或中括号 ( [] ) 来处理;
在 script 内,$0, $1, $2…, $@ 是有特殊意义的!
条件判断式可使用 if…then 来判断,若是固定变量内容的情况下,可使用 case $var in
… esac 来处理
循环主要分为不定循环 (while, until) 以及固定循环 (for) ,配合 do, done 来达成
所需任务!
我们可使用 sh -x script.sh 来进行程序的 debug
判断式
必须要注意
中括号的两端需要有空白字符来分隔喔! 假设我空白键使用“□”符号来表示,那么,在这
些地方你都需要有空白键:
[ “$HOME” == “$MAIL” ] [□”$HOME”□==□”$MAIL”□]
在中括号 [] 内的每个元件都需要有空白键来分隔;
在中括号内的变量,最好都以双引号括号起来;
在中括号内的常数,最好都以单或双引号括号起来。
例子
范例一
1. 这个文件是否存在,若不存在则给予一个“Filename does not exist”的讯息,并中断程
序;
2. 若这个文件存在,则判断他是个文件或目录,结果输出“Filename is regular file”或
“Filename is directory”
3. 判断一下,执行者的身份对这个文件或目录所拥有的权限,并输出权限数据!
[dmtsai@study bin]$ vim file_perm.sh
#!/bin/bash
# Program:
#
User input a filename, program will check the flowing:
#
1.) exist? 2.) file/directory? 3.) file permissions
# 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 -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}"
范例二
1. 当执行一个程序的时候,这个程序会让使用者选择 Y 或 N ,
2. 如果使用者输入 Y 或 y 时,就显示“ OK, continue ”
3. 如果使用者输入 n 或 N 时,就显示“ Oh, interrupt !”
4. 如果不是 Y/y/N/n 之内的其他字符,就显示“ I don’t know what your choice is ”
[dmtsai@study bin]$ vim ans_yn.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
[ "${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
位置参数变量
dmtsai@study ~]$ file /etc/init.d/network
/etc/init.d/network: Bourne-Again shell script, ASCII text executable
# 使用 file 来查询后,系统告知这个文件是个 bash 的可执行 script 喔!
[dmtsai@study ~]$ /etc/init.d/network restart
script 是怎么达成这个功能的呢?其实 script 针对参数已经有设置好一些变量名称
了!对应如下:
/path/to/scriptname opt1 opt2 opt3 opt4 $0 $1 $2 $3 $4
这样够清楚了吧?执行的脚本文件名为 $0 这个变量,第一个接的参数就是 $1 啊
~ 所以,只要我们在 script 里面善用 $1 的话,就可以很简单的立即下达某些指令功能
了!除了这些数字的变量之外, 我们还有一些较为特殊的变量可以在 script 内使用来调用
这些参数喔!
$# :代表后接的参数“个数”,以上表为例这里显示为“ 4 ”;
$@ :代表“ “$1” “$2” “$3” “$4” ”之意,每个变量是独立的(用双引号括起来);
$* :代表“ “$1c$2c$3c$4” ”,其中 c 为分隔字符,默认为空白键, 所以本例中代表“
“$1 $2 $3 $4” ”之意。
范例一
自己注意看执行结果的不同
dmtsai@study bin]$ vim how_paras.sh
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}"
执行结果如下:
[dmtsai@study bin]$ sh how_paras.sh theone haha quot
The script name is ==> how_paras.sh <==文件名
Total parameter number is ==> 3 <==果然有三个参数
Your whole parameter is ==> 'theone haha quot' <==参数的内容全部
The 1st parameter ==> theone <==第一个参数
The 2nd parameter ==> haha <==第二个参数
范例二
位置参数变量的偏移 shift
[dmtsai@study bin]$ vim shift_paras.sh
echo "Total parameter number is ==> $#"
echo "Your whole parameter is ==> '$@'"
shift # 进行第一次“一个变量的 shift ”
echo "Total parameter number is ==> $#"
echo "Your whole parameter is ==> '$@'"
shift 3 # 进行第二次“三个变量的 shift ”
echo "Total parameter number is ==> $#"
echo "Your whole parameter is ==> '$@'"
这玩意的执行成果如下:
[dmtsai@study bin]$ sh shift_paras.sh one two three four five six <==给予六个参数
Total parameter number is ==> 6 <==最原始的参数变量情况Your whole parameter is ==> 'one two three four five six'
Total parameter number is ==> 5 <==第一次偏移,看下面发现第一个 one 不见了
Your whole parameter is ==> 'two three four five six'
Total parameter number is ==> 2 <==第二次偏移
那个 shift 会移动变量,而且 shift 后面可以接数字,代
表拿掉最前面的几个参数的意思。 上面的执行结果中,第一次进行 shift 后他的显示情况
是“ one two three four five six”,所以就剩下五个啦!第二次直接拿掉三个,就变成“ two
three four five six ”啦!