码迷,mamicode.com
首页 > 系统相关 > 详细

鸟哥的Linux私房菜_基础版_学习笔记9:第十三章 学习 Shell Scripts

时间:2015-05-27 10:22:09      阅读:311      评论:0      收藏:0      [点我收藏+]

标签:linux   鸟哥私房菜   

13.1 什么是 Shell scripts
13.1.1 干嘛学习 shell scripts
13.1.2 第一支 script 的撰写与运行
在 shell script 的撰写中还需要用到底下的注意事项:
  1. 命令的运行是从上而下、从左而右的分析与运行;
  2. 命令的下达就如同第五章内提到的: 命令、选项与参数间的多个空白都会被忽略掉;
  3. 空白行也将被忽略掉,并且 [tab] 按键所推开的空白同样视为空白键;
  4. 如果读取到一个 Enter 符号 (CR) ,就尝试开始运行该行 (或该串) 命令;
  5. 至於如果一行的内容太多,则可以使用『 \[Enter] 』来延伸至下一行;
  6. 『 # 』可做为注解!任何加在 # 后面的数据将全部被视为注解文字而被忽略!

假设你写的这个程序档名是 /home/dmtsai/shell.sh 好了,那如何运行这个文件?很简单,可以有底下几个方法:

  • 直接命令下达: shell.sh 文件必须要具备可读与可运行 (rx) 的权限,然后:
    • 绝对路径:使用 /home/dmtsai/shell.sh 来下达命令;
    • 相对路径:假设工作目录在 /home/dmtsai/ ,则使用 ./shell.sh 来运行
    • 变量『PATH』功能:将 shell.sh 放在 PATH 指定的目录内,例如: ~/bin/
  • 撰写第一支 script
1、第一行 #!/bin/bash 在宣告这个 script 使用的 shell 名称:
必须要以『 #!/bin/bash 』来宣告这个文件内的语法使用 bash 的语法!
(在很多状况中,如果没有配置好这一行, 那么该程序很可能会无法运行)
2、程序内容的说明:
一般来说, 建议你一定要养成说明该 script 的:1. 内容与功能; 2. 版本资讯; 3. 作者与联络方式; 4. 建档日期;5. 历史纪录 等等。
3、主要环境变量的宣告:
建议务必要将一些重要的环境变量配置好,可以直接下达一些外部命令,而不必写绝对路径呢!
4、主要程序部分
5、运行成果告知 (定义回传值)
使用 exit 0 ,这代表离开 script 并且回传一个 0 给系统

接下来透过刚刚上头介绍的运行方法来运行看看结果吧!

[root@www scripts]# sh sh01.sh
Hello World !
另外,你也可以利用:『chmod a+x sh01.sh; ./sh01.sh』来运行这个 script 的呢!
13.2 简单的 shell script 练习
13.2.1 简单范例
  • 对谈式脚本:变量内容由使用者决定
[root@www scripts]# vi sh02.sh#!/bin/bash

read -p "Please input your first name: " firstname  # 提示使用者输入
read -p "Please input your last name:  " lastname   # 提示使用者输入
echo -e "\nYour full name is: $firstname $lastname" # 结果由萤幕输出
 
  • 随日期变化:利用 date 进行文件的创建
[root@www scripts]# vi sh03.sh#!/bin/bash

# 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"

13.2.2 script 的运行方式差异 (source, sh script, ./script)
  • 利用直接运行的方式来运行 script
[root@www scripts]# echo $firstname $lastname
    <==确认了,这两个变量并不存在喔!
[root@www scripts]# sh sh02.sh
Please input your first name: VBird <==这个名字是鸟哥自己输入的
Please input your last name:  Tsai 

Your full name is: VBird Tsai      <==看吧!在 script 运行中,这两个变量有生效
[root@www scripts]# echo $firstname $lastname
    <==事实上,这两个变量在父程序的 bash 中还是不存在的!
技术分享
图 2.2.1、sh02.sh 在子程序中运行
  • 利用 source 来运行脚本:在父程序中运行
[root@www scripts]# source sh02.sh
Please input your first name: VBird
Please input your last name:  Tsai

Your full name is: VBird Tsai
[root@www scripts]# echo $firstname $lastname
VBird Tsai  <==嘿嘿!有数据产生喔!
技术分享
图 2.2.2、sh02.sh 在父程序中运行

