📄 0340bashshell-scripts.htm
字号:
target="_blank">针对本文的建议∶http://phorum.vbird.org/viewtopic.php?t=23886</a>
</span>
</span>
</div>
<!-- 本文的正式部分 -->
<hr><a NAME="script"></a><img src="images/penguin-m.gif" alt="大标题的图示" height="34" width="25" align="middle" /><span class="text_h1">什么是 Shell scripts ?</span><br>
<div class=block1>
这个有趣的问题赶紧来回答看看,什么是 shell script 呢? shell 我们在 <a href="0320bash.php">认识 bash</a>
当中已经提过了,那是一个文字介面底下让我们与系统沟通的一个工具介面,那么 script 是啥?
字面上的意义, script 是『脚本、剧本』的意思。整句话是说, shell script 是针对 shell 所写的『剧本!』
什么东西啊?呵呵!其实, <span class=text_import2>shell script 是利用 shell 的功能所写的一个『程式
(program)』,这个程式是使用纯文字档,将一些 shell 的语法与指令写在里面,
搭配正规表示法、管线命令与资料流重导向等功能,以达到我们所想要的处理目的。</span><br><br>
所以,简单的说, shell script 就像是早期 DOS 年代的批次档 (.bat) ,最简单的功能就是将许多指令汇整写在一起,
让使用者很轻易的就能够 one touch (执行一个档案 "shell script" ,就能够一次执行多个指令),
而, shell script 更提供阵列、回圈、条件与逻辑判断等重要功能,让使用者也可以直接以 shell
来撰写程式,而不必使用类似 C 程式语言等传统程式撰写的语法呢!<br><br>
那,这么说您可以了解了吗?是的! shell script 可以简单的被看成是批次档,
也可以被说成是一个程式语言,且这个程式语言由于都是利用 shell 与相关工具指令,
所以不需要编译即可执行,且拥有不错的除错 (debug) 工具,所以,他可以帮助系统管理员快速的管理好主机。<br><br>
<hr><a name="script_why"></a><img src="../images/penguin-s.gif" alt="小标题的图示" height="23" width="16" align="middle" /><span class=text_h2>干嘛学习 shell scripts?</span><br>
<div class=block2>
这是个好问题,我又干嘛一定要学 shell script ?我又不是资讯人,没有写程式的概念,
那我干嘛还要学 shell script 呢?不要学可不可以啊?呵呵~如果 Linux 对您而言,
您只是想要『会用』而已,那么,不需要学 shell script 也还无所谓,这部分先给他跳过去,
等到有空的时候,再来好好的瞧一瞧。但是,如果您是真的想要玩清楚 Linux 的来龙去脉,
那么 shell script 就不可不知,为什么呢?因为∶<br><br>
<li><span class=text_import1>自动化管理的重要依据</span>∶</li>
<div class=block2>
不用鸟哥说您也知道,管理一部主机真不是件简单的事情,每天要进行的任务就有∶
查询登录档、追踪流量、监控使用者使用主机状态、主机各项硬体设备状态、
主机软体更新查询、更不要说得应付其他使用者的突然要求了。而这些工作,
您想要自行手动处理,还是写个简单的程式来帮您每日自动处理分析,若有问题才通知您呢?
当然是让系统自动工作比较好,对吧!呵呵~这就得要良好的 shell script 来帮忙的啦!<br><br>
</div>
<li><span class=text_import1>追踪与管理系统的重要工作</span>∶</li>
<div class=block2>
虽然我们还没有提到服务启动的方法,不过,这里可以先提一下,我们 Linux 系统的服务
( services ) 启动的介面,在 /etc/init.d/ 这个目录下,所有的档案都是 scripts ;
另外,包括开机 (booting) 过程也都是利用 shell script 来帮忙搜寻系统的相关设定资料,
然后再代入各个服务的设定参数啊!举例来说,如果我们想要重新启动系统登录档,
可以使用∶『/etc/init.d/syslogd restart』,那个 syslogd 档案就是 script 啦!
另外,我曾经在某一代的 FC 上面发现,启动 MySQL 这个资料库服务时,确实是可以启动的,
但是萤幕上却老是出现『failure』,后来才发现,原来是启动 MySQL 那个 script
会主动的以『空的密码』去尝试登入 MySQL ,但我修改过 MySQL 的密码棉~当然就登入失败~
后来改了改 script ,就略去这个问题啦!如此说来, script 确实是需要学习的啊!<br><br>
</div>
<li><span class=text_import1>简单入侵侦测功能</span>∶</li>
<div class=block2>
当我们的系统有异状时,大多会将这些异状记录在系统记录器,也就是我们常提到的『系统登录档』,
那么我们可以在固定的几分钟内主动的去分析系统登录档,若察觉有问题,就立刻通报管理员,
或者是立刻加强防火墙的设定规则,如此一来,您的主机可就能够达到『自我保护』的聪明学习功能啦~
举例来说,我们可以通过 shell script 去分析『当该封包尝试几次还是连线失败之后,就予以抵挡住该
IP』之类的举动,例如鸟哥写过一个关于抵挡砍站软体的 shell script ,
就是用这个想法去达成的呢!<br><br>
</div>
<li><span class=text_import1>连续指令单一化</span>∶</li>
<div class=block2>
其实,对于新手而言, script 最简单的功能就是∶『<span class=text_import2>汇整一些在
command line 下达的连续指令,将他写入 scripts 当中,而由直接执行 scripts
来启动一连串的 command line 指令输出入!</span>』例如∶ 防火墙连续规则
( iptables ),开机载入程序的项目 ( 就是在 /etc/rc.d/rc.local 里头的资料
) ,等等都是相似的功能啦! 其实,说穿了,如果不考虑 program 的部分,那么
scripts 也可以想成,仅是帮我们把一大串的指令汇整在一个档案里面,
而直接执行该档案就可以执行那一串又臭又长的指令段!就是这么简单啦!<br><br>
</div>
<li><span class=text_import1>简易的资料处理</span>∶</li>
<div class=block2>
由前一章 <a href="0330regularex.php">正规表示法</a> 的 awk 程式说明中,
您可以发现, awk 可以用来处理简单的数据资料呢!例如薪资单的处理啊等等的。
shell script 的功能更强大,例如鸟哥曾经用 shell script 直接处理数据资料的比对啊,
文字资料的处理啊等等的,撰写方便,速度又快(因为在 Linux 效能较佳),
真的是很不错用的啦!<br><br>
</div>
<li><span class=text_import1>跨平台支援与学习历程较短</span>∶</li>
<div class=block2>
几乎所有的 Unix Like 上面都可以跑 shell script ,连 MS Windows 系列也有相关的模拟器可以用,
此外, shell script 的语法是相当亲和的,看都看的懂得文字,而不是机器码,
很容易学习~这些都是您可以加以考量的学习点啊!<br><br>
</div>
上面这些都是您考虑学习 shell script 的特点~此外, shell script 还可以简单的以 vi
来直接编写,实在是很方便的好东西!所以,还是建议您学习一下啦。<br><br>
不过,虽然 shell script 号称是程式 (program) ,但实际上, shell script
处理资料的速度上是不太够的。因为 shell script 用的是外部的指令与 bash shell
的一些预设工具,所以,他常常会去呼叫外部的函式库,因此,运算速度上面当然比不上传统的程式语言。
所以棉, shell script 用在系统管理上面是很好的一项工具,但是用在处理大量数值运算上,
就不够好了~而且还很麻烦,因为∶<span class=text_import2>Shell scripts 的速度较慢,
且使用的 CPU 资源较多,造成主机资源的分配不良。</span>还好,
我们确实很少看到利用 shell script 在进行大量数据运算的,所以,不必担心的啦!<br><br>
</div>
<hr><a name="script_1st"></a><img src="../images/penguin-s.gif" alt="小标题的图示" height="23" width="16" align="middle" /><span class=text_h2>第一支 script 的撰写与执行</span><br>
<div class=block2>
如同前面讲到的, shell script 其实就是纯文字档 (ASCII) ,我们可以编辑这个档案,
然后让这个档案来帮我们一次执行多个指令,或者是利用一些运算与逻辑判断来帮我们达成某些功能。
所以啦,要编辑这个档案的内容时,当然就需要具备有 bash shell 指令下达的相关认识。
我们说过,要下达指令需要注意的事项在 <a href="0320bash.php#bash_command">bash 章节内</a>已经提过,
在 shell script 的撰写同样需要用到这些注意事项的∶<ol><span class=text_import2>
<li>如同前面 bash command 提到的,指令与参数间的多个空白会被忽略掉;
<li>而空白行也将被忽略掉!,并且 [tab] 也是不会被理会的!
<li>如果读取到一个 Enter 符号 ( CR )),就尝试开始执行该行命令;
<li>至于如果一行的内容太多,则可以使用 \[Enter] 来延伸至下一行;
<li>此外,使用最多的 # 可做为注解!任何<B>加在 # 后面的字</B>,将全部被视为注解文字而被忽略!
</OL></span>
如此一来,我们在 script 内所撰写的程式,就会被一行一行的执行。好了,那么这个程式假设档名是
shell.sh 好了,如何执行这个档案?很简单,可以有底下几个方法∶<ul><span class=text_import2>
<li>将 shell.sh 加上可读与执行 (rx) 的权限,然后就能够以 ./shell.sh 来执行了;
<li>直接以 sh shell.sh 的方式来直接执行即可。</ul></span>
反正重点就是要让那个 shell.sh 内的指令可以被执行的意思啦!咦!那我为何需要使用 ./shell.sh 来下达指令?
还记得我们在 bash 里面一直强调的,指令是否能够被执行与 PATH 这个环境变数有关,
所以,要执行『目前这个目录下的某个档案』就需要加上 ./ 这个目录啦!另外,其实您也可以将
shell.sh 放在您家目录下的 ~/bin 这个目录中,然后利用 PATH="$PATH":~/bin 的设定,
嘿嘿,就能够直接执行您的 script 棉~ ^_^<br><br>
那,为何 sh shell.sh 也可以执行呢?这是因为 /bin/sh 其实就是 /bin/bash ,
使用 sh shell.sh 亦即告诉系统,我想要直接以 bash 的功能来执行 shell.sh 这个档案内的相关指令的意思。
而我们也可以利用 sh 的参数,如 -n 及 -x 来检查与追踪 shell.sh 的语法是否正确呢! ^_^<br><br>
<hr><li><span class=text_import1>撰写第一支 script</span></li>
<div class=block2>
不论是那个门派,要学武功要从扫地做起,那么要学程式呢?呵呵,肯定是由『秀出 Hello World!』
这个字眼开始的!OK!那么鸟哥就先写一支 script 给大家瞧一瞧∶<br>
<table class="term"><tr><td class="term"><pre>
[root@linux ~]# <span class=term_command>mkdir scripts; cd scripts</span>
[root@linux scripts]# <span class=term_command>vi sh01.sh</span>
<span class=term_write>#!/bin/bash
# Program:
# This program is used to show "Hello World !" in 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</span>
</pre></td></tr></table>
在我们这个章节当中,请将所有的撰写的 script 放置到您家目录的 ~/scripts 这个目录内,
比较好管理啦!上面的写法当中,我主要将整个程式的撰写分成数段,大致是这样∶<ol>
<li><span class=text_import2>第一行 #!/bin/bash 在宣告这个 script 使用的 shell 名称∶</span><br>
因为我们使用的是 bash ,所以,必须要以『 <b>#!/bin/bash</b> 』来宣告这个档案内的语法使用
bash 的语法!那么当这个程式被执行时,他就能够载入 bash 的相关环境设定档,
并且执行 bash 来使我们底下的指令能够执行!这很重要的!(在很多状况中,如果没有设定好这一行,
那么该程式很可能会无法执行,因为系统可能无法判断该程式需要使用什么 shell 来执行啊!)<br><br>
<li><span class=text_import2>程式内容的宣告∶<br></span>
整个 script 当中,除了第一行的 #! 是用来宣告 shell 的之外,其他的 # 都是『注解』用途!
所以上面的程式当中,第二行以下就是用来说明整个程式的状态。一般来说,
建议您一定要养成说明该 script 的∶1. 内容与功能; 2. 版本资讯; 3. 作者与联络方式;
4. 建档日期;5. 历史纪录 等等。这将有助于未来程式的改写与 debug 呢!<br><br>
<li><span class=text_import2>主要环境变数的宣告∶</span><br>
建议务必要将一些重要的环境变数设定好,鸟哥个人认为, PATH 是当中最重要的!
如此一来,则可让我们这支程式在进行时,可以直接下达指令,
而不必写绝对路径呢!比较好啦!<br><br>
<li><span class=text_import2>主要程式部分</span><br>
就将主要的程式写好即可!在这个例子当中,就是 echo 那一行啦!<br><br>
<li><span class=text_import2>执行成果告知</span><br>
是否记得我们在 bash 里面要讨论一个指令的执行成功与否,可以使用 $? 这个变数来观察~
那么我们也可以利用 exit 这个指令来让程式中断,并且回传一个数值给系统。
在我们这个例子当中,我使用 exit 0 ,这代表离开 script ,并且回传一个 0 给系统,
所以我执行完这个 script 后,若接著下达 echo $? 则可得到 0 的值喔!
更聪明的读者应该也知道了,呵呵!利用这个 exit n 的功能,我们还可以自订错误讯息,
让这支程式变得更加的 smart 呢!
</ol>
接下来执行看看结果是怎样吧?<br>
<table class="term"><tr><td class="term"><pre>
[root@linux scripts]# <span class=term_command>sh sh01.sh</span>
Hello World !
</pre></td></tr></table>
您会看到萤幕是这样,而且应该还会听到『咚』的一声,为什么呢?还记得前一章提到的
<a href="0330regularex.php#printf">printf</a> 吧?用 echo 接著那些特殊的按键也可以发生同样的事情~
不过, echo 必须要加上 -e 的参数才行!
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -