爱问 爱问共享资料 爱问分类
首页 > > > 高级Bash脚本编程指南.pdf

高级Bash脚本编程指南.pdf

高级Bash脚本编程指南.pdf

上传者: 筱筱
7次下载 0人收藏 暂无简介 简介 2011-06-27 举报

简介:当前资料暂无简介!

译者序毫无疑问,UNIX/Linux最重要的软件之一就是shell,目前最流行的shell被称为Bash(BourneAgainShell),几乎所有的Linux和绝大部分的UNIX都可以使用Bash。作为系统与用户之间的交互接口,shell几乎是你在UNIX工作平台上最亲密的朋友,因此,学好shell,是学习Linux/UNIX的的开始,并且它会始终伴随你的工作学习。shell是如此地重要,但令人惊奇的是,介绍shell的书没有真正令人满意的。所幸的是,我看到了这本被人称为abs的书,这本书介绍了bash大量的细节和广阔的范围,我遇到的绝大部分的技术问题--无论是我忘记的或是以前没有发现的--都可以在这本书里找到答案。这本使用大量的例子详细地介绍了Bash的语法,各种技巧,调试等等的技术,以循序渐进的学习方式,让你了解Bash的所有特性,在书中还有许多练习可以引导你思考,以得到更深入的知识。无论你是新手还是老手,或是使用其他语言的程序员,我能肯定你能在此书用受益。而本书除了介绍BASH的知识之外,也有许多有用的关于Linux/UNIX的知识和其他shell的介绍。在看到本书的英文版后,我决定把它翻译出来,在Linuxsir论坛上结识了译者之一杨春敏共同翻译这本书,600多页的书是本大部头的书,我们花了6个月的业余时间才翻译完了。关于版权的问题,英文版的作者MendelCooper对英文版的版权做了详细的约定,请参考:AppendixQ.Copyright。中文版版权由译者杨春敏和黄毅共同所有,在遵守英文版版权相应条款的条件下,欢迎在保留本书译者名字和版权说明以非盈利的方式自由发布此中文版,以盈利目的的所有行为必须联系英文作者和两位中文译者以获得许可。本书得以成稿,我(黄毅)要多谢我的女朋友,本该给予她的时间我用来了翻译,多谢你的理解,你是一个很棒的女朋友!译者杨春敏黄毅2006.5.15AdvancedBash-ScriptingGuide<<高级Bash脚本编程指南>>一本深入学习shell脚本艺术的书籍Version3.7.22005/11/16作者:MendelCoopermail:thegrendel@theriver.com这本书假定你没有任何脚本或一般程序的编程知识,但是如果你有相关的知识,那么你将很容易达到中高级的水平...allthewhilesneakinginlittlesnippetsofUNIX?wisdomandlore(这句不知道怎么译).你可以把本书作为教材,自学手册,或者你获得shell脚本技术的文档.书中的练习和例子脚本中的注释将会与读者有更好的互动,但是最关键的前提是:想真正学习脚本编程的唯一途径就是编写脚本.这本书也可作为教材来讲解一般的编程概念.下载本书最新版本,http://personal.riverusers.com/~thegrendel/abs-guide-3.7.tar.bz2,这是一个以tar和bzip2进行打包的,并且是以HTML来发行的.当然,你也可以获得本书的pdf版本在http://www.tldp.org/LDP/abs/abs-guide.pdf.可以在http://personal.riverusers.com/~thegrendel/Change.log中查看修订历史.译者:杨春敏,黄毅mail:chunmin.yang@gmail.com一直想好好学习一下bash,可惜网上的资料都杂乱不堪,我还是喜欢通过一本书系统的学习.这本书来得正是时候.本书的作者真是非常的严谨,从例子里的改进人名单就能看出来.可惜我水平真的是非常有限,好多地方估计译得都有问题.希望阅读的朋友们多多提些修改建议.我会尽我的最大努力去修正它.目录++++第一部分.热身1.为什么使用shell编程2.带着一个Sha-Bang出发(Sha-Bang指的是#!)2.1.调用一个脚本2.2.初步的练习第二部分.基本3.特殊字符4.变量和参数的介绍4.1.变量替换4.2.变量赋值4.3.Bash变量是不分类型的4.4.特殊的变量类型5.引用(翻译的可能有问题,特指引号)5.1.引用变量5.2.转义(\)6.退出和退出状态7.Tests7.1.Test结构7.2.文件测试操作7.3.其他比较操作7.4.嵌套的if/then条件test7.5.检查你的test知识8.操作符和相关的主题8.1.操作符8.2.数字常量第三部分.超越基本9.变量重游9.1.内部变量9.2.操作字符串9.3.参数替换9.4.指定类型的变量:declare或者typeset9.5.变量的间接引用9.6.$RANDOM:产生随机整数9.7.双圆括号结构10.循环和分支10.1.循环10.2.嵌套循环10.3.循环控制10.4.测试与分支(case和select结构)11.内部命令与内建11.1.作业控制命令12.外部过滤器,程序和命令12.1.基本命令12.2.复杂命令12.3.时间/日期命令12.4.文本处理命令12.5.文件与归档命令12.6.通讯命令12.7.终端控制命令12.8.数学计算命令12.9.混杂命令13.系统与管理命令13.1.分析一个系统脚本14.命令替换15.算术扩展16.I/O重定向16.1.使用exec16.2.代码块的重定向16.3.应用17.HereDocuments17.1.HereStrings18.休息时间Part4.高级19.正则表达式19.1.一个简要的正则表达式介绍19.2.通配20.子shell(Subshells)21.受限shell(RestrictedShells)22.进程替换23.函数23.1.复杂函数和函数复杂性23.2.局部变量23.3.不使用局部变量的递归24.别名(Aliases)25.列表结构26.数组27./dev和/proc27.1./dev27.2./proc28.关于Zeros和Nulls29.调试30.选项31.Gotchas32.脚本编程风格32.1.非官方的Shell脚本风格33.杂项33.1.交互式和非交互式的shells和脚本33.2.Shell包装33.3.测试和比较:另一种方法33.4.递归33.5.彩色脚本33.6.优化33.7.各种小技巧33.8.安全话题33.8.1.被感染的脚本33.8.2.隐藏Shell脚本源码33.9.移植话题33.10.在Windows下进行Shell编程34.Bash,版本2和334.1.Bash,版本234.2.Bash,版本335.后记35.1.作者后记35.2.关于作者35.3.哪里可以取得帮助?35.4.制作这本书的工具35.4.1.硬件35.4.2.软件和排版软件35.5.CreditsBibliographyA.ContributedScriptsB.ReferenceCardsC.ASedandAwkMicro-PrimerC.1.SedC.2.AwkD.ExitCodesWithSpecialMeaningsE.ADetailedIntroductiontoI/OandI/ORedirectionF.StandardCommand-LineOptionsG.ImportantFilesH.ImportantSystemDirectoriesI.LocalizationJ.HistoryCommandsK.ASample.bashrcFileL.ConvertingDOSBatchFilestoShellScriptsM.ExercisesM.1.AnalyzingScriptsM.2.WritingScriptsN.RevisionHistoryO.MirrorSitesP.ToDoListQ.Copyright表格清单:11-1.作业标识符30-1.Bash选项33-1.转义序列中数值和彩色的对应B-1.SpecialShellVariablesB-2.TESTOperators:BinaryComparisonB-3.TESTOperators:FilesB-4.ParameterSubstitutionandExpansionB-5.StringOperationsB-6.MiscellaneousConstructsC-1.BasicsedoperatorsC-2.ExamplesofsedoperatorsD-1."Reserved"ExitCodesL-1.Batchfilekeywords/variables/operators,andtheirshellequivalentsL-2.DOScommandsandtheirUNIXequivalentsN-1.RevisionHistory例子清单:2-1.清除:清除/var/log下的log文件2-2.清除:一个改良的清除脚本2-3.cleanup:一个增强的和广义的删除logfile的脚本3-1.代码块和I/O重定向3-2.将一个代码块的结果保存到文件3-3.在后台运行一个循环3-4.备份最后一天所有修改的文件.4-1.变量赋值和替换4-2.一般的变量赋值4-3.变量赋值,一般的和比较特殊的4-4.整型还是string?4-5.位置参数4-6.wh,whois节点名字查询4-7.使用shift5-1.echo一些诡异的变量5-2.转义符6-1.exit/exit状态6-2.否定一个条件使用!7-1.什么情况下为真?7-2.几个等效命令test,/usr/bin/test,[],和/usr/bin/[7-3.算数测试使用(())7-4.test死的链接文件7-5.数字和字符串比较7-6.测试字符串是否为null7-7.zmore8-1.最大公约数8-2.使用算术操作符8-3.使用&&和||进行混合状态的test8-4.数字常量的处理9-1.$IFS和空白9-2.时间输入9-3.再来一个时间输入9-4.Timedread9-5.我是root?9-6.arglist:通过$*和$@列出所有的参数9-7.不一致的$*和$@行为9-8.当$IFS为空时的$*和$@9-9.下划线变量9-10.在一个文本文件的段间插入空行9-11.利用修改文件名,来转换图片格式9-12.模仿getopt命令9-13.提取字符串的一种可选的方法9-14.使用参数替换和errormessages9-15.参数替换和"usage"messages9-16.变量长度9-17.参数替换中的模式匹配9-18.重命名文件扩展名9-19.使用模式匹配来分析比较特殊的字符串9-20.对字符串的前缀或后缀使用匹配模式9-21.使用declare来指定变量的类型9-22.间接引用9-23.传递一个间接引用给awk9-24.产生随机数9-25.从一副扑克牌中取出一张随机的牌9-26.两个指定值之间的随机数9-27.使用随机数来摇一个骰子9-28.重新分配随机数种子9-29.使用awk产生伪随机数9-30.C风格的变量处理10-1.循环的一个简单例子10-2.每个[list]元素带两个参数的for循环10-3.文件信息:对包含在变量中的文件列表进行操作10-4.在for循环中操作文件10-5.在for循环中省略[list]10-6.使用命令替换来产生for循环的[list]10-7.对于二进制文件的一个grep替换10-8.列出系统上的所有用户10-9.在目录的所有文件中查找源字串10-10.列出目录中所有的符号连接文件10-11.将目录中的符号连接文件名保存到一个文件中10-12.一个C风格的for循环10-13.在batchmode中使用efax10-14.简单的while循环10-15.另一个while循环10-16.多条件的while循环10-17.C风格的while循环10-18.until循环10-19.嵌套循环10-20.break和continue命令在循环中的效果10-21.多层循环的退出10-22.多层循环的continue10-23.在实际的任务中使用"continueN"10-24.使用case10-25.使用case来创建菜单10-26.使用命令替换来产生case变量10-27.简单字符串匹配10-28.检查是否是字母输入10-29.用select来创建菜单10-30.用函数中select结构来创建菜单11-1.一个fork出多个自己实例的脚本11-2.printf11-3.使用read,变量分配11-4.当使用一个不带变量参数的read命令时,将会发生什么?11-5.read命令的多行输入11-6.检测方向键11-7.通过文件重定向来使用read11-8.管道输出到read中的问题11-9.修改当前的工作目录11-10.用"let"命令来作算术操作.11-11.显示eval命令的效果11-12.强制登出(log-off)11-13.另一个"rot13"的版本11-14.在Perl脚本中使用eval命令来强制变量替换11-15.使用set来改变脚本的位置参数11-16.重新分配位置参数11-17.Unset一个变量11-18.使用export命令传递一个变量到一个内嵌awk的脚本中11-19.使用getopts命令来读取传递给脚本的选项/参数.11-20."Including"一个数据文件11-21.一个没什么用的,source自身的脚本11-22.exec的效果11-23.一个exec自身的脚本11-24.在继续处理之前,等待一个进程的结束11-25.一个结束自身的脚本.12-1.使用ls命令来创建一个烧录CDR的内容列表12-2.HelloorGood-bye12-3.删除当前目录下文件名中包含一些特殊字符(包括空白)的文件..12-4.通过文件的inode号来删除文件12-5.Logfile:使用xargs来监控系统log12-6.把当前目录下的文件拷贝到另一个文件中12-7.通过名字Kill进程12-8.使用xargs分析单词出现的频率12-9.使用expr12-10.使用date命令12-11.分析单词出现的频率12-12.那个文件是脚本?12-13.产生10进制随机数12-14.使用tail命令来监控系统log12-15.在一个脚本中模仿"grep"的行为12-16.在1913年的韦氏词典中查找定义12-17.检查列表中单词的正确性12-18.转换大写:把一个文件的内容全部转换为大写.12-19.转换小写:将当前目录下的所有文全部转换为小写.12-20.Du:DOS到UNIX文本文件的转换.12-21.rot13:rot13,弱智加密.12-22.Generating"Crypto-Quote"Puzzles12-23.格式化文件列表.12-24.使用column来格式化目录列表12-25.nl:一个自己计算行号的脚本.12-26.manview:查看格式化的man页12-27.使用cpio来拷贝一个目录树12-28.解包一个rpm归档文件12-29.从C文件中去掉注释12-30.Exploring/usr/X11R6/bin12-31.一个"改进过"的strings命令12-32.在一个脚本中使用cmp来比较2个文件.12-33.basename和dirname12-34.检查文件完整性12-35.Uudecod编码后的文件12-36.查找滥用的连接来报告垃圾邮件发送者12-37.分析一个垃圾邮件域12-38.获得一份股票报价12-39.更新FedoraCore412-40.使用ssh12-41.一个可以mail自己的脚本12-42.按月偿还贷款12-43.数制转换12-44.使用"heredocument"来调用bc12-45.计算圆周率12-46.将10进制数字转换为16进制数字12-47.因子分解12-48.计算直角三角形的斜边12-49.使用seq来产生循环参数12-50.字母统计12-51.使用getopt来分析命令行选项12-52.一个拷贝自身的脚本12-53.练习dd12-54.记录按键12-55.安全的删除一个文件12-56.文件名产生器12-57.将米转换为英里12-58.使用m413-1.设置一个新密码13-2.设置一个擦除字符13-3.关掉终端对于密码的echo13-4.按键检测13-5.Checkingaremoteserverforidentd<rojybug>13-6.pidof帮助杀掉一个进程13-7.检查一个CD镜像13-8.在一个文件中创建文件系统13-9.添加一个新的硬盘驱动器13-10.使用umask来将输出文件隐藏起来13-11.killall,来自于/etc/rc.d/init.d14-1.愚蠢的脚本策略14-2.从循环的输出中产生一个变量14-3.找anagram(回文构词法,可以将一个有意义的单词,变换为1个或多个有意义的单词,但是还是原来的子母集合)16-1.使用exec重定向标准输入16-2.使用exec来重定向stdout16-3.使用exec在同一脚本中重定向stdin和stdout16-4.避免子shell16-5.while循环的重定向16-6.另一种while循环的重定向16-7.until循环重定向16-8.for循环重定向16-9.for循环重定向loop(将标准输入和标准输出都重定向了)16-10.重定向if/then测试结构16-11.用于上面例子的"names.data"数据文件16-12.记录日志事件17-1.广播:发送消息给每个登录上的用户17-2.仿造文件:创建一个两行的仿造文件17-3.使用cat的多行消息17-4.带有抑制tab功能的多行消息17-5.使用参数替换的heredocument17-6.上传一个文件对到"Sunsite"的incoming目录17-7.关闭参数替换17-8.一个产生另外一个脚本的脚本17-9.Heredocuments与函数17-10."匿名"hereDocument17-11.注释掉一段代码块17-12.一个自文档化(self-documenting)的脚本17-13.在一个文件的开头添加文本20-1.子shell中的变量作用域20-2.列出用户的配置文件20-3.在子shell里进行串行处理21-1.在受限的情况下运行脚本23-1.简单函数23-2.带着参数的函数23-3.函数和被传给脚本的命令行参数23-4.传递间接引用给函数23-5.解除传递给函数的参数引用23-6.再次尝试解除传递给函数的参数引用23-7.两个数中的最大者23-8.把数字转化成罗马数字23-9.测试函数最大的返回值23-10.比较两个大整数23-11.用户名的真实名23-12.局部变量的可见范围23-13.用局部变量来递归23-14.汉诺塔24-1.脚本中的别名24-2.unalias:设置和删除别名25-1.使用"与列表(andlist)"来测试命令行参数25-2.用"与列表"的另一个命令行参数测试25-3."或列表"和"与列表"的结合使用26-1.简单的数组用法26-2.格式化一首诗26-3.多种数组操作26-4.用于数组的字符串操作符26-5.将脚本的内容传给数组26-6.一些数组专用的工具26-7.关于空数组和空数组元素26-8.初始化数组26-9.复制和连接数组26-10.关于连接数组的更多信息26-11.一位老朋友:冒泡排序26-12.内嵌数组和间接引用26-13.复杂数组应用:埃拉托色尼素数筛子26-14.模拟下推的堆栈26-15.复杂的数组应用:列出一种怪异的数学序列26-16.模拟二维数组,并使它倾斜27-1.利用/dev/tcp来检修故障27-2.搜索与一个PID相关的进程27-3.网络连接状态28-1.隐藏cookie而不再使用28-2.用/dev/zero创建一个交换临时文件28-3.创建ramdisk29-1.一个错误的脚本29-2.丢失关键字(keyword)29-3.另一个错误脚本29-4.用"assert"测试条件29-5.捕捉exit29-6.在Control-C后清除垃圾29-7.跟踪变量29-8.运行多进程(在多处理器的机器里)31-1.数字和字符串比较是不相等同的31-2.子SHELL缺陷31-3.把echo的输出用管道输送给read命令33-1.shell包装33-2.稍微复杂一些的shell包装33-3.写到日志文件的shell包装33-4.包装awk的脚本33-5.另一个包装awk的脚本33-6.把Perl嵌入Bash脚本33-7.Bash和Perl脚本联合使用33-8.递归调用自己本身的(无用)脚本33-9.递归调用自己本身的(有用)脚本33-10.另一个递归调用自己本身的(有用)脚本33-11.一个"彩色的"地址资料库33-12.画盒子33-13.显示彩色文本33-14."赛马"游戏33-15.返回值技巧33-16.整型还是string?33-17.传递和返回数组33-18.anagrams游戏33-19.在shell脚本中调用的窗口部件34-1.字符串扩展34-2.间接变量引用-新方法34-3.使用间接变量引用的简单数据库应用34-4.用数组和其他的小技巧来处理四人随机打牌A-1.mailformat:Formattingane-mailmessageA-2.rn:Asimple-mindedfilerenameutilityA-3.blank-rename:renamesfilenamescontainingblanksA-4.encryptedpw:Uploadingtoanftpsite,usingalocallyencryptedpasswordA-5.copy-cd:CopyingadataCDA-6.CollatzseriesA-7.days-between:CalculatenumberofdaysbetweentwodatesA-8.Makea"dictionary"A-9.SoundexconversionA-10."GameofLife"A-11.Datafilefor"GameofLife"A-12.behead:RemovingmailandnewsmessageheadersA-13.ftpget:DownloadingfilesviaftpA-14.password:Generatingrandom8-characterpasswordsA-15.fifo:Makingdailybackups,usingnamedpipesA-16.GeneratingprimenumbersusingthemodulooperatorA-17.tree:DisplayingadirectorytreeA-18.stringfunctions:C-likestringfunctionsA-19.DirectoryinformationA-20.Object-orienteddatabaseA-21.LibraryofhashfunctionsA-22.ColorizingtextusinghashfunctionsA-23.MountingUSBkeychainstoragedevicesA-24.PreservingweblogsA-25.ProtectingliteralstringsA-26.UnprotectingliteralstringsA-27.SpammerIdentificationA-28.SpammerHuntA-29.MakingwgeteasiertouseA-30.A"podcasting"scriptA-31.BasicsReviewedA-32.AnexpandedcdcommandC-1.CountingLetterOccurrencesK-1.Sample.bashrcfileL-1.VIEWDATA.BAT:DOSBatchFileL-2.viewdata.sh:ShellScriptConversionofVIEWDATA.BATP-1.Printtheserverenvironment第一部分热身++++++++++++++++shell是一个命令解释器.是介于操作系统kernel与用户之间的一个绝缘层.准确地说,它也是一一种强力的计算机语言.一个shell程序,被称为一个脚本,是一种很容易使用的工具,它可以通过将系统调用,公共程序,工具,和编译过的二进制程序粘合在一起来建立应用.事实上,所有的UNIX命令和工具再加上公共程序,对于shell脚本来说,都是可调用的.如果这些你还觉得不够,那么shell内建命令,比如test与循环结构,也会给脚本添加强力的支持和增加灵活性.Shell脚本对于管理系统任务和其它的重复工作的例程来说,表现的非常好,根本不需要那些华而不实的成熟紧凑的程序语言.第1章为什么使用shell编程===========================没有程序语言是完美的.甚至没有一个唯一最好的语言,只有对于特定目的,比较适合和不适合的程序语言.HerbertMayer对于任何想适当精通一些系统管理知识的人来说,掌握shell脚本知识都是最基本的,即使这些人可能并不打算真正的编写一些脚本.想一下Linux机器的启动过程,在这个过程中,必将运行/etc/rc.d目录下的脚本来存储系统配置和建立服务.详细的理解这些启动脚本对于分析系统的行为是非常重要的,并且有时候可能必须修改它.学习如何编写shell脚本并不是一件很困难的事,因为脚本可以分为很小的块,并且相对于shell特性的操作和选项[1]部分,只需要学习很小的一部分就可以了.语法是简单并且直观的,编写脚本很像是在命令行上把一些相关命令和工具连接起来,并且只有很少的一部分规则需要学习.绝大部分脚本第一次就可以正常的工作,而且即使调试一个长一些的脚本也是很直观的.一个shell脚本是一个类似于小吃店的(quickanddirty)方法,在你使用原型设计一个复杂的应用的时候.在工程开发的第一阶段,即使从功能中取得很有限的一个子集放到shell脚本中来完成往往都是非常有用的.使用这种方法,程序的结果可以被测试和尝试运行,并且在处理使用诸如C/C++,Java或者Perl语言编写的最终代码前,主要的缺陷和陷阱往往就被发现了.Shell脚本遵循典型的UNIX哲学,就是把大的复杂的工程分成小规模的子任务,并且把这些部件和工具组合起来.许多人认为这种办法更好一些,至少这种办法比使用那种高\大\全的语言更美,更愉悦,更适合解决问题.比如Perl就是这种能干任何事能适合任何人的语言,但是代价就是你需要强迫自己使用这种语言来思考解决问题的办法.什么时候不使用Shell脚本资源密集型的任务,尤其在需要考虑效率时(比如,排序,hash等等)需要处理大任务的数学操作,尤其是浮点运算,精确运算,或者复杂的算术运算(这种情况一般使用C++或FORTRAN来处理)有跨平台移植需求(一般使用C或Java)复杂的应用,在必须使用结构化编程的时候(需要变量的类型检查,函数原型,等等)对于影响系统全局性的关键任务应用。对于安全有很高要求的任务,比如你需要一个健壮的系统来防止入侵,破解,恶意破坏等等.项目由连串的依赖的各个部分组成。需要大规模的文件操作需要多维数组的支持需要数据结构的支持,比如链表或数等数据结构需要产生或操作图形化界面GUI需要直接操作系统硬件需要I/O或socket接口需要使用库或者遗留下来的老代码的接口私人的,闭源的应用(shell脚本把代码就放在文本文件中,全世界都能看到)如果你的应用符合上边的任意一条,那么就考虑一下更强大的语言吧--或许是Perl,Tcl,Python,Ruby--或者是更高层次的编译语言比如C/C++,或者是Java.即使如此,你会发现,使用shell来原型开发你的应用,在开发步骤中也是非常有用的.我们将开始使用Bash,Bash是"Bourne-Againshell"首字母的缩写,也是StephenBourne的经典的Bourneshell的一个双关语,(译者:说实话,我一直搞不清这个双关语是什么意思,为什么叫"Bourn-Againshell",这其中应该有个什么典故吧,哪位好心,告诉我一下^^).Bash已经成为了所有UNIX中shell脚本的事实上的标准了.同时这本书也覆盖了绝大部分的其他一些shell的原则,比如KornShell,Bash从ksh中继承了一部分特性,[2]CShell和它的变种.(注意:CShell编程是不被推荐的,因为一些特定的内在问题,TomChristiansen在1993年10月指出了这个问题请在http://www.etext.org/Quartz/computer/unix/csh.harmful.gz中查看具体内容.)接下来是脚本的一些说明.在展示shell不同的特征之前,它可以减轻一些阅读书中例子的负担.本书中的例子脚本,都在尽可能的范围内进行了测试,并且其中的一些将使用在真实的生活中.读者可以运行这些例子脚本(使用scriptname.sh或者scriptname.bash的形式),[3]并给这些脚本执行权限(chmodu+rxscriptname),然后执行它们,看看发生了什么.如果存档的脚本不可用,那么就从本书的HTML,pdf或者text的发行版本中把它们拷贝粘贴出来.考虑到这些脚本中的内容在我们还没解释它之前就被列在这里,可能会影响读者的理解,这就需要读者暂时忽略这些内容.除非特别注明,本书作者编写了本书中的绝大部分例子脚本.注意事项:[1]这些在builtins章节被引用,这些是shell的内部特征.[2]ksh88的许多特性,甚至是一些ksh93的特性都被合并到Bash中了.[3]根据惯例,用户编写的Bourneshell脚本应该在脚本的名字后边加上.sh扩展名.一些系统脚本,比如那些在/etc/rc.d中的脚本,则不遵循这种命名习惯.第2章带着一个Sha-Bang出发(Sha-Bang指的是#!)==============================================在一个最简单的例子中,一个shell脚本其实就是将一堆系统命令列在一个文件中.它的最基本的用处就是,在你每次输入这些特定顺序的命令时可以少敲一些字.Example2-1清除:清除/var/log下的log文件################################StartScript#######################################1#Cleanup2#当然要使用root身份来运行这个脚本34cd/var/log5cat/dev/null>messages6cat/dev/null>wtmp7echo"Logscleanedup."################################EndScript#########################################这根本就没什么稀奇的,只不过是命令的堆积,来让从console或者xterm中一个一个的输入命令更方便一些.好处就是把所有命令都放在一个脚本中,不用每次都敲它们.这样的话,对于特定的应用来说,这个脚本就很容易被修改或定制.Example2-2清除:一个改良的清除脚本################################StartScript#######################################1#!/bin/bash2#一个Bash脚本的正确的开头部分.34#Cleanup,版本256#当然要使用root身份来运行.7#在此处插入代码,来打印错误消息,并且在不是root身份的时候退出.89LOG_DIR=/var/log10#如果使用变量,当然比把代码写死的好.11cd$LOG_DIR1213cat/dev/null>messages14cat/dev/null>wtmp151617echo"Logscleanedup."1819exit#这个命令是一种正确并且合适的退出脚本的方法.################################EndScript#########################################现在,让我们看一下一个真正意义的脚本.而且我们可以走得更远...Example2-3.cleanup:一个增强的和广义的删除logfile的脚本################################StartScript#######################################1#!/bin/bash2#清除,版本334#Warning:5#-------6#这个脚本有好多特征,这些特征是在后边章节进行解释的,大概是进行到本书的一半的7#时候,8#你就会觉得它没有什么神秘的了.9#10111213LOG_DIR=/var/log14ROOT_UID=0#$UID为0的时候,用户才具有根用户的权限15LINES=50#默认的保存行数16E_XCD=66#不能修改目录?17E_NOTROOT=67#非根用户将以error退出181920#当然要使用根用户来运行21if["$UID"-ne"$ROOT_UID"]22then23echo"Mustberoottorunthisscript."24exit$E_NOTROOT25fi2627if[-n"$1"]28#测试是否有命令行参数(非空).29then30lines=$131else32lines=$LINES#默认,如果不在命令行中指定33fi343536#StephaneChazelas建议使用下边37#+的更好方法来检测命令行参数.38#+但对于这章来说还是有点超前.39#40#E_WRONGARGS=65#非数值参数(错误的参数格式)41#42#case"$1"in43#"")lines=50;;44#*[!0-9]*)echo"Usage:`basename$0`file-to-cleanup";exit$E_WRONGARGS;;45#*)lines=$1;;46#esac47#48#*直到"Loops"的章节才会对上边的内容进行详细的描述.495051cd$LOG_DIR5253if[`pwd`!="$LOG_DIR"]#或者if["$PWD"!="$LOG_DIR"]54#不在/var/log中?55then56echo"Can'tchangeto$LOG_DIR."57exit$E_XCD58fi#在处理logfile之前,再确认一遍当前目录是否正确.5960#更有效率的做法是61#62#cd/var/log||{63#echo"Cannotchangetonecessarydirectory.">&264#exit$E_XCD;65#}6667686970tail-$linesmessages>mesg.temp#保存logfile消息的最后部分.71mvmesg.tempmessages#变为新的log目录.727374#cat/dev/null>messages75#*不再需要了,使用上边的方法更安全.7677cat/dev/null>wtmp#':>wtmp'和'>wtmp'具有相同的作用78echo"Logscleanedup."7980exit081#退出之前返回0,返回0表示成功.82#################################EndScript#########################################因为你可能希望将系统log全部消灭,这个版本留下了log消息最后的部分.你将不断地找到新的方法来完善这个脚本,并提高效率.要注意,在每个脚本的开头都使用"#!",这意味着告诉你的系统这个文件的执行需要指定一个解释器.#!实际上是一个2字节[1]的魔法数字,这是指定一个文件类型的特殊标记,换句话说,在这种情况下,指的就是一个可执行的脚本(键入manmagic来获得关于这个迷人话题的更多详细信息).在#!之后接着是一个路径名.这个路径名指定了一个解释脚本中命令的程序,这个程序可以是shell,程序语言或者是任意一个通用程序.这个指定的程序从头开始解释并且执行脚本中的命令(从#!行下边的一行开始),忽略注释.[2]如:1#!/bin/sh2#!/bin/bash3#!/usr/bin/perl4#!/usr/bin/tcl5#!/bin/sed-f6#!/usr/awk-f上边每一个脚本头的行都指定了一个不同的命令解释器,如果是/bin/sh,那么就是默认shell(在Linux系统中默认是Bash).[3]使用#!/bin/sh,在大多数商业发行的UNIX上,默认是Bourneshell,这将让你的脚本可以正常的运行在非Linux机器上,虽然这将会牺牲Bash一些独特的特征.脚本将与POSIX[4]的sh标准相一致.注意:#!后边给出的路径名必须是正确的,否则将会出现一个错误消息,通常是"Commandnotfound",这将是你运行这个脚本时所得到的唯一结果.当然"#!"也可以被忽略,不过这样你的脚本文件就只能是一些命令的集合,不能够使用shell内建的指令了,如果不能使用变量的话,当然这也就失去了脚本编程的意义了.注意:这个例子鼓励你使用模块化的方式来编写脚本,平时也要注意收集一些零碎的代码,这些零碎的代码可能用在你将来编写的脚本中.这样你就可以通过这些代码片段来构造一个较大的工程用例.以下边脚本作为序,来测试脚本被调用的参数是否正确.################################StartScript##################################