13.3 善用判断式
13.3.1 利用 test 命令的测试功能
[root@www ~]# test -e /dmtsai
[root@www ~]# test -e /dmtsai && echo "exist" || echo "Not exist"
Not exist  <==结果显示不存在啊!
测试的标志 代表意义
1. 关於某个档名的『文件类型』判断,如 test -e filename 表示存在否
-e 该『档名』是否存在?(常用)
-f 该『档名』是否存在且为文件(file)?(常用)
-d 该『档名』是否存在且为目录(directory)?(常用)
-b 该『档名』是否存在且为一个 block device 装置?
-c 该『档名』是否存在且为一个 character device 装置?
-S 该『档名』是否存在且为一个 Socket 文件?
-p 该『档名』是否存在且为一个 FIFO (pipe) 文件?
-L 该『档名』是否存在且为一个连结档?
2. 关於文件的权限侦测,如 test -r filename 表示可读否 (但 root 权限常有例外)
-r 侦测该档名是否存在且具有『可读』的权限?
-w 侦测该档名是否存在且具有『可写』的权限?
-x 侦测该档名是否存在且具有『可运行』的权限?
-u 侦测该档名是否存在且具有『SUID』的属性?
-g 侦测该档名是否存在且具有『SGID』的属性?
-k 侦测该档名是否存在且具有『Sticky bit』的属性?
-s 侦测该档名是否存在且为『非空白文件』?
3. 两个文件之间的比较,如: test file1 -nt file2
-nt (newer than)判断 file1 是否比 file2 新
-ot (older than)判断 file1 是否比 file2 旧
-ef 判断 file1 与 file2 是否为同一文件,可用在判断 hard link 的判定上。 主要意义在判定,两个文件是否均指向同一个 inode 哩!
4. 关於两个整数之间的判定,例如 test n1 -eq n2
-eq 两数值相等 (equal)
-ne 两数值不等 (not equal)
-gt n1 大於 n2 (greater than)
-lt n1 小於 n2 (less than)
-ge n1 大於等於 n2 (greater than or equal)
-le n1 小於等於 n2 (less than or equal)
5. 判定字串的数据
test -z string 判定字串是否为 0 ?若 string 为空字串,则为 true
test -n string 判定字串是否非为 0 ?若 string 为空字串,则为 false。
注: -n 亦可省略
test str1 = str2 判定 str1 是否等於 str2 ,若相等,则回传 true
test str1 != str2 判定 str1 是否不等於 str2 ,若相等,则回传 false
6. 多重条件判定,例如: test -r filename -a -x filename
-a (and)两状况同时成立!例如 test -r file -a -x file,则 file 同时具有 r 与 x 权限时,才回传 true。
-o (or)两状况任何一个成立!例如 test -r file -o -x file,则 file 具有 r 或 x 权限时,就可回传 true。
! 反相状态,如 test ! -x file ,当 file 不具有 x 时,回传 true

13.3.2 利用判断符号 [ ]

如果我想要知道 $HOME 这个变量是否为空的,可以这样做:

[root@www ~]# [ -z "$HOME" ] ; echo $?

必须要注意中括号的两端需要有空白字节来分隔喔! 假设我空白键使用『□』符号来表示,那么,在这些地方你都需要有空白键:

[  "$HOME"  ==  "$MAIL"  ]
[□"$HOME"□==□"$MAIL"□]

所以说,你最好要注意:

  • 在中括号 [] 内的每个组件都需要有空白键来分隔;
  • 在中括号内的变量,最好都以双引号括号起来;
  • 在中括号内的常数,最好都以单或双引号括号起来。

为什么要这么麻烦啊?直接举例来说,假如我配置了 name="VBird Tsai" ,然后这样判定:

[root@www ~]# name="VBird Tsai"
[root@www ~]# [ $name == "VBird" ]
bash: [: too many arguments
[root@www scripts]# vi sh06.sh

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
13.3.3 Shell script 的默认变量($0, $1...)

其实 script 针对参数已经有配置好一些变量名称了!对应如下:

/path/to/scriptname  opt1  opt2  opt3  opt4 
       $0             $1    $2    $3    $4
  • $# :代表后接的参数『个数』,以上表为例这里显示为『 4 』;
  • $@ :代表『 "$1" "$2" "$3" "$4" 』之意,每个变量是独立的(用双引号括起来);
  • $* :代表『 "$1c$2c$3c$4" 』,其中 c 为分隔字节,默认为空白键, 所以本例中代表『 "$1 $2 $3 $4" 』之意。
[root@www scripts]# vi sh07.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"

运行结果如下:

[root@www scripts]# sh sh07.sh theone haha quot
The script name is        ==> sh07.sh            <==档名
Total parameter number is ==> 3                  <==果然有三个参数
Your whole parameter is   ==> ‘theone haha quot‘ <==参数的内容全部
The 1st parameter         ==> theone             <==第一个参数
The 2nd parameter         ==> haha               <==第二个参数
  • shift:造成参数变量号码偏移
[root@www scripts]# vi sh08.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   ==> ‘$@‘"

这玩意的运行成果如下:

[root@www scripts]# sh sh08.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   <==第二次偏移掉三个,two three four 不见了
Your whole parameter is   ==> ‘five six‘
13.4 条件判断式
13.4.1 利用 if .... then

  • 单层、简单条件判断式
if [ 条件判断式 ]; then
	当条件判断式成立时,可以进行的命令工作内容;
fi   <==将 if 反过来写,就成为 fi 啦!结束 if 之意!
  • && 代表 AND ;
  • || 代表 or ;

 现在我们来将 sh06.sh 这个脚本修改成为 if ... then 的样式来看看:

[root@www scripts]# cp sh06.sh sh06-2.sh  <==用改的比较快!
[root@www scripts]# vi sh06-2.sh

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

  • 多重、复杂条件判断式
# 一个条件判断,分成功进行与失败进行 (else)
if [ 条件判断式 ]; then
	当条件判断式成立时,可以进行的命令工作内容;
else
	当条件判断式不成立时,可以进行的命令工作内容;
fi

如果考虑更复杂的情况,则可以使用这个语法:

# 多个条件判断 (if ... elif ... elif ... else) 分多种不同情况运行
if [ 条件判断式一 ]; then
	当条件判断式一成立时,可以进行的命令工作内容;
elif [ 条件判断式二 ]; then
	当条件判断式二成立时,可以进行的命令工作内容;
else
	当条件判断式一与二均不成立时,可以进行的命令工作内容;
fi

好!我们来将 sh06-2.sh 改写成这样:

[root@www scripts]# cp sh06-2.sh sh06-3.sh
[root@www scripts]# vi sh06-3.sh

read -p "Please input (Y/N): " yn

if [ "$yn" == "Y" ] || [ "$yn" == "y" ]; then
	echo "OK, continue"
elif [ "$yn" == "N" ] || [ "$yn" == "n" ]; then
	echo "Oh, interrupt!"
else
	echo "I don‘t know what your choice is"
fi

我们在第十一章已经学会了 grep 这个好用的玩意儿,那么多学一个叫做 netstat 的命令,这个命令可以查询到目前主机有开启的网络服务端口 (service ports), 相关的功能我们会在服务器架设篇继续介绍,这里你只要知道,我可以利用『 netstat -tuln 』来取得目前主机有启动的服务, 而且取得的资讯有点像这样:

[root@www ~]# netstat -tuln
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address     Foreign Address   State
tcp        0      0 0.0.0.0:111       0.0.0.0:*         LISTEN
tcp        0      0 127.0.0.1:631     0.0.0.0:*         LISTEN
tcp        0      0 127.0.0.1:25      0.0.0.0:*         LISTEN
tcp        0      0 :::22             :::*              LISTEN
udp        0      0 0.0.0.0:111       0.0.0.0:*
udp        0      0 0.0.0.0:631       0.0.0.0:*
#封包格式           本地IP:端口       远程IP:端口       是否监听

上面的重点是『Local Address (本地主机的IP与端口对应)』那个栏位,他代表的是本机所启动的网络服务! IP的部分说明的是该服务位於那个介面上,若为 127.0.0.1 则是仅针对本机开放,若是 0.0.0.0 或 ::: 则代表对整个 Internet 开放 (更多资讯请参考服务器架设篇的介绍)。 每个端口 (port) 都有其特定的网络服务,几个常见的 port 与相关网络服务的关系是:

  • 80: WWW
  • 22: ssh
  • 21: ftp
  • 25: mail
  • 111: RPC(远程程序呼叫)
  • 631: CUPS(列印服务功能)

假设我的主机有兴趣要侦测的是比较常见的 port 21, 22, 25及 80 时,那我如何透过 netstat 去侦测我的主机是否有开启这四个主要的网络服务端口呢?由於每个服务的关键字都是接在冒号『 : 』后面, 所以可以藉由撷取类似『 :80 』来侦测的!那我就可以简单的这样去写这个程序喔:

[root@www scripts]# vi sh10.sh

# 1. 先作一些告知的动作而已~
echo "Now, I will detect your Linux server‘s services!"
echo -e "The www, ftp, ssh, and mail will be detect! \n"

# 2. 开始进行一些测试的工作,并且也输出一些资讯罗!
testing=$(netstat -tuln | grep ":80 ")   # 侦测看 port 80 在否?
if [ "$testing" != "" ]; then
	echo "WWW is running in your system."
fi
testing=$(netstat -tuln | grep ":22 ")   # 侦测看 port 22 在否?
if [ "$testing" != "" ]; then
	echo "SSH is running in your system."
fi
testing=$(netstat -tuln | grep ":21 ")   # 侦测看 port 21 在否?
if [ "$testing" != "" ]; then
	echo "FTP is running in your system."
fi
testing=$(netstat -tuln | grep ":25 ")   # 侦测看 port 25 在否?
if [ "$testing" != "" ]; then
	echo "Mail is running in your system."
fi

能不能写个脚本程序来跑,让使用者输入他的退伍日期,让你去帮他计算还有几天才退伍?

利用『 date --date="YYYYMMDD" +%s 』转成秒数后,接下来的动作就容易的多了!如果你已经写完了程序,对照底下的写法试看看:

[root@www scripts]# vi sh11.sh

# 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>20090401): " date2

# 2. 测试一下,这个输入的内容是否正确?利用正规表示法罗~
date_d=$(echo $date2 |grep ‘[0-9]\{8\}‘)   # 看看是否有八个数字
if [ "$date_d" == "" ]; then
	echo "You input the wrong date format...."
	exit 1
fi

# 3. 开始计算日期罗~
declare -i date_dem=`date --date="$date2" +%s`    # 退伍日期秒数
declare -i date_now=`date +%s`                    # 现在日期秒数
declare -i date_total_s=$(($date_dem-$date_now))  # 剩余秒数统计
declare -i date_d=$(($date_total_s/60/60/24))     # 转为日数
if [ "$date_total_s" -lt "0" ]; then              # 判断是否已退伍
	echo "You had been demobilization before: " $((-1*$date_d)) " ago"
else
	declare -i date_h=$(($(($date_total_s-$date_d*60*60*24))/60/60))
	echo "You will demobilize after $date_d days and $date_h hours."
fi

13.4.2 利用 case ..... esac 判断
case  $变量名称 in   <==关键字为 case ,还有变量前有钱字号
  "第一个变量内容")   <==每个变量内容建议用双引号括起来,关键字则为小括号 )
	程序段
	;;            <==每个类别结尾使用两个连续的分号来处理!
  "第二个变量内容")
	程序段
	;;
  *)                  <==最后一个变量内容都会用 * 来代表所有其他值
	不包含第一个变量内容与第二个变量内容的其他程序运行段
	exit 1
	;;
