位置: 编程技术 - 正文

shell脚本学习指南[五](Arnold Robbins & Nelson H.F. Beebe著)(shell脚本用法)

发布时间:2024-02-27

作者告诉我们:到目前为止基础已经搞定,可以将前边所学结合shell变成进军中等难度的任务了。激动的要哭了,终于看到本书结束的曙光了 T T 。码字比码代码还辛苦。不过令人兴奋的是立刻就学以致用了,花了一天半的时间处理了一个3.8G的服务器日志文件,你妹啊,破电脑内存才2G。不过切割化小然后写了几个awk文件和sh文件按规则处理合并,算是搞定了!

第十一章扩展实例:合并用户数据库

问题描述就是有两台UNIX的计算机系统,这两个系统现在要合并,用户群同样需要合并。有许多用户两台系统上都有帐号。现在合并需要的功能是:将两个系统里的/etc/passwd文件合并,并确保来自这两台系统的所有用户有唯一UID。针对已存在的UID、但被用在不同用户身上的情况,则将其所有文件的所有权变更为正确用户。

解决这个问题,我们程序必须处理的情况可能有这些:1、用户在两个系统都有用户名和UID。2、用户的用户名和UID只有一台系统里有,另一台没有,这合并时不会有问题。3、用户在两台系统都有相同的用户名但UID不同。4、用户在两台系统拥有相同UID但用户名不同。

合并密码文件几个步骤:1、直接物理合并文件,重复的username聚在一起,产生结果为下步输入。2、将合并文件分三分:具有相同username和UID的用户放入unique,未重复的用户username也放入。具有相同username但不同UID的放入dupusers,具有相同UID但不同username的放入dupids。3、建立已使用中具有唯一性的UID编号列表。可用来寻找新的未使用UID。4、编写另一个程序,搭配使用UID编号了解,寻找新的UID编号。5、建立用以产生最后/etc/passwd记录的三项组合(username、old UID、new UID)列表。还有最重要的:产生命令,以变更文件系统中文件的所有权。与此同时,针对原来就拥有数个UID的用户以及同一UID拥有多个用户,建立最后的密码文件项目。6、建立最终密码文件。7、建立变更文件所有权的命令列表,并执行,这部分要谨慎处理,小心规划。

这里书中针对上述步骤书写了程序,很大一部分代码是处理UID的,个人感觉全部使用新的UID来重新映射username,不是很简单就搞定一切了。只用把所有出现的username记录出来,重复的干掉,再顺序给出对应UID,很简单几步搞定了。至于之后根据old UID更改文件权限,完全可以做新旧UID的映射,直接改到新的里边就OK了。这样想来如果更改文件权限是程序主要耗时部分的话,书中原方法还是可取的,只是编码复杂度较高。如果更改权限耗时能够承受,还是选择编码复杂度低的来搞速度还快点,也方便。

这里更改文件权限使用chown命令,可以更改文件拥有用户或用户组。-R选项递归处理。但出现的问题是用户拥有的文件未必只放在用户根目录里。所以更改用户在每一个地方的文件需要使用find命令,从根目录开始做。类似这样:find / -user $user -exec chown $newuid '{}' ;-exec选项会针对每一个与条件比对相符的文件执行接下来的所有参数,直到分号为止。find命令里的{}意指替换找到的文件名称至命令。这样使用find代码很高,因为它会针对每一个文件或目录建立一个新的chown进程。可以替换成:find / -user $user -print | xargs chown $newuid#有GNU工具集可以:find / -user $user -print0 | xargs --null chown $newuid这样就把所有需要更改的文件传送至一个新的进程来处理,而不是很多个。

这里有个另外的问题,加入old-new-list里的数据这样:juser mrwizard 也就是说如果先变更juser,把juser的文件权限UID变更为UID以后,再变更mrwizard的时候问题就来了,程序会把之前所有的juser的文件当成mrwizard的文件。这时就牵扯到处理顺序问题,我们必须在变成之前,把变成。解决方法也简单,给所有的UID编号是没有任何地方使用过即可。

这里还剩最后一个小问题,就是find命令寻找用户的时候,注意我们问题的环境,目前是有两台服务器,find寻找用户的时候是有可能找不到另一台服务器用户的。需要作出处理。

再说一下我们解决这个问题时规避的一些真实世界的问题。最明显的是我们很可能也需要合并/etc/group文件。再者,任何一个大型的系统,都可能会出现文件拥有已不存在于/etc/passwd与/etc/group里的UID或GID值,寻找这里文件可以这样:find / '(' -nouser -o -nogroup ')' -ls这样做将产生所有这样的文件输出。可以使用管道进一步处理xargs chown...这样。第三点是在改变文件的用户与组处理期间,文件系统绝对得静止。处理时不应该有任何其他活动发生,使系统处于单用户模式下root登录,且只能在系统物理console设备上完成这个任务。最后就是效率问题,每个用户都需要跑一遍find是很不划算的,我们可以跑一遍来处理所有用户的文件,类似这样:find / -ls | awk -f make-command.awk old-to-new.txt - > /tmp/commands/sh ... 在执行前先检查 /tmp/commands/sh ... sh / tmp/commands/sh类似这样。先读取old-to-new.txt的旧换新UID变更,然后awk会针对每一个输出文件寻找是否有必须被更改,如果要更改则使用chown命令。

详细代码之类的略过吧,没特殊算法,都很简单。

第十二章拼写检查

最初的unix拼写检查原型为代码说一下:

comm命令是用以比较两个排序后的文件,并选定或拒绝两个文件里共同的行。-选项是仅输出来自第二个文件(管道输入的内容)但不在第一个文件(字典)里的行。-1 不显示第一列(只在第一个文件出现的行)-2 不显示第二列(只在第2个文件出现的行)-3不显示第三列(两个文件都有的行)。

后续的有改良的命令ispell和aspell,有一个不错的功能就是可以提供本地有效的单词拼写列表,如:spell +/usr/local/lib/local.words myfile > myfile.errs针对所写文档提供哦功能私有拼写字典,非常重要,这能使拼写检查更高效准确。但是spell还有一些棘手的事情,即locale变动后会使命令达不到预期效果如:

默认的locale在操作系统版本之间可能有所不同。因此最好的方式便是将LC_ALL环境变量设置与私人字典排序一致,再执行spell。env命令的作用是在重建的环境中运行命令。

书中展现了spell的awk版本,也展现awk的强大。为引导程序进行,先列出我们预期的设计目标:1、程序将会能够读取文字数据流、隔离单词、以及报告不在已知单词列表的单词。2、将会有一个默认的单词列表,由一个或多个系统字典收集而成。3、它将可能取代默认的单词列表。4、标准单词列表将有可能由一个或多个用户所提供的单词列表而扩增。该列表在技术性文件上特别有用,例如首字母缩写、术语及专有名词等。5、单词列表将无须排序。6、虽然默认单词列表都是英文,但辅以适当的替代性单词列表,程序将可能处理任何语言的文字,只要它是以基础为ASCII的字符集呈现,以空白字符分隔单词。7、忽略字母大小写,让单词列表维持在易于管理的大小,但异常报告采用原大小写。8、忽略标点符号,但顿点符号(缩写的撇)将视为字母。9、默认的报告将为排序后具有独一无二单词的列表以一行一个单词的方式呈现。为拼写异常列表。、将可通过选项增加异常列表报告,并有位置信息,如文件名行号等,以利于寻找异常单词。报告将以位置排序,且当他们在同一位置发现多个异常时,则进一步依异常单词排序。、支持用户可指定的后缀缩写,让单词列表保持在易于管理的大小。

又是很长的代码,码的头晕。。。不保证全对,注释也先不写了。执行命令:$ awk -f spell.awk testfile

这里针对搞算法竞赛的同学说一点,shell脚本里的高效,怎么样叫高效,我也是搞竞赛的,总是追求程序运行时的效率,但是在shell脚本里追求的是总体效率。完成一个任务假如编码时间用了1个小时,最终完成的代码运行花秒钟,和为了优化程序提高运行效率而编码时间花了2个小时乃至更多时间,最后运行代码时间缩减,无论缩减多少,我们都认为这个优化还是不太值得肯定的。这里不是否定代码运行效率,而是要平衡这个编码时间。而且shell目前我感觉应该是线下运行的程序多,不是在线运行的程序,所以时间上的要求可以放宽很多。所以我们要做的就是完成一个任务花费更少的时间就好。个人感觉,不对了感谢指正。

第十三章进程

