1、网线串口线宿主机(开发平台)目标机(运行平台)宿主机要求:1安装操作系统RedHat linux 。2、宿主机配置网络及各种服务器。3、建立交叉编译调试环境。基于基于Linux的嵌入式系统开发模式的嵌入式系统开发模式二、宿主机二、宿主机Linux系统配置:系统配置:1、安装VMware tools:鼠标移动、显示性能、网络功能、共享资源2、配置桌面、网络:3、实现windows和linux共享:4、设置nfs服务器:建立交叉编译环境方法:(共享法)共享设置./install.sh修改/root/.bash_profile注销2、armv4l-unknown-linux-gcc1、arm-lin
2、ux-gcc1)利用nfs或者文件夹共享,将配好的redhat linux中opt/crosstools文件夹考到本地linux中opt目录下。2)修改/root/.bash_profile文件或者利用共享覆盖。3)注销登录PATH=$path:$home/bin/:第二章第二章 Linux 程序设计基础程序设计基础1、Linux下下c程序开发程序开发2、Linux下的下的 shell 编程编程Linux下的下的C语言语言 C语言是一门“中级语言”,是汇编语言和高级语言过渡的一种语言,但是它既具有高级语言简单易懂、灵活方便的特点,同时,他又具有汇编语言的执行高效和可对硬件直接操作的特点。C语言
3、的应用进行底层的开发: 如内核开发及基于linux的嵌入式开发。进行顶层的开发: 如linux下的应用程序的开发1.概述概述Linux应用软件开发:应用软件开发: Linux开发具有活跃的开发环境,Linux开发工作一般是由多个Linux用户共同完成一个项目的。开发工作完成后,该软件就被放到Internet站点上,任何用户都可以访问和下载它。 大多数Linux软件是经过自由软件基金会提供的GNU公开认证授权的,因而通常被称作GNU软件。 GNU软件免费提供给用户使用,并被证明是非常可靠和高效的。一个完整的开发工具应该包括:编辑工具:vi编辑器编译工具:gcc调试工具: gdb配置、项目管理工具
4、2.1 Linux下下 c 程序开发程序开发函数库及系统头文件:集成开发环境IDEKylixKdevelopRHIDELinux 安装时完成了这些Linux下下 c 程序的开发过程:程序的开发过程:使用vi等编辑工具编写源程序保存为*.c使用gcc编译成二进制可执行文件./文件名 执行有问题可以用gdb进行调试一、编辑工具:一、编辑工具: 在Linux下编程,你不再拥有集成化环境,你可以使用类似于记事本的工具-经典的vi来编辑源程序。当然,还有更高档一些的,如joe、emacs等。总之,编辑程序与编译工作是分开的。 vi编辑器有三种工作模式:命令行模式插入模式底行模式编辑编辑 hello.c1
5、)命令行模式:)命令行模式: 用户在用vi编辑文件时,最初进入的一般模式,此时键盘输入当做命令。在该模式中可以进行光标移动、删除、复制、粘贴等操作,但是无法编辑文字。命命 令令功功 能能h h方向键,向左移动光标一个字符的位置,相当于键方向键,向左移动光标一个字符的位置,相当于键“”j j方向键,向下移动光标到下一行的位置,相当于键方向键,向下移动光标到下一行的位置,相当于键“”k k方向键,向上移动光标到上一行的位置,相当于键方向键,向上移动光标到上一行的位置,相当于键“”l l方向键,向右移动光标一个字符的位置,相当于键方向键,向右移动光标一个字符的位置,相当于键“”1G1G移动光标到文件
6、的第移动光标到文件的第1 1行行G G移动光标到文件的最后移动光标到文件的最后1 1行行光标命令光标命令命命 令令功功 能能NxNx(Expurgate)(Expurgate)删除从光标位置开始的连续删除从光标位置开始的连续N N个字符(并复制个字符(并复制到编辑缓冲区)到编辑缓冲区)NddNdd(Delete)(Delete)删除从光标位置开始的连续删除从光标位置开始的连续N N行(并复制到编辑行(并复制到编辑缓冲区)缓冲区)NyyNyy(Yank)(Yank)复制从光标位置开始的连续复制从光标位置开始的连续N N行到编辑缓冲区行到编辑缓冲区p p(Put)(Put)从编辑缓冲区复制文本到当
7、前光标位置(即粘贴)从编辑缓冲区复制文本到当前光标位置(即粘贴)u u(Undo)(Undo)取消上一次操作(即恢复功能)取消上一次操作(即恢复功能)编辑命令编辑命令2)插入模式:)插入模式:在该模式下,vi编辑器进入编辑状态:状态命令状态命令命命 令令功功 能能a a(Append)(Append)进入编辑状态,从当前光标之前的位置开始插进入编辑状态,从当前光标之前的位置开始插入键盘输入的字符入键盘输入的字符i i(Insert)(Insert)进入编辑状态,从当前光标之后的位置开始插进入编辑状态,从当前光标之后的位置开始插入键盘输入的字符入键盘输入的字符o o(Open)(Open)进入编
8、辑状态,并插入一新行,光标移到该新行进入编辑状态,并插入一新行,光标移到该新行的行首,以后键盘输入的字符将插入到光标位置的行首,以后键盘输入的字符将插入到光标位置ESCESC进入命令行模式进入命令行模式3)末行模式:)末行模式:在该模式下,vi编辑器实现文件的保存和退出。命命 令令功功 能能:q:q(Quit)(Quit)退出没有被修改的文件退出没有被修改的文件(若文件被修改了而没有保存,则此命令无效)(若文件被修改了而没有保存,则此命令无效):q!:q!强制退出,且不保存修改过的部分强制退出,且不保存修改过的部分:w:w(Write)(Write)保存文件,但不退出保存文件,但不退出:w!:
9、w!强制保存文件,但不退出强制保存文件,但不退出:wq / :x:wq / :x(Exit)(Exit)保存文件并退出保存文件并退出:x!:x!强制保存文件并退出强制保存文件并退出:w File:w File另存为另存为FileFile给出的文件名,不退出给出的文件名,不退出:w! File:w! File强制另存为强制另存为FileFile给出的文件名,不退出给出的文件名,不退出:r File:r File(Read)(Read)读入读入FileFile指定的文件内容插入到光标位置指定的文件内容插入到光标位置2、编译工具:、编译工具:gcc gcc是gnu推出的功能强大性能优越的多平台编译器
10、,gcc能将c、Fottran等语言源文件进行编译、连接生成可执行文件。gcc支持下面后缀名的文件: .c c语言源文件 .h c语言头文件 .i 已经预处理的源文件 .o 编译后的目标文件.s 汇编语言源代码文件gcc v 查询gcc的版本号Gcc编译过程编译过程 :预处理链接汇编组译源程序(*.c)可执行文件ELF格式预处理器汇编器组译器连接器.o目标文件gcc的使用格式如下:gcc options filenames 当使用gcc时,gcc会完成预处理、编译、汇编和连接。前三步生成目标文件,连接时,把生成的目标文件链接成可执行文件。gcc可以针对支持不同的源程序文件进行不同处理,文件格式
11、以文件的后缀来识别。gcc -o 目标文件名 源文件名(.c形式的文件)如 gcc o hello hello.c ./可执行文件名 进行执行文件gcc o test.o c test.c gcc c test.c 仅把源代码编译为目标代码而跳过连接,优点:当编译多个c程序时速度更快,易于管理。gcc o test test1.c test2.c test3.c 有多个源文件生成 testgcc c test.c -o test.o gcc g o hello hello.c 编译生成可执行连接文件hello同时生成供调试的信息。使用优化选项使用优化选项 当用gcc编译C代码时,它会试着用最少
12、的时间完成编译并且使编译后的代码易于调试. 易于调试意味着编译后的代码与源代码有同样的执行次序,编译后的代码没有经过优化。有很多选项可用于告诉gcc,在耗费更多编译时间和牺牲易调试性的基础上,产生更小更快的可执行文件。这些选项中最典型的是-O和-O2选项。-O选项告诉gcc对源代码进行基本优化。这些优化在大多数情况下都会使程序执行的更快。 -O2选项告诉gcc产生尽可能小和尽可能快的代码。-O2选项将使编译的速度比使用-O 时慢。但通常产生的代码执行速度会更快。 Gcc主要完成程序的编译和连接,任何一个源文件首先会生成中间目标文件,再由中间目标文件生成执行文件。GNU make 管理项目管理项
13、目1、包含多个源文件的项目在编译时都有长而复杂的命令行,每次都分别编译链该项目,比较麻烦。2、当某一个源文件被修改以后,则必须重新编译和链接,最后生成可执行文件。a.c b.c e.c f.c Makefilea 项目目录# make 有了Makefile文件,我们只用一个make命令就可以自动智能地根据当前的文件修改的情况编译所需要的文件和链接目标程序。 在执行make指令时makefile的默认文件名为GNUmakefile、makefile或Makefile,当然也可以在make的命令行中指定别的文件名。一、make的执行:#make f makefilename#make target
14、(目标文件)Makefile的文件的基本结构:的文件的基本结构:1、makefile 是一个文本形式的数据库文件,其中包含了一些规则告诉make处理哪些文件以及怎么处理这些文件。2、这些规则主要描述一些target目标文件是从哪些依赖文件产生的,以及用什么命令来执行该过程。依靠这些规则,make会对磁盘上的文件进行检查时间差,以便更新目标文件。3、目标文件不一定是最后的可执行文件,可以是任何中间文件,并可以做为其他目标文件的依赖文件。# 一个简单的一个简单的Makefile的例子(以的例子(以#开头的为注释行)开头的为注释行)test:prog.o code.ogcc o test prog.
15、o code.o prog.o:prog.c prog.h code.hgcc c prog.c o prog.o code.o:code.c code.hgcc c code.c o code.o clean:rm f *.o#make#make Makefile#make test命令行以tab键开始伪目标:#make clean例如 :用make编译hello.c 单一文件 对于一个有很多源文件的项目,当改变一个头文件的时候,由于所有的依赖关系都在Makefile里,因此不再需要记住依赖此头文件的所有源码文件,make可以自动的重新编译所有那些因依赖这个头文件而改变了的源码文件,如果需要
16、,再进行重新连接。 Makefile文件的简化:文件的简化:1、利用、利用Makefile中的自定义变量:中的自定义变量: Makefile里的变量就像一个环境变量。事实上,环境变量在make中也被解释成make的变量。这些变量对大小写敏感,一般使用大写宇母。几乎可以从任何地方引用定义的变量,变量的主要作用如下: a、保存文件名列表、保存文件名列表b、保存可执行命令名、保存可执行命令名c、保存编译器的参数、保存编译器的参数变量引用:变量引用:$VARNAME make解释规则时,VARNAME在等式右端展开为定义它的字符串。变量一般都在Makefile的头部定义。按照惯例,所有的Makefil
17、e变量都应该是大写。如果变量的值发生变化,就只需要在一个地方修改,从而简化了Makefile的维护。 现在利用变量把前面的现在利用变量把前面的Makefile重写一遍:重写一遍:OBJS=prog.o code.oCC=gcc test:$ OBJS $ CC o test $ OBJS prog.o:prog.c prog.h code.h$ CC c prog.c o prog.ocode.o:code.c code.h$ CC c code.c o code.o clean:rm f *.o 2、利用、利用Makefile中的其它变量:中的其它变量:一个C编译的具体命令将会是:$ CC
18、$ CFLAGS c $ -o $CFLAGS: c编译器的选项TARGET_ARCH: 目标机器的结构定义预定义变量预定义变量如:源程序为经过变量替换过后的makefile文件:3、利用、利用Makefile中的隐含规则:中的隐含规则: 现在利用变量把前面的现在利用变量把前面的Makefile重写一遍:重写一遍:OBJS=prog.o code.oCC=gcc test:$ OBJS $ CC o $ $prog.o:prog.c prog.h code.hcode.o:code.c code.hclean:rm f *.o 使用automake和autoconf产生Makefile 在开始
19、使用Automake和autoconf之前,请先确认系统已经安装以下的软件:GNU AutomakeGNU AutoconfGNU m4PerlGNU Libtool (如果你需要产生 shared library) 完成实验内容三、调试工具三、调试工具GDB: Linux系统中包含了GNU 调试程序gdb,它是一个用来调试C和 C+ 程序的调试器。可以使程序开发者在程序运行时观察程序的内部结构和内存的使用情况。gdb 所提供的一些功能如下:1、运行程序,设置所有的能影响程序运行的参数和环境;2、控制程序在指定的条件下停止运行;3、当程序停止时,可以检查程序的状态;4、修改程序的错误,并重新运
20、行程序; 5、动态监视程序中变量的值; 6、可以单步执行代码,观察程序的运行状态。 gdb的功能非常强大,到目前为止,gdb已能够支持Moduls-2、Chill、Pascal和FORTRAN程序的调试,但是调试这些语言的源程序时有一些功能还不能使用。 gdb程序调试的对象是可执行文件然而,并不是所有的可执行文件都可以用gdb调试。如果要让产生的可执行文件可以用来调试,需在执行gcc指令编译程序时,加上-g参数,指定程序在编译时包含调试信息。GDB命令的基本使用和应用命令的基本使用和应用1gdb基本命令基本命令:gdb filename gdb支持很多的命令且能实现不同的功能。这些命令从简单的
21、文件装入到允许你检查所调用的堆栈内容的复杂命令, 下面列出了在使用gdb 调试时会用到的一些命令。1)file命令:装入想要调试的可执行文件。 2)cd命令:改变工作目录。 3)pwd命令:返回当前工作日录。 4)run命令:执行当前被调试的程序。 5)kill命令:停止正在调试的应用程序。 6)list命令:列出正在调试的应用程序的源代码。 7)break命令:设置断点。 8)TbreakTbreak命令;设置临时断点。它的语法与break相同。区别在于用tbreak设置的断点执行一次之后立即消失。 9)watchwatch命令:设置监视点,监视表达式的变化。10)awatchawatch命
22、令:设置读写监视点。当要监视的表达式被读或写时将应用程序挂起。它的语法与watch命令相同。 11)rwatchrwatch命令:设置读监视点,当监视表达式被读时将程序挂起,等侍调试。此命令的语法与watch相同。 12)nextnext命令:执行下一条源代码,但是不进入函数内部。也就是说,将一条函数调用作为一条语句执行。执行这个命令的前提是已经run,开始了代码的执行。 13)stepstep命令:执行下一条源代码,进入函数内部。如果调用了某个函数,会跳到函数所在的代码中等候一步步执行。执行这个命令的前提是已经用run开始执行代码。 14)displaydisplay命令:在应用程序每次停止
23、运行时显示表达式的值。15)info breakinfo break命令:显示当前断点列表,包括每个断点到达的次数。 16)info filesinfo files命令:显示调试文件的信息。 17)info funcinfo func命令:显示所有的函数名。 18)info localinfo local命令:显示当前函数的所有局部变量的信息。 19)info prog命令:显示调试程序的执行状态。 20)print命令;显示表达式的值。 21)delete命令:删除断点。指定一个断点号码,则删除指定断点。不指定参数则删除所有的断点。 22)Shell命令:执行Linux Shell命令。 2
24、3)make命令:不退出gdb而重新编译生成可执行文件。 24)Quit命令:退出gdb。LINUX shell LINUX shell 编程编程变量变量特殊字符特殊字符条件判断结构与循环结构条件判断结构与循环结构函数的定义和使用函数的定义和使用Shell是一个作为用户与LINUX系统间接口的程序,它允许用户向操作系统输入需要执行的命令。shell编程语言如BASH、SH、TCSH、GAWK、Perl、Tcl和Tk都利用自己的解释器。用这些语言编制的文件,可以直接运行。编译器则不同,它将生成一个独立的二进制代码文件然后才可以运行。变量变量用户变量用户变量环境变量环境变量位置变量位置变量预定义变
25、量预定义变量用户变量的定义及其使用与所有的编程语言一样,shell也允许把值存在变量中,shell变量名以字母或下划线字符开始,由字母、数字或下划线组成要把值存入变量,只要写出变量名,或紧跟一个=,再加变量值即可例如:variable=value count=1在程序中使用变量的值时,要在变量名前面加上一个符号“$”。这个符号告诉Shell,要读取该变量的值。例如:echo $variable环境变量环境变量是一种特殊的变量,其特点为:它们可以由其他程序传递给脚本在脚本中被调用的任何程序都将继承环境变量可以像定义一个变量一样来设置环境变量,在标记它为环境变量时需要使用“ export ”命令应
26、用示例:$ export MYENV=1$ echo $MYENV使用“ set ”命令可以获取当前上下文中全部的变量 位置参数位置参数执行Shell脚本时可以使用参数。由出现命令行上的位置确定的参数称做位置参数。在sh中总共有十个位置参数,其对应的名称依次是$0,$1,$2,.$9。其中$0始终表示命令名或Shell脚本名,对于一个命令行,必然有命令名,也就必定有$0;而其它位置参数依据实际需求,可有可无。应用示例:编辑ison文件内容如下who | grep $1 执行:$ chmod +x ison $ ./ison bc shell将用bc代替$1,命令行变为:who | grep b
27、c shift命令shift命令的作用是把位置参数左移原来在$2中的内容赋给$1,$3中内容赋给$2,依此类推。原来$1中的值就丢失了。$#(参数变量的个数)也自动减1shift命令(二)编辑shiftdemo程序如下: echo $# $* shift echo $# $* shift echo $# $* shift echo $# $* 执行: chmod +x shiftdemo./ shiftdemo a b c预定义变量$# 变量用于存放命令行中所键入的参数个数shell程序测试这个变量确定用户输入的参数个数是否正确应用示例:编辑args文件内容如下: echo $# argume
28、nts passed echo arg 1= :$1: arg 2 =:$2: arg 3 =:$3: 执行: $ args a b c $ args a b $ args 从这个例子可以看到shell程序将命令行的参数个数传递给了$#变量 预定义变量$* 变量可以引用传递给程序的所有参数经常应用在参数不确定或者参数数目可变的程序中应用示例:编辑args2文件内容如下: echo $# arguments passed echo they are $* 执行 : $ chmod +x args2 $ arg2 a b c $ arg2 a b $ arg2 预定义变量$变量$变量和变量和$*变
29、量功能基本相同变量功能基本相同 改写改写args2程序如下:程序如下: echo $# arguments passed echo they are $预定义变量$? 变量每当程序执行完成后都会给系统返回一个退出状态。该状态是个数值,通常指示该命令运行是否成功。退出状态为0表示运行成功,非零表示运行失败。Shell自动将最后所执行命令的退出状态设置到shell变量 $? 中,可以用echo命令在终端上显示它的值应用示例$ who | grep bc $ echo $? $ who | grep 123 $ echo $? 特殊字符特殊字符 通配符通常的通配符有三种:* 星号,它匹配任意字符的0
30、次或多次出现。但注意,文件名前面的圆点(.)和路径名中的斜线(/)必须显示匹配。? 问号,它匹配任意一个字符。 一对方括号,其中有一个字符组。其作用是匹配该字符组所限定的任意一个字符。应该注意:字符 * 和 ?在一对方括号外面是通配符,若出现在其内部,它们就失去通配符的能力了。! 叹号,若它紧跟在一对方括号的左方括号之后,则表示不在一对方括号中所列出的字符。 特殊字符特殊字符 引号双引号” ”由双引号括起来的字符,除$、倒引号和反斜线()仍保留其功能外,其余字符通常作为普通字符对待。单引号 由单引号括起来的字符都作为普通字符出现。倒引号 反引号用于设置系统命令的输出到变量。shell 将反引号
31、中的内容作为一个系统命令,并执行其内容。反斜线转义字符,若想在字符串中使用反斜线本身,则必须采用()的形式,其中第一个反斜线作为转义字符,而把第二个反斜线变为普通字符。 条件判断条件判断语句是几乎所有编程语言中都有的语句,shell中有两种条件判断语句:if表达式case表达式 if表达式一般结构 if conmmand1 then elif command2 then else fi 这个ifthenelse表达式中的else和elif是可选部分。其中elif是else if得缩写,在ifthenelse表达式中这样的else if语句可以有多个。其中fi表示ifthenelse表达式的结束
32、。Bash支持此类表达式的多层嵌套。 其中command1需要执行并检测其退出状态,如果退出状态为0,则执行其后then与elif之间的语句,同理执行并检测command2的退出状态,并根据退出状态是否为0选择执行elif与else之间或else与fi之间的语句test命令shell有一条内部命令test,经常用来在if命令中测试一种或几种条件,其一般格式为: test expression 其中expression表示要测试的条件。test计算expression,若结果为真,其返回的退出状态为0,若结果为假,返回的退出状态就不为零应用示例:$ name=bc$ test “$name” =
33、 bc$ echo $?注意:test把所有操作数($name和bc)和操作符作为单独的参数分别对待,也就是说它们之间至少要有一个空白字符分隔 test命令(二)test命令的另一种格式shell程序使用test命令非常频繁,因此产生了另一种公认的命令格式: expression “”实际上就是命令的名字,同时要求在表达式的有一个配对的“”,在“之后和”之前都要有空格应用示例:$ name=bc$ “$name” = bc $ echo $? test命令(三)整数操作符test命令还有一类进行整数比较的操作符,见右表:例如:操作符“-eq”检测两个整数是否相等,如果有一个变量名为count,
34、想看看它的值是否为0,则可以写成: “$count” eq 0 操作符返回真(退出状态为0)的条件int1 eq int2int1 等于 int2int1 ge int2 int1 大于或等于 int2int1 gt int2int1 大于 int2int1 le int2 int1 小于或等于 int2int1 lt int2int1 小于 int2int1 ne int2int1 不等于 int2test命令(四)文件操作符test提供了一类问询文件状态的一元操作符,见右表:例如: -f /etc/fstab 检测fstab文件是否存在且是否为普通文件 if结构应用示例使用ifthenel
35、se结构编写一个判断命令行所传入参数大小的程序将所输入数值存放在位置参数$1中若$1100,则输出:the number is greater than 100若$1 do echo $i done可以看到终端上依次输出1、2、3 不带列表的for命令forfor命令也可以写成以下形式:命令也可以写成以下形式:for varfor vardo do command commanddone done shellshell也能认出这种少了也能认出这种少了inin的特殊格式,的特殊格式,shellshell会自动将命令行键入的所有参数依次组织会自动将命令行键入的所有参数依次组织成列表。成列表。应用示
36、例:应用示例: 编辑编辑fordemofordemo文件内容如下:文件内容如下:echo Number of arguments passed is $# echo Number of arguments passed is $# for argfor arg do do echo $arg echo $arg done done执行执行 : $ chmod +x fordemo: $ chmod +x fordemo $ ./fordemo a b c $ ./fordemo a b cwhile命令第二种循环命令是while,格式为:while command1 do command do
37、ne 先执行command1,并检测其退出状态,如果为0则执行do与done之间命令,再次检测直到command1退出状态不为0如果第一次执行command1时退出状态就不为0,那么do和done之间的命令可能根本不执行while命令应用示例while循环通常跟shift命令结合使用,以处理命令行中键入的参数个数可变的情况编写whiledemo程序如下: while “$#” -ne 0 do echo “$1” shift done执行: $ chmod +x whiledemo $ ./whiledemo a b cshift命令使位置变量向下移($2到$1,$3到$2), 并且$#递减。
38、until命令until命令跟while很像,区别在于只要在until后面的命令退出状态不为0,循环就一直执行下去,其格式为:until command1do commanddone跟while命令一样,如果第一次执行command1时返回的退出状态为0,do和done之间的命令可能 跟本不会执行。 until命令示例程序编辑untildemo程序如下: if $# -ne 1 then echo Usage:untildemo user exit 1fiuntil who | grep $1 /dev/nulldo sleep 10doneecho $1 has logged on执行: $
39、chmod +x untildemo $ ./untildemo bc $ ./untildemo 123结束进程:ctrl+Cbreak命令与continue命令break命令与continue命令与C中相应命令功能相同break命令只退出循环而不退出程序continue命令不退出循环,只跳过循环体后面的命令,而后循环像正常情况一样继续执行 函数的定义和调用和真正的编程语言一样, Bash 也有函数,虽然在某些实现方面稍有些限制. 一个函数是一个子程序,用于实现一串操作的代码块(code block),它是完成特定任务的黑盒子. 当有重复代码, 当一个任务只需要很少的修改就被重复几次执行时,
40、 这时你应考虑使用函数.其定义格式如下: funcname() command . command 函数被调用或被触发, 只需要简单地用函数名调用.简单函数的例子 #!/bin/bash fun () if -z $1 # 第一个参数是否长度为零第一个参数是否长度为零? then echo -Parameter #1 is zero length.- # 则没有参数传递进来则没有参数传递进来. else echo -Param #1 is $1.- fi funfun “hello”综合实验一综合实验一:清除清除log 文件文件 cleanlog.sh版本版本1 在一个最简单的例子中,一个sh
41、ell 脚本其实就是将一堆系统命令列在一个文件中。好处就是把所有命令都放在一个脚本中,不用每次都敲它们.这样,对于特定的应用来说,这个脚本就很容易被修改或定制。在这次练习中,我们编写一个最简单的脚本,其内容是清除/var/log/message和/var/log/wtmp中的内容,如下。 cd /var/log cat /dev/null messages cat /dev/null wtmp echo Logs cleaned up.综合实验一综合实验一:清除清除log 文件文件 cleanlog.sh版本版本2下面按照Shell编程的一些规则进行改良:在第一行添加一个Bash 脚本的正确的
42、开头部分,指定解释器为bash。使用变量指定/var/log目录,在后面使用这个变量。最后用exit正常退出。使用注释说明各部分的用法。 综合实验一综合实验一:清除清除log 文件文件#!/bin/bash# 一个Bash 脚本的正确的开头部分.# 要使用root 身份来运行.# 在此处插入代码,来打印错误消息,并且在不是root 身份的时候退出.LOG_DIR=/var/log# 使用变量比把代码写死的好.cd $LOG_DIRcat /dev/null messagescat /dev/null wtmpecho Logs cleaned up.“exit # 这个命令是一种正确并且合适的
43、退出脚本的方法.综合实验一综合实验一:清除清除log 文件文件cleanlog.sh版本版本3 现在,让我们来编写有真正意义的脚本:添加权限有关语句,判断执行脚本的是否根用户,如果不是则输出出错信息,退出。添加语句,判断是否有命令行参数,如果有,假设是n,在后面的清除log的时候保留最后的n行;如果没有,设n=50。你可以不断地找到新的方法来完善这个脚本,并提高效率。综合实验一综合实验一:清除清除log 文件文件#!/bin/bash# 说明:删除logfile 的脚本#LOG_DIR=/var/logROOT_UID=0 # $UID 为0 的用户才具有根用户的权限LINES=50 # 默认
44、的保存行数E_XCD=66 # 不能修改目录,与下面的E_NOTROOT相似,用于本脚本退出返回E_NOTROOT=67 # 非根用户# 一定要使用根用户来运行if $UID -ne $ROOT_UID then echo Must be root to run this script. exit $E_NOTROOTfi 综合实验一综合实验一:清除清除log 文件文件if -n $1 # 测试是否有命令行参数(非空).then lines=$1else lines=$LINES # 如果不在命令行中指定,使用默认fi cd $LOG_DIRif pwd != $LOG_DIR # 查看是否在
45、 /var/log目录中then echo Cant change to $LOG_DIR. exit $E_XCDfi# 在处理log file 之前,再确认一遍当前目录是否正确.tail -$lines messages mesg.temp # 保存log file 消息的最后部分.mv mesg.temp messages # 变为新的log 目录.cat /dev/null wtmpecho Logs cleaned up.exit 0 # 退出之前返回0,表示成功.综合实验二:找出死链接文件综合实验二:找出死链接文件 编写思路:判断是否有命令行参数,如果没有,那么就使用当前目录,否则
46、就使用传递进来的参数作为目录来搜索。建立函数linkchk,用来检查传进来的目录或文件是否是链接和是否链接到不存在的路径,即死链接。如果是死链,打印出它们的路径。如果传进来的目录有子目录,那么把子目录也发送到linkchk 函数中处理,也就是递归目录。对每个从脚本传递进来的参数,都调用linkchk 函数去处理,如果有参数不是目录,那就打印出错误消息和使用信息。1.Exit退出。综合实验二:找出死链接文件综合实验二:找出死链接文件#!/bin/bash# 说明:用来找出死链接文件并且输出它们的路径# 如果没对这个脚本传递参数,那么就使用当前目录.# 否则就使用传递进来的参数作为目录来搜索. $
47、# -eq 0 & directorys=pwd | directorys=$linkchk () for element in $1/*; do -h $element -a ! -e $element & echo $element -d $element & linkchk $element # -h是测试链接,-d是测试目录. done综合实验二:找出死链接文件综合实验二:找出死链接文件#对每个从脚本传递进来的参数,都调用linkchk 函数去处理#如果有参数不是目录,那就打印出错误消息和使用信息。for directory in $directorys; do if -d $directory then linkchk $directoryelse echo $directory is not a directory echo Usage: $0 dir1 dir2 . fidoneexit 0