高级Bash脚本编程指南.pdf

高级Bash脚本编程指南.pdf

上传者: 筱筱
7次下载 0人收藏 暂无简介 简介 2011-06-27 举报

简介:当前资料暂无简介!

译者序毫无疑问,UNIX/Linux最重要的软件之一就是shell,目前最流行的shell被称为Bash(BourneAgainShell),几乎所有的Linux和绝大部分的UNIX都可以使用Bash。作为系统与用户之间的交互接口,shell几乎是你在UNIX工作平台上最亲密的朋友,因此,学好shell,是学习Linux/UNIX的的开始,并且它会始终伴随你的工作学习。shell是如此地重要,但令人惊奇的是,介绍shell的书没有真正令人满意的。所幸的是,我看到了这本被人称为abs的书,这本书介绍了bash大量的细节和广阔的范围,我遇到的绝大部分的技术问题--无论是我忘记的或是以前没有发现的--都可以在这本书里找到答案。这本使用大量的例子详细地介绍了Bash的语法,各种技巧,调试等等的技术,以循序渐进的学习方式,让你了解Bash的所有特性,在书中还有许多练习可以引导你思考,以得到更深入的知识。无论你是新手还是老手,或是使用其他语言的程序员,我能肯定你能在此书用受益。而本书除了介绍BASH的知识之外,也有许多有用的关于Linux/UNIX的知识和其他shell的介绍。在看到本书的英文版后,我决定把它翻译出来,在Linuxsir论坛上结识了译者之一杨春敏共同翻译这本书,600多页的书是本大部头的书,我们花了6个月的业余时间才翻译完了。关于版权的问题,英文版的作者MendelCooper对英文版的版权做了详细的约定,请参考:AppendixQ.Copyright。中文版版权由译者杨春敏和黄毅共同所有,在遵守英文版版权相应条款的条件下,欢迎在保留本书译者名字和版权说明以非盈利的方式自由发布此中文版,以盈利目的的所有行为必须联系英文作者和两位中文译者以获得许可。本书得以成稿,我(黄毅)要多谢我的女朋友,本该给予她的时间我用来了翻译,多谢你的理解,你是一个很棒的女朋友!译者杨春敏黄毅2006.5.15AdvancedBash-ScriptingGuide<<高级Bash脚本编程指南>>一本深入学习shell脚本艺术的书籍Version3.7.22005/11/16作者:MendelCoopermail:thegrendel@theriver.com这本书假定你没有任何脚本或一般程序的编程知识,但是如果你有相关的知识,那么你将很容易达到中高级的水平...allthewhilesneakinginlittlesnippetsofUNIX?wisdomandlore(这句不知道怎么译).你可以把本书作为教材,自学手册,或者你获得shell脚本技术的文档.书中的练习和例子脚本中的注释将会与读者有更好的互动,但是最关键的前提是:想真正学习脚本编程的唯一途径就是编写脚本.这本书也可作为教材来讲解一般的编程概念.下载本书最新版本,http://personal.riverusers.com/~thegrendel/abs-guide-3.7.tar.bz2,这是一个以tar和bzip2进行打包的,并且是以HTML来发行的.当然,你也可以获得本书的pdf版本在http://www.tldp.org/LDP/abs/abs-guide.pdf.可以在http://personal.riverusers.com/~thegrendel/Change.log中查看修订历史.译者:杨春敏,黄毅mail:chunmin.yang@gmail.com一直想好好学习一下bash,可惜网上的资料都杂乱不堪,我还是喜欢通过一本书系统的学习.这本书来得正是时候.本书的作者真是非常的严谨,从例子里的改进人名单就能看出来.可惜我水平真的是非常有限,好多地方估计译得都有问题.希望阅读的朋友们多多提些修改建议.我会尽我的最大努力去修正它.目录++++第一部分.热身1.为什么使用shell编程2.带着一个Sha-Bang出发(Sha-Bang指的是#!)2.1.调用一个脚本2.2.初步的练习第二部分.基本3.特殊字符4.变量和参数的介绍4.1.变量替换4.2.变量赋值4.3.Bash变量是不分类型的4.4.特殊的变量类型5.引用(翻译的可能有问题,特指引号)5.1.引用变量5.2.转义(\)6.退出和退出状态7.Tests7.1.Test结构7.2.文件测试操作7.3.其他比较操作7.4.嵌套的if/then条件test7.5.检查你的test知识8.操作符和相关的主题8.1.操作符8.2.数字常量第三部分.超越基本9.变量重游9.1.内部变量9.2.操作字符串9.3.参数替换9.4.指定类型的变量:declare或者typeset9.5.变量的间接引用9.6.$RANDOM:产生随机整数9.7.双圆括号结构10.循环和分支10.1.循环10.2.嵌套循环10.3.循环控制10.4.测试与分支(case和select结构)11.内部命令与内建11.1.作业控制命令12.外部过滤器,程序和命令12.1.基本命令12.2.复杂命令12.3.时间/日期命令12.4.文本处理命令12.5.文件与归档命令12.6.通讯命令12.7.终端控制命令12.8.数学计算命令12.9.混杂命令13.系统与管理命令13.1.分析一个系统脚本14.命令替换15.算术扩展16.I/O重定向16.1.使用exec16.2.代码块的重定向16.3.应用17.HereDocuments17.1.HereStrings18.休息时间Part4.高级19.正则表达式19.1.一个简要的正则表达式介绍19.2.通配20.子shell(Subshells)21.受限shell(RestrictedShells)22.进程替换23.函数23.1.复杂函数和函数复杂性23.2.局部变量23.3.不使用局部变量的递归24.别名(Aliases)25.列表结构26.数组27./dev和/proc27.1./dev27.2./proc28.关于Zeros和Nulls29.调试30.选项31.Gotchas32.脚本编程风格32.1.非官方的Shell脚本风格33.杂项33.1.交互式和非交互式的shells和脚本33.2.Shell包装33.3.测试和比较:另一种方法33.4.递归33.5.彩色脚本33.6.优化33.7.各种小技巧33.8.安全话题33.8.1.被感染的脚本33.8.2.隐藏Shell脚本源码33.9.移植话题33.10.在Windows下进行Shell编程34.Bash,版本2和334.1.Bash,版本234.2.Bash,版本335.后记35.1.作者后记35.2.关于作者35.3.哪里可以取得帮助?35.4.制作这本书的工具35.4.1.硬件35.4.2.软件和排版软件35.5.CreditsBibliographyA.ContributedScriptsB.ReferenceCardsC.ASedandAwkMicro-PrimerC.1.SedC.2.AwkD.ExitCodesWithSpecialMeaningsE.ADetailedIntroductiontoI/OandI/ORedirectionF.StandardCommand-LineOptionsG.ImportantFilesH.ImportantSystemDirectoriesI.LocalizationJ.HistoryCommandsK.ASample.bashrcFileL.ConvertingDOSBatchFilestoShellScriptsM.ExercisesM.1.AnalyzingScriptsM.2.WritingScriptsN.RevisionHistoryO.MirrorSitesP.ToDoListQ.Copyright表格清单:11-1.作业标识符30-1.Bash选项33-1.转义序列中数值和彩色的对应B-1.SpecialShellVariablesB-2.TESTOperators:BinaryComparisonB-3.TESTOperators:FilesB-4.ParameterSubstitutionandExpansionB-5.StringOperationsB-6.MiscellaneousConstructsC-1.BasicsedoperatorsC-2.ExamplesofsedoperatorsD-1."Reserved"ExitCodesL-1.Batchfilekeywords/variables/operators,andtheirshellequivalentsL-2.DOScommandsandtheirUNIXequivalentsN-1.RevisionHistory例子清单:2-1.清除:清除/var/log下的log文件2-2.清除:一个改良的清除脚本2-3.cleanup:一个增强的和广义的删除logfile的脚本3-1.代码块和I/O重定向3-2.将一个代码块的结果保存到文件3-3.在后台运行一个循环3-4.备份最后一天所有修改的文件.4-1.变量赋值和替换4-2.一般的变量赋值4-3.变量赋值,一般的和比较特殊的4-4.整型还是string?4-5.位置参数4-6.wh,whois节点名字查询4-7.使用shift5-1.echo一些诡异的变量5-2.转义符6-1.exit/exit状态6-2.否定一个条件使用!7-1.什么情况下为真?7-2.几个等效命令test,/usr/bin/test,[],和/usr/bin/[7-3.算数测试使用(())7-4.test死的链接文件7-5.数字和字符串比较7-6.测试字符串是否为null7-7.zmore8-1.最大公约数8-2.使用算术操作符8-3.使用&&和||进行混合状态的test8-4.数字常量的处理9-1.$IFS和空白9-2.时间输入9-3.再来一个时间输入9-4.Timedread9-5.我是root?9-6.arglist:通过$*和$@列出所有的参数9-7.不一致的$*和$@行为9-8.当$IFS为空时的$*和$@9-9.下划线变量9-10.在一个文本文件的段间插入空行9-11.利用修改文件名,来转换图片格式9-12.模仿getopt命令9-13.提取字符串的一种可选的方法9-14.使用参数替换和errormessages9-15.参数替换和"usage"messages9-16.变量长度9-17.参数替换中的模式匹配9-18.重命名文件扩展名9-19.使用模式匹配来分析比较特殊的字符串9-20.对字符串的前缀或后缀使用匹配模式9-21.使用declare来指定变量的类型9-22.间接引用9-23.传递一个间接引用给awk9-24.产生随机数9-25.从一副扑克牌中取出一张随机的牌9-26.两个指定值之间的随机数9-27.使用随机数来摇一个骰子9-28.重新分配随机数种子9-29.使用awk产生伪随机数9-30.C风格的变量处理10-1.循环的一个简单例子10-2.每个[list]元素带两个参数的for循环10-3.文件信息:对包含在变量中的文件列表进行操作10-4.在for循环中操作文件10-5.在for循环中省略[list]10-6.使用命令替换来产生for循环的[list]10-7.对于二进制文件的一个grep替换10-8.列出系统上的所有用户10-9.在目录的所有文件中查找源字串10-10.列出目录中所有的符号连接文件10-11.将目录中的符号连接文件名保存到一个文件中10-12.一个C风格的for循环10-13.在batchmode中使用efax10-14.简单的while循环10-15.另一个while循环10-16.多条件的while循环10-17.C风格的while循环10-18.until循环10-19.嵌套循环10-20.break和continue命令在循环中的效果10-21.多层循环的退出10-22.多层循环的continue10-23.在实际的任务中使用"continueN"10-24.使用case10-25.使用case来创建菜单10-26.使用命令替换来产生case变量10-27.简单字符串匹配10-28.检查是否是字母输入10-29.用select来创建菜单10-30.用函数中select结构来创建菜单11-1.一个fork出多个自己实例的脚本11-2.printf11-3.使用read,变量分配11-4.当使用一个不带变量参数的read命令时,将会发生什么?11-5.read命令的多行输入11-6.检测方向键11-7.通过文件重定向来使用read11-8.管道输出到read中的问题11-9.修改当前的工作目录11-10.用"let"命令来作算术操作.11-11.显示eval命令的效果11-12.强制登出(log-off)11-13.另一个"rot13"的版本11-14.在Perl脚本中使用eval命令来强制变量替换11-15.使用set来改变脚本的位置参数11-16.重新分配位置参数11-17.Unset一个变量11-18.使用export命令传递一个变量到一个内嵌awk的脚本中11-19.使用getopts命令来读取传递给脚本的选项/参数.11-20."Including"一个数据文件11-21.一个没什么用的,source自身的脚本11-22.exec的效果11-23.一个exec自身的脚本11-24.在继续处理之前,等待一个进程的结束11-25.一个结束自身的脚本.12-1.使用ls命令来创建一个烧录CDR的内容列表12-2.HelloorGood-bye12-3.删除当前目录下文件名中包含一些特殊字符(包括空白)的文件..12-4.通过文件的inode号来删除文件12-5.Logfile:使用xargs来监控系统log12-6.把当前目录下的文件拷贝到另一个文件中12-7.通过名字Kill进程12-8.使用xargs分析单词出现的频率12-9.使用expr12-10.使用date命令12-11.分析单词出现的频率12-12.那个文件是脚本?12-13.产生10进制随机数12-14.使用tail命令来监控系统log12-15.在一个脚本中模仿"grep"的行为12-16.在1913年的韦氏词典中查找定义12-17.检查列表中单词的正确性12-18.转换大写:把一个文件的内容全部转换为大写.12-19.转换小写:将当前目录下的所有文全部转换为小写.12-20.Du:DOS到UNIX文本文件的转换.12-21.rot13:rot13,弱智加密.12-22.Generating"Crypto-Quote"Puzzles12-23.格式化文件列表.12-24.使用column来格式化目录列表12-25.nl:一个自己计算行号的脚本.12-26.manview:查看格式化的man页12-27.使用cpio来拷贝一个目录树12-28.解包一个rpm归档文件12-29.从C文件中去掉注释12-30.Exploring/usr/X11R6/bin12-31.一个"改进过"的strings命令12-32.在一个脚本中使用cmp来比较2个文件.12-33.basename和dirname12-34.检查文件完整性12-35.Uudecod编码后的文件12-36.查找滥用的连接来报告垃圾邮件发送者12-37.分析一个垃圾邮件域12-38.获得一份股票报价12-39.更新FedoraCore412-40.使用ssh12-41.一个可以mail自己的脚本12-42.按月偿还贷款12-43.数制转换12-44.使用"heredocument"来调用bc12-45.计算圆周率12-46.将10进制数字转换为16进制数字12-47.因子分解12-48.计算直角三角形的斜边12-49.使用seq来产生循环参数12-50.字母统计12-51.使用getopt来分析命令行选项12-52.一个拷贝自身的脚本12-53.练习dd12-54.记录按键12-55.安全的删除一个文件12-56.文件名产生器12-57.将米转换为英里12-58.使用m413-1.设置一个新密码13-2.设置一个擦除字符13-3.关掉终端对于密码的echo13-4.按键检测13-5.Checkingaremoteserverforidentd<rojybug>13-6.pidof帮助杀掉一个进程13-7.检查一个CD镜像13-8.在一个文件中创建文件系统13-9.添加一个新的硬盘驱动器13-10.使用umask来将输出文件隐藏起来13-11.killall,来自于/etc/rc.d/init.d14-1.愚蠢的脚本策略14-2.从循环的输出中产生一个变量14-3.找anagram(回文构词法,可以将一个有意义的单词,变换为1个或多个有意义的单词,但是还是原来的子母集合)16-1.使用exec重定向标准输入16-2.使用exec来重定向stdout16-3.使用exec在同一脚本中重定向stdin和stdout16-4.避免子shell16-5.while循环的重定向16-6.另一种while循环的重定向16-7.until循环重定向16-8.for循环重定向16-9.for循环重定向loop(将标准输入和标准输出都重定向了)16-10.重定向if/then测试结构16-11.用于上面例子的"names.data"数据文件16-12.记录日志事件17-1.广播:发送消息给每个登录上的用户17-2.仿造文件:创建一个两行的仿造文件17-3.使用cat的多行消息17-4.带有抑制tab功能的多行消息17-5.使用参数替换的heredocument17-6.上传一个文件对到"Sunsite"的incoming目录17-7.关闭参数替换17-8.一个产生另外一个脚本的脚本17-9.Heredocuments与函数17-10."匿名"hereDocument17-11.注释掉一段代码块17-12.一个自文档化(self-documenting)的脚本17-13.在一个文件的开头添加文本20-1.子shell中的变量作用域20-2.列出用户的配置文件20-3.在子shell里进行串行处理21-1.在受限的情况下运行脚本23-1.简单函数23-2.带着参数的函数23-3.函数和被传给脚本的命令行参数23-4.传递间接引用给函数23-5.解除传递给函数的参数引用23-6.再次尝试解除传递给函数的参数引用23-7.两个数中的最大者23-8.把数字转化成罗马数字23-9.测试函数最大的返回值23-10.比较两个大整数23-11.用户名的真实名23-12.局部变量的可见范围23-13.用局部变量来递归23-14.汉诺塔24-1.脚本中的别名24-2.unalias:设置和删除别名25-1.使用"与列表(andlist)"来测试命令行参数25-2.用"与列表"的另一个命令行参数测试25-3."或列表"和"与列表"的结合使用26-1.简单的数组用法26-2.格式化一首诗26-3.多种数组操作26-4.用于数组的字符串操作符26-5.将脚本的内容传给数组26-6.一些数组专用的工具26-7.关于空数组和空数组元素26-8.初始化数组26-9.复制和连接数组26-10.关于连接数组的更多信息26-11.一位老朋友:冒泡排序26-12.内嵌数组和间接引用26-13.复杂数组应用:埃拉托色尼素数筛子26-14.模拟下推的堆栈26-15.复杂的数组应用:列出一种怪异的数学序列26-16.模拟二维数组,并使它倾斜27-1.利用/dev/tcp来检修故障27-2.搜索与一个PID相关的进程27-3.网络连接状态28-1.隐藏cookie而不再使用28-2.用/dev/zero创建一个交换临时文件28-3.创建ramdisk29-1.一个错误的脚本29-2.丢失关键字(keyword)29-3.另一个错误脚本29-4.用"assert"测试条件29-5.捕捉exit29-6.在Control-C后清除垃圾29-7.跟踪变量29-8.运行多进程(在多处理器的机器里)31-1.数字和字符串比较是不相等同的31-2.子SHELL缺陷31-3.把echo的输出用管道输送给read命令33-1.shell包装33-2.稍微复杂一些的shell包装33-3.写到日志文件的shell包装33-4.包装awk的脚本33-5.另一个包装awk的脚本33-6.把Perl嵌入Bash脚本33-7.Bash和Perl脚本联合使用33-8.递归调用自己本身的(无用)脚本33-9.递归调用自己本身的(有用)脚本33-10.另一个递归调用自己本身的(有用)脚本33-11.一个"彩色的"地址资料库33-12.画盒子33-13.显示彩色文本33-14."赛马"游戏33-15.返回值技巧33-16.整型还是string?33-17.传递和返回数组33-18.anagrams游戏33-19.在shell脚本中调用的窗口部件34-1.字符串扩展34-2.间接变量引用-新方法34-3.使用间接变量引用的简单数据库应用34-4.用数组和其他的小技巧来处理四人随机打牌A-1.mailformat:Formattingane-mailmessageA-2.rn:Asimple-mindedfilerenameutilityA-3.blank-rename:renamesfilenamescontainingblanksA-4.encryptedpw:Uploadingtoanftpsite,usingalocallyencryptedpasswordA-5.copy-cd:CopyingadataCDA-6.CollatzseriesA-7.days-between:CalculatenumberofdaysbetweentwodatesA-8.Makea"dictionary"A-9.SoundexconversionA-10."GameofLife"A-11.Datafilefor"GameofLife"A-12.behead:RemovingmailandnewsmessageheadersA-13.ftpget:DownloadingfilesviaftpA-14.password:Generatingrandom8-characterpasswordsA-15.fifo:Makingdailybackups,usingnamedpipesA-16.GeneratingprimenumbersusingthemodulooperatorA-17.tree:DisplayingadirectorytreeA-18.stringfunctions:C-likestringfunctionsA-19.DirectoryinformationA-20.Object-orienteddatabaseA-21.LibraryofhashfunctionsA-22.ColorizingtextusinghashfunctionsA-23.MountingUSBkeychainstoragedevicesA-24.PreservingweblogsA-25.ProtectingliteralstringsA-26.UnprotectingliteralstringsA-27.SpammerIdentificationA-28.SpammerHuntA-29.MakingwgeteasiertouseA-30.A"podcasting"scriptA-31.BasicsReviewedA-32.AnexpandedcdcommandC-1.CountingLetterOccurrencesK-1.Sample.bashrcfileL-1.VIEWDATA.BAT:DOSBatchFileL-2.viewdata.sh:ShellScriptConversionofVIEWDATA.BATP-1.Printtheserverenvironment第一部分热身++++++++++++++++shell是一个命令解释器.是介于操作系统kernel与用户之间的一个绝缘层.准确地说,它也是一一种强力的计算机语言.一个shell程序,被称为一个脚本,是一种很容易使用的工具,它可以通过将系统调用,公共程序,工具,和编译过的二进制程序粘合在一起来建立应用.事实上,所有的UNIX命令和工具再加上公共程序,对于shell脚本来说,都是可调用的.如果这些你还觉得不够,那么shell内建命令,比如test与循环结构,也会给脚本添加强力的支持和增加灵活性.Shell脚本对于管理系统任务和其它的重复工作的例程来说,表现的非常好,根本不需要那些华而不实的成熟紧凑的程序语言.第1章为什么使用shell编程===========================没有程序语言是完美的.甚至没有一个唯一最好的语言,只有对于特定目的,比较适合和不适合的程序语言.HerbertMayer对于任何想适当精通一些系统管理知识的人来说,掌握shell脚本知识都是最基本的,即使这些人可能并不打算真正的编写一些脚本.想一下Linux机器的启动过程,在这个过程中,必将运行/etc/rc.d目录下的脚本来存储系统配置和建立服务.详细的理解这些启动脚本对于分析系统的行为是非常重要的,并且有时候可能必须修改它.学习如何编写shell脚本并不是一件很困难的事,因为脚本可以分为很小的块,并且相对于shell特性的操作和选项[1]部分,只需要学习很小的一部分就可以了.语法是简单并且直观的,编写脚本很像是在命令行上把一些相关命令和工具连接起来,并且只有很少的一部分规则需要学习.绝大部分脚本第一次就可以正常的工作,而且即使调试一个长一些的脚本也是很直观的.一个shell脚本是一个类似于小吃店的(quickanddirty)方法,在你使用原型设计一个复杂的应用的时候.在工程开发的第一阶段,即使从功能中取得很有限的一个子集放到shell脚本中来完成往往都是非常有用的.使用这种方法,程序的结果可以被测试和尝试运行,并且在处理使用诸如C/C++,Java或者Perl语言编写的最终代码前,主要的缺陷和陷阱往往就被发现了.Shell脚本遵循典型的UNIX哲学,就是把大的复杂的工程分成小规模的子任务,并且把这些部件和工具组合起来.许多人认为这种办法更好一些,至少这种办法比使用那种高\大\全的语言更美,更愉悦,更适合解决问题.比如Perl就是这种能干任何事能适合任何人的语言,但是代价就是你需要强迫自己使用这种语言来思考解决问题的办法.什么时候不使用Shell脚本资源密集型的任务,尤其在需要考虑效率时(比如,排序,hash等等)需要处理大任务的数学操作,尤其是浮点运算,精确运算,或者复杂的算术运算(这种情况一般使用C++或FORTRAN来处理)有跨平台移植需求(一般使用C或Java)复杂的应用,在必须使用结构化编程的时候(需要变量的类型检查,函数原型,等等)对于影响系统全局性的关键任务应用。对于安全有很高要求的任务,比如你需要一个健壮的系统来防止入侵,破解,恶意破坏等等.项目由连串的依赖的各个部分组成。需要大规模的文件操作需要多维数组的支持需要数据结构的支持,比如链表或数等数据结构需要产生或操作图形化界面GUI需要直接操作系统硬件需要I/O或socket接口需要使用库或者遗留下来的老代码的接口私人的,闭源的应用(shell脚本把代码就放在文本文件中,全世界都能看到)如果你的应用符合上边的任意一条,那么就考虑一下更强大的语言吧--或许是Perl,Tcl,Python,Ruby--或者是更高层次的编译语言比如C/C++,或者是Java.即使如此,你会发现,使用shell来原型开发你的应用,在开发步骤中也是非常有用的.我们将开始使用Bash,Bash是"Bourne-Againshell"首字母的缩写,也是StephenBourne的经典的Bourneshell的一个双关语,(译者:说实话,我一直搞不清这个双关语是什么意思,为什么叫"Bourn-Againshell",这其中应该有个什么典故吧,哪位好心,告诉我一下^^).Bash已经成为了所有UNIX中shell脚本的事实上的标准了.同时这本书也覆盖了绝大部分的其他一些shell的原则,比如KornShell,Bash从ksh中继承了一部分特性,[2]CShell和它的变种.(注意:CShell编程是不被推荐的,因为一些特定的内在问题,TomChristiansen在1993年10月指出了这个问题请在http://www.etext.org/Quartz/computer/unix/csh.harmful.gz中查看具体内容.)接下来是脚本的一些说明.在展示shell不同的特征之前,它可以减轻一些阅读书中例子的负担.本书中的例子脚本,都在尽可能的范围内进行了测试,并且其中的一些将使用在真实的生活中.读者可以运行这些例子脚本(使用scriptname.sh或者scriptname.bash的形式),[3]并给这些脚本执行权限(chmodu+rxscriptname),然后执行它们,看看发生了什么.如果存档的脚本不可用,那么就从本书的HTML,pdf或者text的发行版本中把它们拷贝粘贴出来.考虑到这些脚本中的内容在我们还没解释它之前就被列在这里,可能会影响读者的理解,这就需要读者暂时忽略这些内容.除非特别注明,本书作者编写了本书中的绝大部分例子脚本.注意事项:[1]这些在builtins章节被引用,这些是shell的内部特征.[2]ksh88的许多特性,甚至是一些ksh93的特性都被合并到Bash中了.[3]根据惯例,用户编写的Bourneshell脚本应该在脚本的名字后边加上.sh扩展名.一些系统脚本,比如那些在/etc/rc.d中的脚本,则不遵循这种命名习惯.第2章带着一个Sha-Bang出发(Sha-Bang指的是#!)==============================================在一个最简单的例子中,一个shell脚本其实就是将一堆系统命令列在一个文件中.它的最基本的用处就是,在你每次输入这些特定顺序的命令时可以少敲一些字.Example2-1清除:清除/var/log下的log文件################################StartScript#######################################1#Cleanup2#当然要使用root身份来运行这个脚本34cd/var/log5cat/dev/null>messages6cat/dev/null>wtmp7echo"Logscleanedup."################################EndScript#########################################这根本就没什么稀奇的,只不过是命令的堆积,来让从console或者xterm中一个一个的输入命令更方便一些.好处就是把所有命令都放在一个脚本中,不用每次都敲它们.这样的话,对于特定的应用来说,这个脚本就很容易被修改或定制.Example2-2清除:一个改良的清除脚本################################StartScript#######################################1#!/bin/bash2#一个Bash脚本的正确的开头部分.34#Cleanup,版本256#当然要使用root身份来运行.7#在此处插入代码,来打印错误消息,并且在不是root身份的时候退出.89LOG_DIR=/var/log10#如果使用变量,当然比把代码写死的好.11cd$LOG_DIR1213cat/dev/null>messages14cat/dev/null>wtmp151617echo"Logscleanedup."1819exit#这个命令是一种正确并且合适的退出脚本的方法.################################EndScript#########################################现在,让我们看一下一个真正意义的脚本.而且我们可以走得更远...Example2-3.cleanup:一个增强的和广义的删除logfile的脚本################################StartScript#######################################1#!/bin/bash2#清除,版本334#Warning:5#-------6#这个脚本有好多特征,这些特征是在后边章节进行解释的,大概是进行到本书的一半的7#时候,8#你就会觉得它没有什么神秘的了.9#10111213LOG_DIR=/var/log14ROOT_UID=0#$UID为0的时候,用户才具有根用户的权限15LINES=50#默认的保存行数16E_XCD=66#不能修改目录?17E_NOTROOT=67#非根用户将以error退出181920#当然要使用根用户来运行21if["$UID"-ne"$ROOT_UID"]22then23echo"Mustberoottorunthisscript."24exit$E_NOTROOT25fi2627if[-n"$1"]28#测试是否有命令行参数(非空).29then30lines=$131else32lines=$LINES#默认,如果不在命令行中指定33fi343536#StephaneChazelas建议使用下边37#+的更好方法来检测命令行参数.38#+但对于这章来说还是有点超前.39#40#E_WRONGARGS=65#非数值参数(错误的参数格式)41#42#case"$1"in43#"")lines=50;;44#*[!0-9]*)echo"Usage:`basename$0`file-to-cleanup";exit$E_WRONGARGS;;45#*)lines=$1;;46#esac47#48#*直到"Loops"的章节才会对上边的内容进行详细的描述.495051cd$LOG_DIR5253if[`pwd`!="$LOG_DIR"]#或者if["$PWD"!="$LOG_DIR"]54#不在/var/log中?55then56echo"Can'tchangeto$LOG_DIR."57exit$E_XCD58fi#在处理logfile之前,再确认一遍当前目录是否正确.5960#更有效率的做法是61#62#cd/var/log||{63#echo"Cannotchangetonecessarydirectory.">&264#exit$E_XCD;65#}6667686970tail-$linesmessages>mesg.temp#保存logfile消息的最后部分.71mvmesg.tempmessages#变为新的log目录.727374#cat/dev/null>messages75#*不再需要了,使用上边的方法更安全.7677cat/dev/null>wtmp#':>wtmp'和'>wtmp'具有相同的作用78echo"Logscleanedup."7980exit081#退出之前返回0,返回0表示成功.82#################################EndScript#########################################因为你可能希望将系统log全部消灭,这个版本留下了log消息最后的部分.你将不断地找到新的方法来完善这个脚本,并提高效率.要注意,在每个脚本的开头都使用"#!",这意味着告诉你的系统这个文件的执行需要指定一个解释器.#!实际上是一个2字节[1]的魔法数字,这是指定一个文件类型的特殊标记,换句话说,在这种情况下,指的就是一个可执行的脚本(键入manmagic来获得关于这个迷人话题的更多详细信息).在#!之后接着是一个路径名.这个路径名指定了一个解释脚本中命令的程序,这个程序可以是shell,程序语言或者是任意一个通用程序.这个指定的程序从头开始解释并且执行脚本中的命令(从#!行下边的一行开始),忽略注释.[2]如:1#!/bin/sh2#!/bin/bash3#!/usr/bin/perl4#!/usr/bin/tcl5#!/bin/sed-f6#!/usr/awk-f上边每一个脚本头的行都指定了一个不同的命令解释器,如果是/bin/sh,那么就是默认shell(在Linux系统中默认是Bash).[3]使用#!/bin/sh,在大多数商业发行的UNIX上,默认是Bourneshell,这将让你的脚本可以正常的运行在非Linux机器上,虽然这将会牺牲Bash一些独特的特征.脚本将与POSIX[4]的sh标准相一致.注意:#!后边给出的路径名必须是正确的,否则将会出现一个错误消息,通常是"Commandnotfound",这将是你运行这个脚本时所得到的唯一结果.当然"#!"也可以被忽略,不过这样你的脚本文件就只能是一些命令的集合,不能够使用shell内建的指令了,如果不能使用变量的话,当然这也就失去了脚本编程的意义了.注意:这个例子鼓励你使用模块化的方式来编写脚本,平时也要注意收集一些零碎的代码,这些零碎的代码可能用在你将来编写的脚本中.这样你就可以通过这些代码片段来构造一个较大的工程用例.以下边脚本作为序,来测试脚本被调用的参数是否正确.################################StartScript##################################
  • 相关资料
  • 该用户的其他资料
  • 名称/格式
  • 下载次数
  • 资料大小
  • 名称/格式
  • 下载次数
  • 资料大小

用户评论

0/200
暂无评论
上传我的资料

资料阅读排行

关闭

请选择举报的类型

关闭

提示

提交成功!

感谢您对爱问共享资料的支持,我们将尽快核实并处理您的举报信息。

关闭

提示

提交失败!

您的举报信息提交失败,请重试!

关闭

提示

重复举报!

亲爱的用户!感觉您对爱问共享资料的支持,请勿重复举报噢!

全屏 缩小 放大
收藏
资料评价:

/ 590
所需积分:5 立即下载
返回
顶部
举报
资料
关闭

温馨提示

感谢您对爱问共享资料的支持,精彩活动将尽快为您呈现,敬请期待!