进程是一个执行中程序的一个实例,新进程由fork()与execve()等系统调用所起始执行直到exit()为止。进程会被指定优先权,nice和renice命令用于调整进程的优先权。任何瞬间,等待执行之进程的平均数,被成为平均负载,uptime命令可显示。列出进程状态的命令是ps(process status)。System V形式下:ps -efl显示更多信息,BSD形式是ps aux 。进程列表是动态的,如果想观察动态的,可以使用top命令。

shell程序处理下一个命令之前会等待前一条命令结束,但是在命令最后加入&可以使其在后台运行,便可不用等待上一个命令了。wait命令可以用来等待某个特定进程完成,在不加任何参数情况下,则为等待所有后台进程完成。另外控制的还有bg、fg、jobs等都处理目前shell下所建立的执行中的进程。

有4组键盘字符可用以中断前台进程,这些字符可通过stty命令选项而设置。一般是Ctrl-C(intr:杀除)、Ctrl-Y(dsusp:暂时搁置,直到输入更新为止)、Ctrl-Z(susp:暂时搁置),与Ctrl-(quit:以核心存储方式杀除)。

用上边的几个命令实现一个简单的top命令:

再实现一个针对user查询的脚本:

内容都很简单,不再赘述注释。

进程列表有了,如何控制或者删除某一个进程呢。之前有说exit()能让进程终止,但有时候我们会提前终止,这时我们需要kill命令。kill命令会传送信号(signal)给指定的执行程序,不过它有两个例外,稍后提到。进程接到信号,并处理之,有时可能直接选择忽略它们。只有进程拥有者或root、内核、进程本身可以传送信号给它。但是接收信号的进程本身无法判断信号从何而来。不同的系统支持不同的信号类型,你可以通过kill -l 来列出你当前使用的系统支持的信号类型。每个处理信号的程序都可以自由决定如何解决接到的这些信号。信号名称反应的是惯用性(conventions),而非必须性(requirement),所以对不同的程序而言,信号所表示的意义也会稍有不同。

kill pid 就可以直接终止进程。控制进程的话,就使用刚才kill -l罗列出来的进程信号,用法:kill[-ssignal|-p][-a]pid... 需要自行了解自己系统的进程信号。比如:

删除进程必须直到四个信号:ABRT(中断)、HUP(搁置)、KILL、TERM(终结)。不同系统有所不同貌似,可以查看一下,名字应该类似:kill -l | grep -e "KILL|BRT|HUP|TERM"

有些程序会在结束前做些清理工作,一般TERM信号解释为“快速清理并结束”,如果未指定信号,默认的kill会传送此信号。ABRT类似TERM它会抑制清除操作,并产生进程内的影像的副本。HUP类似要求中止,时常表示进程应该先停止正在处理的事情,然后准备处理新工作。有两个进程没有任何进程可以忽略的:KILL和STOP,这两个信号一定会立刻被传送,但是也有特例情况,根据实际情况也可能会被延时的。不同系统平台有差异。

小心使用这些终止命令。当程序非正常中止,都可能在文件系统留下残余数据,这些残余数据除了浪费空间,还可能导致下次执行程序发生问题。比如:daemon、邮件客户端程序、文字编辑器、以及网页浏览器都会产生锁定(lock)。如果程序第二实例被启动,而第一实例仍在执行时,第二个实例会侦测到已存在的lock,回报该事实并立即中止。最糟糕的是,这些程序很少会告诉你lock文件的文件名,并很少将它写入文件里。如果该lock文件长期执行进程的残余数据,你可能发现程序无法执行,直到你找到lock并删除为止。

有的系统提供pgrep和pkill。它们能根据进程名称结束进程,详细自行看manual。

关于捕捉进程信号。进程会向内核注册哪些它们想要处理的信号。它们标明在signal()程序库调用的参数里。man -a signal 可以查看所有关于信号的manual。trap可引起shell注册信号处理器(signal handler),抓取指定的信号。trap取得一个字符串参数,其包含采取捕捉时要被执行的命令列表,紧接着一个要设置捕捉的信号列表。

下边展示一个小型shell脚本:looper,它的功能是使用trap命令,说明被抓取(caught)与未被抓取的信号。

]

$ looper & #运行这个脚本于后台[1] $ kill -HUP Ignoring HUP ...$ kill -USR1 Terminating on USR1 ...[1]+Done(1)

其他进程控制命令自行测试,或者搜文章学习。后边又讲了一些进程的日志。