esac                  <==最终的 case 结尾!『反过来写』思考一下!

[root@www scripts]# vi sh09-2.sh
case $1 in
  "hello")
	echo "Hello, how are you ?"
	;;
  "")
	echo "You MUST input parameters, ex> {$0 someword}"
	;;
  *)   # 其实就相当於万用字节,0~无穷多个任意字节之意!
	echo "Usage $0 {hello}"
	;;
esac

一般来说,使用『 case $变量 in 』这个语法中,当中的那个『 $变量 』大致有两种取得的方式:

  • 直接下达式:例如上面提到的,利用『 script.sh variable 』 的方式来直接给予 $1 这个变量的内容,这也是在 /etc/init.d 目录下大多数程序的设计方式。

  • 互动式:透过 read 这个命令来让使用者输入变量的内容。

这么说或许你的感受性还不高,好,我们直接写个程序来玩玩:让使用者能够输入 one, two, three , 并且将使用者的变量显示到萤幕上,如果不是 one, two, three 时,就告知使用者仅有这三种选择。

[root@www scripts]# vi sh12.sh

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
13.4.3 利用 function 功能
function fname() {
	程序段
}

 要注意的是,因为 shell script 的运行方式是由上而下,由左而右, 因此在 shell script 当中的 function 的配置一定要在程序的最前面, 这样才能够在运行时被找到可用的程序段喔!好~我们将 sh12.sh 改写一下,自订一个名为 printit 的函数来使用喔:

