1.什么是 Shell Script
在 shell script 的撰写中还需要用到底下的注意事项:
命令的运行是从上而下、从左而右的分析与运行;『 # 』可做为注解!任何加在 # 后面的数据将全部被视为注解文字而被忽略!
那如何运行这个文件?很简单,可以有底下几个方法:
直接命令下达: shell.sh 文件必须要具备可读与可运行 (rx) 的权限,然后:
绝对路径:使用 /home/dmtsai/shell.sh 来下达命令;变量『PATH』功能:将 shell.sh 放在 PATH 指定的目录内,例如: ~/bin/
以 bash 程序来运行:透过『 bash shell.sh 』或『 sh shell.sh 』来运行
撰写第一支 script
大致是这样:
1.第一行 #!/bin/bash 在宣告这个 script 使用的 shell 名称:因为我们使用的是 bash ,所以,必须要以『 #!/bin/bash 』来宣告这个文件内的语法使用 bash 的语法!那么当这个程序被运行时,他就能够加载 bash 的相关环境配置档 (一般来说就是 non-login shell 的 ~/.bashrc), 并且运行 bash 来使我们底下的命令能够运行!
2.程序内容的说明:除了第一行的『 #! 』是用来宣告 shell 的之外,其他的 # 都是『注解』用途!第二行以下就是用来说明整个程序的基本数据。一般来说, 建议你一定要养成说明该 script 的:1. 内容与功能; 2. 版本资讯; 3. 作者与联络方式; 4. 建档日期;5. 历史纪录 等等。这将有助於未来程序的改写与 debug 呢!
3.主要环境变量的宣告:建议务必要将一些重要的环境变量配置好,鸟哥个人认为, PATH 与 LANG (如果有使用到输出相关的资讯时) 是当中最重要的! 如此一来,则可让我们这支程序在进行时,可以直接下达一些外部命令,而不必写绝对路径呢!比较好啦!
4.主要程序部分就将主要的程序写好即可!在这个例子当中,就是 echo 那一行啦!
5.运行成果告知 (定义回传值)2.简单的 shell script 练习
1)简单范例: 对谈式脚本, 随日期变化, 数值运算
对谈式脚本:变量内容由使用者决定
很多时候我们需要使用者输入一些内容,好让程序可以顺利运行。如,可使用 read 命令。
随日期变化:利用 date 进行文件的创建
假设我的服务器内有数据库,数据库每天的数据都不太一样,因此当我备份时, 希望将每天的数据都备份成不同的档名,这样才能够让旧的数据也能够保存下来不被覆盖。 哇!不同档名呢!
数值运算:简单的加减乘除
可以使用 declare 来定义变量的类型吧? 当变量定义成为整数后才能够进行加减运算啊!此外,我们也可以利用『 $((计算式)) 』来进行数值运算的。 可惜的是, bash shell 里头默认仅支持到整数的数据而已。
在数值的运算上,有:『 +, -, *, /, % 』等等。我们可以使用『 declare -i total=$firstnu*$secnu 』 也可以使用上面的方式来进行!基本上,鸟哥比较建议使用这样的方式来进行运算:
var=$((运算内容))
2)script 的运行方式差异 (source, sh script, ./script)
利用直接运行的方式来运行 script
直接命令下达 (不论是绝对路径/相对路径还是 $PATH 内),或者是利用 bash (或 sh) 来下达脚本时, 该 script 都会使用一个新的 bash 环境来运行脚本内的命令!也就是说,使用者种运行方式时, 其实 script 是在子程序的 bash 内运行的!
利用 source 来运行脚本:在父程序中运行
如果你使用 source 来运行命令那就不一样了! sh02.sh 会在父程序中运行的,因此各项动作都会在原本的 bash 内生效!
3.善用判断式
1)利用 test 命令的测试功能
例如:
[root@www ~]# test -e /dmtsai && echo "exist" || echo "Not exist"
测试的标志及代表意义:
1. 关於某个档名的『文件类型』判断,如 test -e filename 表示存在否2)利用判断符号 [ ]
除了我们很喜欢使用的 test 之外,其实,我们还可以利用判断符号『 [ ] 』(就是中括号啦) 来进行数据的判断呢! 举例来说,如果我想要知道 $HOME 这个变量是否为空的,可以这样做:
[root@www ~]# [ -z "$HOME" ] ; echo $?
如果要在 bash 的语法当中使用中括号作为 shell 的判断式时,必须要注意中括号的两端需要有空白字节来分隔喔!
所以说,你最好要注意:
在中括号 [] 内的每个组件都需要有空白键来分隔;3)Shell script 的默认变量($0, $1...): shift
命令可以带有选项与参数,例如 ls -la 可以察看包含隐藏档的所有属性与权限。那么 shell script 能不能在脚本档名后面带有参数呢?举例来说,如果你想要重新启动系统登录档的功能,可以这样做:
[root@www ~]# file /etc/init.d/syslog[root@www ~]# /etc/init.d/syslog restart
那么如果你在 /etc/init.d/syslog 后面加上 stop 呢?没错!就可以直接关闭该服务了!
其实 script 针对参数已经有配置好一些变量名称了!对应如下:
/path/to/scriptname opt1 opt2 opt3 opt4
$0 $1 $2 $3 $4
除了这些数字的变量之外, 我们还有一些较为特殊的变量可以在 script 内使用来呼叫这些参数喔!
$# :代表后接的参数『个数』,以上表为例这里显示为『 4 』;
$@ :代表『 "$1" "$2" "$3" "$4" 』之意,每个变量是独立的(用双引号括起来);
$* :代表『 "$1c$2c$3c$4" 』,其中 c 为分隔字节,默认为空白键, 所以本例中代表『 "$1 $2 $3 $4" 』之意。
1)shift:造成参数变量号码偏移
除此之外,脚本后面所接的变量是否能够进行偏移 (shift) 呢?hift 会移动变量,而且 shift 后面可以接数字,代表拿掉最前面的几个参数的意思。
4.条件判断式
1)利用 if .... then: 单层简单条件, 多重复杂条件, 检验$1内容, 网络状态, 退伍
单层、简单条件判断式
语法如下:
if [ 条件判断式 ]; then
当条件判断式成立时,可以进行的命令工作内容;
fi <==将 if 反过来写,就成为 fi 啦!结束 if 之意!
例如:
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
多重、复杂条件判断式
语法如下:
# 一个条件判断,分成功进行与失败进行 (else)
if [ 条件判断式 ]; then
当条件判断式成立时,可以进行的命令工作内容;
else
当条件判断式不成立时,可以进行的命令工作内容;
fi
# 多个条件判断 (if ... elif ... elif ... else) 分多种不同情况运行
if [ 条件判断式一 ]; then
当条件判断式一成立时,可以进行的命令工作内容;
elif [ 条件判断式二 ]; then
当条件判断式二成立时,可以进行的命令工作内容;
else
当条件判断式一与二均不成立时,可以进行的命令工作内容;
fi
一般来说,如果你不希望使用者由键盘输入额外的数据时, 可以使用上一节提到的参数功能 ($1)!让使用者在下达命令时就将参数带进去!
例子:
if [ "$1" == "hello" ]; then
echo "Hello, how are you ?"
elif [ "$1" == "" ]; then
echo "You MUST input parameters, ex> {$0 someword}"
else
echo "The only parameter is 'hello', ex> {$0 hello}"
fi
2)利用 case ..... esac 判断
语法如下:
case $变量名称 in <==关键字为 case ,还有变量前有钱字号esac <==最终的 case 结尾!『反过来写』思考一下!
例子:
case $1 in
"hello")esac
系统的很多服务的启动 scripts 都是使用这种写法的。
一般来说,使用『 case $变量 in 』这个语法中,当中的那个『 $变量 』大致有两种取得的方式:
直接下达式:例如上面提到的,利用『 script.sh variable 』 的方式来直接给予 $1 这个变量的内容,这也是在 /etc/init.d 目录下大多数程序的设计方式。3)利用 function 功能
语法如下:
function fname() {
程序段
}
因为 shell script 的运行方式是由上而下,由左而右, 因此在 shell script 当中的 function 的配置一定要在程序的最前面, 这样才能够在运行时被找到可用的程序段喔!
另外, function 也是拥有内建变量的~他的内建变量与 shell script 很类似, 函数名称代表示 $0 ,而后续接的变量也是以 $1, $2... 来取代的~
5.回圈 (loop)
1)while...do...done, until...do...done (不定回圈)
语法如下:
while [ condition ] <==中括号内的状态就是判断式
do <==do 是回圈的开始!
程序段落
done <==done 是回圈的结束
while 的中文是『当....时』,所以,这种方式说的是『当 condition 条件成立时,就进行回圈,直到 condition 的条件不成立才停止』的意思。
语法如下:
until [ condition ]done
这种方式恰恰与 while 相反,它说的是『当 condition 条件成立时,就终止回圈, 否则就持续进行回圈的程序段。』2)for...do...done (固定回圈): 帐号检查, 网络状态 $(seq )
语法如下:
for var in con1 con2 con3 ...done
例子:
for animal in dog cat elephant
users=$(cut -d ':' -f1 /etc/passwd) # 撷取帐号名称
for username in $users
for sitenu in $(seq 1 100)
3)for...do...done 的数值处理
语法如下:
for (( 初始值; 限制值; 运行步阶 ))done
例子:
for (( i=1; i<=$nu; i=i+1 ))
6.shell script 的追踪与 debug
scripts 在运行之前,最怕的就是出现语法错误的问题了!那么我们如何 debug 呢?有没有办法不需要透过直接运行该 scripts 就可以来判断是否有问题呢?呵呵!当然是有的!我们就直接以 bash 的相关参数来进行判断吧!
在输出的信息中,在加号后面的数据其实都是命令串,由於 sh -x 的方式来将命令运行过程也显示出来, 如此使用者可以判断程序码运行到哪一段时会出现相关的资讯!
参考自:http://cn.linux.vbird.org/linux_basic/linux_basic.php