进程延迟。sleep命令暂停执行一段时间后唤醒。at是延迟至特定时间,这个命令在不同系统有差异,但下列例子普遍适用:at : #晚上9点执行at now #立刻执行at now + minutes #分钟后执行at now + 8 hoursat tomorrow #明天早上4点执行at Julyat noon + minutes #今天下午:执行at teatime #下午:执行at允许相当复杂的时间指定 。接受HH:MM的时间式样,如果时间过了则为第二天这个时间。midnight是午夜,noon中午,teatime下午4点,也可以适用AM或PM后缀指定上下午,也可以month-name dat加上可选的年份式样来指定日期,或者给出MMDDYY、MM/DD/YY或DD.MM.YY来执行日期。日期单位有minutes hours days weeks ,还有today、tomorrow。

atq命令列出at队列里的所有工作,而atrm则是删除它们。batch在系统负载水平允许的时候执行命令,换句话说当平均负载低于0.8或降到了在atrun文件中指定的期望值时运行。

大部分计算机有许多管理工作需要重复执行,像每晚文件系统备份之类的。crontab命令可在指定的时间执行工作,其包括了系统启动时起始的cron daemon。crontab -l 列出你目前工作调度,以crontab -e启动编辑器更新调度。编辑器的选择根据EDITOR环境变量而定,有些计算机会因为未设置此参数而拒绝执行crontab。crontab适用的调度参数:

前5栏除了使用单一数字外,还可以搭配连字符分隔,指出一段区间,或者使用逗点分隔数字列表或区间。还可以使用星号,指该字段所有可能数字。范例: * * * * command # 每个小时的第分钟执行0 2 1 * * command # 每个月一开始的:执行0 8 1 1,7 * command # 每个一月一日与七月一日的:执行0 6 * * 1 command # 每周一:执行0 8- * * 0,6 command # 每周末的:到:间一小时执行一次在command可以详细指出要执行的文件或重新设定要执行文件的查找路径:0 4 * * * /usr/local/bin/updatedb0 4 * * * PATH=/usr/local/bin:$PATH updatedb任何出现在标准错误输出或标准输出上的数据都会显示给你,或是在其他实例中,将会寄到MAILTO变量的值所指定的用户。实物上通常会比较倾向与将输出重导至一个日志文件,并累积连续执行的记录: * * * $HOME/bin/daily >> $HOME/logs/daily.log 2>&1这样日志文件会过大,一般可以加上日期: * * * $HOME/bin/daily > $HOME/logs/daily.`date +%Y.%m.%d`.log 2>&1这样时间长了文件会过多,你可以轻松删除或压缩这些文件:find $HOME/logs/*.log -ctime + | xargs bzip2 -9 #压缩一个月前的日志文件find $HOME/logs/*.log -ctime + | xargs rm #删除一个月前的日志文件这里小心crontab -r 将crontab文件整个删除。它就像rm一样无法撤回,也无法复原。建议保留备份:crontab -l > $HOME/.crontab.`hostname` #存储现行的crontab恢复的时候:crontab $HOME/.crontab.`hostname` #回复存储的crontab就像at命令那样,系统目录里也有cron.allow与cron.deny文件,用以控制是否允许cron工作,以及谁可以执行它们。

最后讲了一下/proc文件系统,大概意思是每个子进程在那里有个目录用进程ID命令。

推荐整理分享shell脚本学习指南[五](Arnold Robbins & Nelson H.F. Beebe著)(shell脚本用法),希望有所帮助,仅作参考,欢迎阅读内容。

shell脚本学习指南[五](Arnold Robbins & Nelson H.F. Beebe著)(shell脚本用法)

文章相关热门搜索词:shell脚本详解,shell脚本指南,shell脚本基础知识,shell脚本 教程,shell脚本基础教学,shell脚本学习指南,shell脚本基础知识,shell脚本学习指南,内容如对您有帮助,希望把文章链接给更多的朋友!

shell脚本学习指南[六](Arnold Robbins & Nelson H.F. Beebe著) 学shell到现在了,一直以为自己不会犯一个大家常说的非常二的问题,结果这本书最后的时候犯了个十分2的事,晚节不保啊!!!我在测试文件路径下