[root@www scripts]# vi sh12-2.sh

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 也是拥有内建变量的~他的内建变量与 shell script 很类似, 函数名称代表示 $0 ,而后续接的变量也是以 $1, $2... 来取代的~ 这里很容易搞错喔~因为『 function fname() { 程序段 } 』内的 $0, $1... 等等与 shell script 的 $0 是不同的。以上面 sh12-2.sh 来说,假如我下达:『 sh sh12-2.sh one 』 这表示在 shell script 内的 $1 为 "one" 这个字串。但是在 printit() 内的 $1 则与这个 one 无关。 我们将上面的例子再次的改写一下,让你更清楚!

[root@www scripts]# vi sh12-3.sh

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

13.5 循环 (loop)
while do done, until do done (不定循环圈)

一般来说,不定回圈最常见的就是底下这两种状态了:

while [ condition ]  <==中括号内的状态就是判断式
do            <==do 是回圈的开始!
	程序段落
done          <==done 是回圈的结束

当 condition 条件成立时,就进行回圈,直到 condition 的条件不成立才停止』的意思。还有另外一种不定回圈的方式:

until [ condition ]
do
	程序段落
done
[root@www scripts]# vi sh13.sh

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."

如果使用 until 呢?呵呵有趣罗~ 他的条件会变成这样:

[root@www scripts]# vi sh13-2.sh

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."

仔细比对一下这两个东西有啥不同喔! ^_^再来,如果我想要计算 1+2+3+....+100 这个数据呢? 利用回圈啊~他是这样的:

[root@www scripts]# vi sh14.sh

s=0  # 这是加总的数值变量
i=0  # 这是累计的数值,亦即是 1, 2, 3....
while [ "$i" != "100" ]
do
	i=$(($i+1))   # 每次 i 都会添加 1 
	s=$(($s+$i))  # 每次都会加总一次!
done
echo "The result of ‘1+2+3+...+100‘ is ==> $s"

嘿嘿!当你运行了『 sh sh14.sh 』之后,就可以得到 5050 这个数据才对啊!


13.5.2 for...do...done (固定循环)
for 这种语法,则是『 已经知道要进行几次循环』的状态!
for var in con1 con2 con3 ...
do
	程序段
done

我们可以做个简单的练习。假设我有三种动物,分别是 dog, cat, elephant 三种, 我想每一行都输出这样:『There are dogs...』之类的字样,则可以:

[root@www scripts]# vi sh15.sh

for animal in dog cat elephant
do
	echo "There are ${animal}s.... "
done

13.5.3 for...do...done 的数值处理
for (( 初始值; 限制值; 运行步阶 ))
do
	程序段
done

值得注意的是,在『运行步阶』的配置上,如果每次添加 1 ,则可以使用类似『i++』的方式,亦即是 i 每次回圈都会添加一的意思。好,我们以这种方式来进行 1 累加到使用者输入的回圈吧!

[root@www scripts]# vi sh19.sh

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"

13.6 shell script 的追踪与 debug

scripts 在运行之前,最怕的就是出现语法错误的问题了!那么我们如何 debug 呢?有没有办法不需要透过直接运行该 scripts 就可以来判断是否有问题呢?呵呵!当然是有的!我们就直接以 bash 的相关参数来进行判断吧!

[root@www ~]# sh [-nvx] scripts.sh
选项与参数:
-n  :不要运行 script,仅查询语法的问题;
-v  :再运行 sccript 前,先将 scripts 的内容输出到萤幕上;
-x  :将使用到的 script 内容显示到萤幕上,这是很有用的参数!

范例一:测试 sh16.sh 有无语法的问题?
[root@www ~]# sh -n sh16.sh 
# 若语法没有问题,则不会显示任何资讯!

范例二:将 sh15.sh 的运行过程全部列出来~
[root@www ~]# sh -x sh15.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 的方式来将命令运行过程也显示出来, 如此使用者可以判断程序码运行到哪一段时会出现相关的资讯!这个功能非常的棒!透过显示完整的命令串, 你就能够依据输出的错误资讯来订正你的脚本了!

熟悉 sh 的用法,将可以使你在管理 Linux 的过程中得心应手!至於在 Shell scripts 的学习方法上面,需要『多看、多模仿、并加以修改成自己的样式!』 是最快的学习手段了!网络上有相当多的朋友在开发一些相当有用的 scripts ,若是你可以将对方的 scripts 拿来,并且改成适合自己主机的样子!那么学习的效果会是最快的呢!

鸟哥的Linux私房菜_基础版_学习笔记9:第十三章 学习 Shell Scripts

标签:linux   鸟哥私房菜   

原文地址:http://blog.csdn.net/keyyuanxin/article/details/46038137

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!