`

第十三章 简单的 shell script 练习

 
阅读更多
第一支 script 的撰写与运行

如同前面讲到的,shell script 其实就是纯文字档,我们可以编辑这个文件,然后让这个文件来帮我们一次运行多个命令, 或者是利用一些运算与逻辑判断来帮我们达成某些功能。所以啦,要编辑这个文件的内容时,当然就需要具备有 bash 命令下达的相关认识。下达命令需要注意的事项在第五章的开始下达命令小节内已经提过,有疑问请自行回去翻阅。 在 shell script 的撰写中还需要用到底下的注意事项:

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

如此一来,我们在 script 内所撰写的程序,就会被一行一行的运行。现在我们假设你写的这个程序档名是 /home/dmtsai/shell.sh 好了,那如何运行这个文件?很简单,可以有底下几个方法:

直接命令下达: shell.sh 文件必须要具备可读与可运行 (rx) 的权限,然后:

1.绝对路径:使用 /home/dmtsai/shell.sh 来下达命令;
2.相对路径:假设工作目录在 /home/dmtsai/ ,则使用 ./shell.sh 来运行
3.变量『PATH』功能:将 shell.sh 放在 PATH 指定的目录内,例如: ~/bin/

以 bash 程序来运行:透过『 bash shell.sh 』或『 sh shell.sh 』来运行

反正重点就是要让那个 shell.sh 内的命令可以被运行的意思啦! 咦!那我为何需要使用 『./shell.sh 』来下达命令?忘记了吗?回去第十一章内的命令搜寻顺序察看一下, 你就会知道原因了!同时,由於 CentOS 默认使用者家目录下的 ~/bin 目录会被配置到 $PATH 内,所以你也可以将 shell.sh 创建在 /home/dmtsai/bin/ 底下 ( ~/bin 目录需要自行配置) 。此时,若 shell.sh 在 ~/bin 内且具有 rx 的权限,那就直接输入 shell.sh 即可运行该脚本程序!

那为何『 sh shell.sh 』也可以运行呢?这是因为 /bin/sh 其实就是 /bin/bash (连结档),使用 sh shell.sh 亦即告诉系统,我想要直接以 bash 的功能来运行 shell.sh 这个文件内的相关命令的意思所以此时你的 shell.sh 只要有 r 的权限即可被运行喔!而我们也可以利用 sh 的参数,如 -n 及 -x 来检查与追踪 shell.sh 的语法是否正确呢! ^_^

撰写第一支 script

在武侠世界中,不论是那个门派,要学武功要从扫地做起,那么要学程序呢?呵呵,肯定是由『秀出 Hello World!』 这个字眼开始的!OK!那么鸟哥就先写一支 script 给大家瞧一瞧:

[root@www ~]# mkdir scripts; cd scripts
[root@www scripts]# vi sh01.sh
#!/bin/bash
# Program:
#       This program shows "Hello World!" in your screen.
# History:
# 2005/08/23	VBird	First release
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
echo -e "Hello World! \a \n"
exit 0


1.第一行 #!/bin/bash 在宣告这个 script 使用的 shell 名称:
因为我们使用的是 bash ,所以,必须要以『 #!/bin/bash 』来宣告这个文件内的语法使用 bash 的语法!那么当这个程序被运行时,他就能够加载 bash 的相关环境配置档 (一般来说就是 non-login shell 的 ~/.bashrc), 并且运行 bash 来使我们底下的命令能够运行!这很重要的!(在很多状况中,如果没有配置好这一行, 那么该程序很可能会无法运行,因为系统可能无法判断该程序需要使用什么 shell 来运行啊!)

2.程序内容的说明:
整个 script 当中,除了第一行的『 #! 』是用来宣告 shell 的之外,其他的 # 都是『注解』用途! 所以上面的程序当中,第二行以下就是用来说明整个程序的基本数据。一般来说, 建议你一定要养成说明该 script 的:1. 内容与功能; 2. 版本资讯; 3. 作者与联络方式; 4. 建档日期;5. 历史纪录 等等。这将有助於未来程序的改写与 debug 呢!

3.主要环境变量的宣告:
建议务必要将一些重要的环境变量配置好,鸟哥个人认为, PATH 与 LANG (如果有使用到输出相关的资讯时) 是当中最重要的! 如此一来,则可让我们这支程序在进行时,可以直接下达一些外部命令,而不必写绝对路径呢!比较好啦!

4.主要程序部分
就将主要的程序写好即可!在这个例子当中,就是 echo 那一行啦!

运行成果告知 (定义回传值)
是否记得我们在第十一章里面要讨论一个命令的运行成功与否,可以使用 $? 这个变量来观察~ 那么我们也可以利用 exit 这个命令来让程序中断,并且回传一个数值给系统。 在我们这个例子当中,鸟哥使用 exit 0 ,这代表离开 script 并且回传一个 0 给系统, 所以我运行完这个 script 后,若接著下达 echo $? 则可得到 0 的值喔! 更聪明的读者应该也知道了,呵呵!利用这个 exit n (n 是数字) 的功能,我们还可以自订错误信息, 让这支程序变得更加的 smart 呢!
接下来透过刚刚上头介绍的运行方法来运行看看结果吧!

[root@www scripts]# sh sh01.sh
Hello World !


你会看到萤幕是这样,而且应该还会听到『咚』的一声,为什么呢?还记得前一章提到的 printf 吧?用 echo 接著那些特殊的按键也可以发生同样的事情~ 不过, echo 必须要加上 -e 的选项才行!呵呵!在你写完这个小 script 之后,你就可以大声的说:『我也会写程序了』!哈哈! 很简单有趣吧~ ^_^

另外,你也可以利用:『chmod a+x sh01.sh; ./sh01.sh』来运行这个 script 的呢!



在第一支 shell script 撰写完毕之后,相信你应该具有基本的撰写功力了。 接下来,在开始更深入的程序概念之前,我们先来玩一些简单的小范例好了。 底下的范例中,达成结果的方式相当的多,建议你先自行撰写看看,写完之后再与鸟哥写的内容比对, 这样才能更加深概念喔!好!不罗唆,我们就一个一个来玩吧!

简单范例

底下的范例在很多的脚本程序中都会用到,而底下的范例又都很简单!值得参考看看喔!

对谈式脚本:变量内容由使用者决定

很多时候我们需要使用者输入一些内容,好让程序可以顺利运行。 简单的来说,大家应该都有安装过软件的经验,安装的时候,他不是会问你『要安装到那个目录去』吗? 那个让使用者输入数据的动作,就是让使用者输入变量内容啦。

你应该还记得在十一章 bash 的时候,我们有学到一个 read 命令吧?现在,请你以 read 命令的用途,撰写一个 script ,他可以让使用者输入:1. first name 与 2. last name, 最后并且在萤幕上显示:『Your full name is: 』的内容:

[root@www scripts]# vi sh02.sh
#!/bin/bash
# Program:
#	User inputs his first name and last name.  Program shows his full name.
# History:
# 2005/08/23	VBird	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" # 结果由萤幕输出


将上面这个 sh02.sh 运行一下,你就能够发现使用者自己输入的变量可以让程序所取用,并且将他显示到萤幕上! 接下来,如果想要制作一个每次运行都会依据不同的日期而变化结果的脚本呢?

随日期变化:利用 date 进行文件的创建

想像一个状况,假设我的服务器内有数据库,数据库每天的数据都不太一样,因此当我备份时, 希望将每天的数据都备份成不同的档名,这样才能够让旧的数据也能够保存下来不被覆盖。 哇!不同档名呢!这真困扰啊?难道要我每天去修改 script ?

不需要啊!考虑每天的『日期』并不相同,所以我可以将档名取成类似: backup.2009-02-14.data , 不就可以每天一个不同档名了吗?呵呵!确实如此。那个 2009-02-14 怎么来的?那就是重点啦!接下来出个相关的例子: 假设我想要创建三个空的文件 (透过 touch) ,档名最开头由使用者输入决定,假设使用者输入 filename 好了,那今天的日期是 2009/02/14 , 我想要以前天、昨天、今天的日期来创建这些文件,亦即 filename_20090212, filename_20090213, filename_20090214 ,该如何是好?

[root@www scripts]# vi sh03.sh
#!/bin/bash
# Program:
#	Program creates three files, which named by user's input 
#	and date command.
# History:
# 2005/08/23	VBird	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"


上面的范例鸟哥使用了很多在十一章介绍过的概念: 包括小命令『 $(command) 』的取得信息、变量的配置功能、变量的累加以及利用 touch 命令辅助! 如果你开始运行这个 sh03.sh 之后,你可以进行两次运行:一次直接按 [Enter] 来查阅档名是啥? 一次可以输入一些字节,这样可以判断你的脚本是否设计正确喔!

数值运算:简单的加减乘除

各位看官应该还记得,我们可以使用 declare 来定义变量的类型吧? 当变量定义成为整数后才能够进行加减运算啊!此外,我们也可以利用『 $((计算式)) 』来进行数值运算的。 可惜的是, bash shell 里头默认仅支持到整数的数据而已。OK!那我们来玩玩看,如果我们要使用者输入两个变量, 然后将两个变量的内容相乘,最后输出相乘的结果,那可以怎么做?

[root@www scripts]# vi sh04.sh
#!/bin/bash
# Program:
#	User inputs 2 integer numbers; program will cross these two numbers.
# History:
# 2005/08/23	VBird	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 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"


在数值的运算上,我们可以使用『 declare -i total=$firstnu*$secnu 』 也可以使用上面的方式来进行!基本上,鸟哥比较建议使用这样的方式来进行运算:

var=$((运算内容))

不但容易记忆,而且也比较方便的多,因为两个小括号内可以加上空白字节喔! 未来你可以使用这种方式来计算的呀!至於数值运算上的处理,则有:『 +, -, *, /, % 』等等。 那个 % 是取余数啦~举例来说, 13 对 3 取余数,结果是 13=4*3+1,所以余数是 1 啊!就是:

[root@www scripts]# echo $(( 13 % 3 ))
1


这样了解了吧?多多学习与应用喔! ^_^

script 的运行方式差异 (source, sh script, ./script)

不同的 script 运行方式会造成不一样的结果喔!尤其影响 bash 的环境很大呢!脚本的运行方式除了前面小节谈到的方式之外,还可以利用 source 或小数点 (.) 来运行喔!那么这种运行方式有何不同呢?当然是不同的啦!让我们来说说!

利用直接运行的方式来运行 script

当使用前一小节提到的直接命令下达 (不论是绝对路径/相对路径还是 $PATH 内),或者是利用 bash (或 sh) 来下达脚本时, 该 script 都会使用一个新的 bash 环境来运行脚本内的命令!也就是说,使用者种运行方式时, 其实 script 是在子程序的 bash 内运行的!我们在第十一章 BASH 内谈到 export 的功能时,曾经就父程序/子程序谈过一些概念性的问题, 重点在於:『当子程序完成后,在子程序内的各项变量或动作将会结束而不会传回到父程序中』! 这是什么意思呢?

我们举刚刚提到过的 sh02.sh 这个脚本来说明好了,这个脚本可以让使用者自行配置两个变量,分别是 firstname 与 lastname,想一想,如果你直接运行该命令时,该命令帮你配置的 firstname 会不会生效?看一下底下的运行结果:

[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 中还是不存在的!


上面的结果你应该会觉得很奇怪,怎么我已经利用 sh02.sh 配置好的变量竟然在 bash 环境底下无效!怎么回事呢? 如果将程序相关性绘制成图的话,我们以下图来说明。当你使用直接运行的方法来处理时,系统会给予一支新的 bash 让我们来运行 sh02.sh 里面的命令,因此你的 firstname, lastname 等变量其实是在下图中的子程序 bash 内运行的。 当 sh02.sh 运行完毕后,子程序 bash 内的所有数据便被移除,因此上表的练习中,在父程序底下 echo $firstname 时, 就看不到任何东西了!这样可以理解吗?



利用 source 来运行脚本:在父程序中运行

如果你使用 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  <==嘿嘿!有数据产生喔!

竟然生效了!没错啊!因为 source 对 script 的运行方式可以使用底下的图示来说明! sh02.sh 会在父程序中运行的,因此各项动作都会在原本的 bash 内生效!这也是为啥你不注销系统而要让某些写入 ~/.bashrc 的配置生效时,需要使用『 source ~/.bashrc 』而不能使用『 bash ~/.bashrc 』是一样的啊!

转自:http://vbird.dic.ksu.edu.tw/linux_basic/0340bashshell-scripts_2.php
  • 大小: 3.2 KB
分享到:
评论
发表评论

文章已被作者锁定,不允许评论。

相关推荐

    shell 脚本

    在提供的文件列表中,虽然只有一个名为"第13章.flv"的视频文件,这可能是一个关于Shell脚本教学的视频资源。观看这样的视频教程可以帮助你通过实例学习Shell脚本的使用方法和技巧。 总的来说,掌握Shell脚本不仅...

    shell 基础学习

    /bin/bash`作为第一行,这称为“shebang”,用于指定执行该脚本的Shell类型。接着,你可以开始编写命令和控制结构。 3. **变量**:在Shell脚本中,变量用于存储数据。声明变量时无需指定类型,如`name="John"`。...

    13_学习_Shell_Scripts

    撰写Shell Script的良好习惯** - **注释清晰**:良好的注释可以提高脚本的可读性和维护性。 - **代码格式化**:合理地使用空格和缩进,使代码看起来整洁。 - **变量声明明确**:为变量分配有意义的名字,并在使用...

    shell编程使用手册

    **Shell编程使用手册** Shell编程是Linux和Unix操作系统中的一种脚本编程语言,它允许用户通过命令行界面执行一系列操作,实现自动化任务。这个“Shell编程使用手册”将...不断练习和探索,你将成为Shell编程的高手。

    linux命令的使用与shell脚本学习

    7. `/opt`:存放第三方应用程序。 8. `/root`:超级用户(root)的主目录。 9. `/sbin`:系统管理命令的存放地。 10. `/tmp`:临时文件存储区,系统重启时会被清空。 11. `/usr`:包含用户程序和共享库。 12. `/var`...

    《Linux系统应用与开发教程》所有课后习题和答案.doc

    13. shell 程序设计 * shell 程序设计:使用 shell Script 语言编写程序,实现自动化管理和维护 Linux 系统。 * shell 程序设计的方法:使用 shell Script 语言、编辑 shell 脚本文件等。 14. gcc 的使用与开发 *...

    linux shell脚本基础知识学习

    了解这些基础知识后,你就可以开始编写简单的Shell脚本来自动化日常任务了。随着经验的积累,你将能够处理更复杂的逻辑和系统管理任务。记得练习是掌握Shell脚本的关键,不断实践,你的技能将得到提升。

    LINUX 24学时教程

    第13学时 因特网上的下载与浏览 209 13.1 使用文件传输协议程序来获取文件 209 13.1.1 使用ftp命令检索文件 209 13.1.2 使用ncftp命令进行下载 215 13.2 使用Linux浏览器程序浏览 World Wide Web网 216 13.2.1 使用...

    linux 授课计划

    17. **练习Shell script** (2学时): 学生将编写和运行自己的Shell脚本,加深对Shell编程的理解。 18. **使用判断式** (2学时): 教授条件语句,如`if`, `if-else`, `case`等,用于编写更复杂的脚本。 19. **使用...

    UNIX环境高级编程部分

    #### 第13章:精灵进程 - **精灵进程的特征**:常驻内存的服务进程。 - **编程规则**:编写精灵进程的最佳实践。 - **出错记录**:记录和报告错误的方法。 - **客户机-服务器模型**:精灵进程作为服务器提供服务。 ...

    Linux高级bash编程

    第三部分. 超越基本 9. 变量重游 9.1. 内部变量 9.2. 操作字符串 9.3. 参数替换 9.4. 指定类型的变量:declare或者typeset 9.5. 变量的间接引用 9.6. $RANDOM: 产生随机整数 9.7. 双圆括号结构 10. 循环...

    Advanced Bash-Scripting Guide <>

    第三部分. 超越基本 9. 变量重游 9.1. 内部变量 9.2. 操作字符串 9.3. 参数替换 9.4. 指定类型的变量:declare 或者typeset 9.5. 变量的间接引用 9.6. $RANDOM: 产生随机整数 9.7. 双圆括号结构 10. 循环和分支 10.1....

    学习困难

    13. **Shell版本差异**:不同的Shell有不同的语法和特性,比如Bash、Zsh、Dash等。理解不同Shell之间的差异有助于写出更兼容的脚本。 14. **最佳实践**:了解编写安全、可维护的Shell脚本的最佳实践,如避免命令...

    高级Bash编程

    通过丰富的实例和练习,读者将逐步掌握Shell脚本的编写技巧。 #### 二、基本概念与入门 ##### 2.1 Sha-Bang(#!)的使用 在Bash脚本的第一行,通常会使用`#!/bin/bash`这样的形式来指定解释器。这被称为“sha-bang...

    javascript讲义(1).pptx

    // 方法一:使用第三个变量 var temp = a; a = b; b = temp; // 方法二:使用加减法 a = a + b; b = a - b; a = a - b; // 方法三:使用异或运算 a = a ^ b; b = a ^ b; a = a ^ b; ``` #### 结论...

Global site tag (gtag.js) - Google Analytics