csh,tcsh,bash,sh等shell的区别 出自bash的faq,仔细看看。顺便翻译学习一下。SectionC:DifferencesfromotherUnixshellsC:跟其他UNIXshells脚本的区别C1)Howdoesbashdifferfromsh,theBourneshell?C1)bash和sh、Bou

Shell字符串截取的详细方法 一、Linuxshell截取字符变量的前8位,有方法如下:1.exprsubstr$a.echo$a|awk‘{printsubstr(,1,8)}'3.echo$a|cut-c1-.echo$5.expr$a:‘(.\).*'6.echo$a|ddbs=1count=/dev/null二、

标签: shell脚本用法

本文链接地址:https://www.jiuchutong.com/biancheng/374764.html 转载请保留说明!

上一篇:shell脚本学习指南[四](Arnold Robbins & Nelson H.F. Beebe著)(shell脚本指南)

下一篇:shell脚本学习指南[六](Arnold Robbins & Nelson H.F. Beebe著)(shell脚本用法)

  • 新办营利性医疗机构是否免征土地使用税和房产税?
  • 企业的罚款支出包括违约金吗
  • 资产负债表债务法是什么意思
  • 税收优惠政策落实情况报告
  • 一般计税方法是全额计税吗
  • 进项税转出大于进项税额还需要填列加计抵减附表吗
  • 公司收入是否应优先支付工资
  • 交易性金融资产借贷方向
  • 已计提的固定资产减值准备累计金额
  • 政策性用房包括哪些
  • 政府补贴装修费怎么算
  • 企业支付小额劳务费税率
  • 公司开发票要交多少钱的税?
  • 实缴年月正常补收
  • 销售方针有哪些
  • 城市建设维护税是什么意思
  • 民办非企业所得税免税政策
  • 预付账款收不到发票怎么冲账
  • 融资租赁不动产税务处理
  • 过期商品报损账务处理?
  • 附加税是销项税减去进项税
  • mac怎么打印文件内容
  • 生产车间机器设备日常维修
  • 即征即退申报表如何填写
  • 航空公司收取什么费
  • 商品房买卖合同备案查询
  • mac废纸篓立即删除和清倒
  • linux sar文件
  • 电脑网络提示ip地址错误怎么办
  • 利尼扬蒂野生动物保护区中的一只雄性豹子,博茨瓦纳 (© Karine Aigner/Tandem Stills + Motion)
  • 失控发票进项转出后要补企业所得税吗
  • 广告费增值税税目是什么
  • 漏洞 标准
  • codeigniter3中文手册
  • 招聘下岗职工一名
  • 劳务公司已开票,可款项未收到,税票多久有效
  • Thinkphp事务操作实例(推荐)
  • wordpress转化为html
  • vue中 router.beforeEach() 的用法
  • 魔改6.67
  • php如何使用
  • 总公司与分公司怎么报税
  • 新准则下担保企业有哪些
  • 行政事业单位资产管理办法
  • 公司购买手机的发票
  • 车船税酌定减免
  • 脚手架租赁费用超过购买价格
  • 购买商品优惠怎么做账
  • 税务法新规
  • 分批发货分批付款
  • mysql异常退出
  • 回购股票不注销如何发可转债
  • 结账的内容和程序是什么
  • 销售折让如何做分录
  • 汇算清缴预缴
  • 生产成本制造费用结转
  • 公司办公室装修装修
  • 离职员工未休完的年假如何支付
  • 进项税转出补税按多少补税
  • 成本利润率计算销售价格
  • Vista技巧:何在Vista上运行不兼容的旧版本软件
  • linux系统的安装与配置
  • winxp程序和功能在哪里
  • win7屏幕颜色变了怎么恢复
  • 怎么更改windows商店的安装位置
  • 工商网银登陆
  • linux的samba是什么
  • win8注销在哪里
  • win7如何安装iis7.0
  • 如何获取system权限win10
  • perl的chomp
  • Node.js中的事件循环是什么意思
  • linux中切换目录命令符
  • javascript基础笔记
  • unity3d鼠标点击移动
  • 哪些润滑油属于润滑剂
  • 企业购置房屋需要交哪些税费
  • 国家税务局总局政策咨询
  • 河南省郑州市巩义市籍贯怎么写
  • 退契税的时间是什么时候
  • 免责声明:网站部分图片文字素材来源于网络,如有侵权,请及时告知,我们会第一时间删除,谢谢! 邮箱:opceo@qq.com

    鄂ICP备2023003026号