LINUX实验指导书新.doc
Unix/Linux程序设计实验指导书实验1目的:练习vi编辑器以及X Window桌面的使用。需要的知识:第3章vi编辑器的使用和第4章建立快速链接的内容。题目:首先使用vi编辑器编辑一个c语言源程序hello.c,程序的功能为:接受用户输入的姓名,然后向屏幕输出一条语句“Welcome 姓名”。使用命令“gcc o hello hello.c”编译源程序,如果发现程序错误则需要反复使用vi修改源文件并且在修改后重新编译。最后在X Window的桌面上放置源程序hello.c的链接。实验步骤:步骤1:使用vi编辑文件hello.c#include <stdio.h>main()char name20;printf("Please input your name:");scanf("%s",name); /输入姓名printf("Welcome %s!n",name); /输出welcome 姓名return 0;步骤2:编译文件gcc o hello hello.c步骤3:如果有错误,再次使用vi修改hello.c的内容;然后再次编译。直至编译时不报任何错误。步骤4:在桌面建立链接:创建链接有如下两个方法:方法1:打开文件管理器,找到hello.c文件,单击鼠标右键,选择【创建链接】命令,则在文件管理器的窗口中出现一个图标,名字为“到的链接”,并且带一个小箭头符号。只要将该图标拖放到桌面,就可以建立到该项目的链接。方法2:选中hello.c文件,按住鼠标中键(三键鼠标)的滚轮键,拖放到桌面,当放开鼠标中键时,会弹出【移动到此处】、【复制到此处】、【在此处创建链接】等命令,选择【在此处创建链接】命令,就可以在桌面创建到该项目的链接。提示:本题用到了编译命令,题目中已经指出了该命令的使用方式,不要求理解每个项目的含义,在第12章会有具体介绍。实验2目的:练习存储设备的挂载以及编写shell程序将日常管理任务简化。需要的知识:第6章存储设备的挂载和第11章shell编程的内容题目:假设有一台Windows和Linux双启动的主机,Window有C、D两个分区,编写一个负责挂载的脚本程序mmnt,参数为cdrom时挂载光驱、参数为floppy时挂载软驱、参数为C(大小写都可以)时挂载Windows的C盘(有中文字符),参数为D(大小写都可以)时挂载Windows的D盘(有中文字符),参数为其它时显示帮助信息:Usage: mmnt cdrom|floppy|C|c|D|d编写一个负责卸载的脚本程序umnt,完成相应的存储设备的卸载,参数的含义同上。实验步骤:步骤1:以root身份登录Linux系统,使用fdisk l命令查看系统连接的存储设备,主要查看windows的两个分区的名称,比如hda3, hda5等。步骤2:建立挂载点:一般地,光驱和软驱的挂载点/mnt/cdrom、/mnt/floppy由系统缺省建立,查看一下这两个目录是否存在,如果没有,手工建立;此外使用mkdir命令建立windows的C盘和D盘的挂载点:mkdir /mnt/C mkdir /mnt/D步骤3:编写/etc/fstab文件,编辑或者添加如下4行:/dev/hda3/mnt/Cvfatnoauto,iocharset=cp9360 0/dev/hda5/mnt/Dvfatnoauto,iocharset=cp9360 0/dev/cdrom /mnt/cdromiso9660noauto,owner,ro0 0/dev/fd0 /mnt/floppyautonoauto,owner0 0步骤4:编写shell脚本mmnt#!/bin/shcase $1 incdrom) mount /mnt/cdrom ;floppy) mount /mnt/floppy ;C|c) mount /mnt/C ;D|d) mount /mnt/D ;*) echo “Usage: mmnt cdrom|floppy|C|c|D|d”;esac步骤5:编写shell脚本umnt#!/bin/shcase $1 incdrom) umount /mnt/cdrom ;floppy) umount /mnt/floppy ;C|c) umount /mnt/C ;D|d) umount /mnt/D ;*) echo “Usage: mmnt cdrom|floppy|C|c|D|d”;esac步骤6:使脚本mmnt和umnt可执行chmod +x mmntchmod +x umnt提示:此实验可以分两步,学完第6章后完成步骤1到步骤3,使用系统命令mount和umount测试自己的设置,学完第11章shell编程之后完成最后几步。实验3目的:练习网络服务的配置与管理。需要的知识:第7章网络配置、第8章网络服务器的配置和使用。题目:某局域网()具有3台安装了Linux系统的计算机,分别用于提供WWW、FTP和DNS服务,要求:设计分配IP地址和主机名,配置三种服务器,使得可以通过域名访问网络服务。实验步骤:步骤1:设计分配各主机的IP地址和域名,假设三台主机分别为A、B、C,可以如下分配IP地址和域名:主机IP主机名域名A.192.168.1.10wwwB192.168.1.11ftpC192.168.1.12dns步骤2:构建WWW服务器1. 在A主机中安装最新版的Apache服务器软件2. 配置Apache3. 在其主文档目录中建立web主页4. 启动Apache服务器5. 在本机中测试服务器与网页是否正常运行步骤3:构建FTP服务器1. 在B主机中安装最新版的vsFtpd服务器软件2. 配置vsFtpd,按需求建立不同形式的登录方式3. 在对应的文件目录中复制有关文件资料4. 启动vsFtpd服务器5. 在本机中测试服务器是否正常运行步骤4:构建DNS服务器1. 在C主机中安装最新版的bind服务器软件2. 配置系统,建立主机与IP地址的映射。3. 启动bind服务器4. 在本机中测试服务器是否正常运行步骤5:设置客户机1. 在客户机中修改本地DNS服务器的设置。2. 打开网页浏览器,在地址栏中输入: ,检验是否连接WWW服务器3. 打开网页浏览器,在地址栏中输入:ftp:/ ,检验是否连接FTP服务器实验4目的:了解Linux下的用户管理机制,熟练掌握Linux下的C语言编程以及gcc工具的使用。需要的知识:C/C+语言的基本技能、第9章用户管理知识、第12章gcc的使用。题目:Linux系统管理的一项重要工作就是用户管理。用户的口令以加密的形式存储在口令文件/etc/shadow中。弱口令就是很容易被猜出来的口令,比如与用户名相同的口令、象“、admin、computer”这类常用的口令等,口令字典是指将一些常用弱口令写在一个文本文件。管理员应该定期检测系统中是否存在弱口令。试编写一个c语言程序,主动检查自己的Linux系统中是否存在弱口令。实验步骤;步骤1:分析/etc/shadow文件的格式。可以查看自己的系统中该文件的格式,参照9.1节的介绍,该文件的每一行对应一个用户,下面是一个系统中/etc/shadow文件的实例:user1:$6$DVLiBPZG$IrR9o0KpjtGQOj7I5WvgxQ.jMQ/Qzl3cJp4w0loUMZs4xQSQ8wkdIK7Sdkdk2pMXeAfOYq9O07r/QuDdJ8f3c0:14748:0:99999:7:user2:$6$RR8pmW2aerqIkySA$PcMV7/Z37QFCe9hJrf1rlUjPTAOdmKsW/mfG40V343kxG1QNsWWI7mdzl.50SCJpI4TQ/x4z4zsCoiA48EjAn1:14748:0:99999:7:user3:$6$oGG.739y$9ysybZ.VaTQ7dmR1zyz1vR8OiCUSCnzqnFd1PUYvedJMt.t6ElISwUohtOAlqAuT7.sPDjfy.bKCKar82mSp2.:14748:0:99999:7:user4:$6$AJerec5o$bwgJnQ0mTPzZMRCZYuivQVsWtD9mlh3.pWK2tR2pZPr4NzSlqk6hhFq3/zfWJXQCNmXJTlZhubwwW9x6a8mtM0:14748:0:99999:7:user5:$6$o1DA6WOiXtme7Zsw$Lj6bXgI5c5Kg/GewGWYv.4pQ0fD/AnSYEjMvmXxuvzEK3IYhNYjnTIEnTPQr9pZIMzatBOyrC4FgBjYtR5R.n1:14749:0:99999:7:user6:$6$UUXC4WKX$mKyl/32n7xrU1ChPIJYs2gwYuEoObdkNsPcVhxR22xFBIspNjVIfRv4FgoDWsJIxy4TZ.ci70MeDvDMEeExXL0:14749:0:99999:7:步骤2:了解Linux下口令加密的原理口令的加密是使用Linux系统的crypt函数。使用info或者man可以了解该命令的工作原理:Red Hat Linux9中使用的MD5算法,在Fedora 10中默认使用了SHA-512算法。它使用一个字符串作为salt(翻译成盐),长度是8到16个字节,将用户输入的口令key进行加密。函数crypt(key,salt)的结果存入/etc/shadow文件的第2个域。这个域前面$6$salt$就是crypt函数的salt参数。当给用户设置口令时,salt是由系统随机选取的,因此即使是相同的key,因salt不同而第二个域的值也不同。当用户在登录中输入自己的口令时,系统使用crypt进行同样的计算,如果所得的结果与/etc/shadow中存储的一致,则接受用户的登录。步骤3:什么是弱口令:弱口令就是很容易被猜出来的口令,比如admin,guest,fllower,,beauty等等。在口令猜测或者破解时,一般不会穷尽所有字符的所有排列组合,一般都使用一个弱口令字典,字典中包含了常被用来作为口令的字符串。可以到网上查找口令字典。步骤4:弱口令检查的原理对每个用户而言,逐个将那些经常被用来作为口令的词,使用crypt做运算,如果运算结果与/etc/shadow所存储的加密后的口令相同,则口令被猜出来。步骤5:用c语言编写实现口令检查的程序关键部分的代码如下: 通过读取/etc/shadow的每一行,获得一个关于用户的数据结构,存放在pwd中。char saltstr21; /存放种子,最多是20个字节 bzero(saltstr,sizeof(saltstr);/将变了全部清0strncpy(saltstr,pwd->pw_passwd,20);/将salt取出,最多20个字节,以其中$作为边界 cp = crypt (guess, saltstr); /调用crypt加密函数 if (strcmp (cp, pwd -> pw_passwd) /与口令文件中存储的信息比较 return (0); /若不一致则返回printf ("Warning! Password Problem: Guessed:t%stpasswd: %sn",pwd -> pw_name, guess); /找到口令,显示口令步骤6:编译程序gcc o passchk pass.c lcrypt 其中-o选项指定编译后的可执行文件名,-l选项表示使用crypt函数库步骤7:执行口令检查程序 ./passchk P myshadow w words p 其中passchk是可执行文件名,myshadow是口令文件,如果没有-P选项,则缺省使用Linux系统的/etc/shadow文件,words是存放弱口令的口令字典文件,选项-p表示将破解后的口令输出。 实验5目的:练习Gtk+编程和gcc工具的使用。需要的知识:C/C+语言的基本技能、第12章gcc的使用与开发、第13章Gtk+图形程序设计;题目:日志的查询统计是系统管理的一项重要任务。Linux系统的日志以文本文件的形式存在,使用Gtk+编写一个图形界面的系统日志管理器(针对日志文件/var/log/messages*),它可以列出系统当前的日志个数(/var/log/message, /var/log/message.1, /var/log/message.2,共多少个),对指定的日志文件可以查询哪些条目含有(include)指定信息(比如含有“succeed”的条目),哪些不含有(exclude)指定信息。图5-1是一个示例程序的效果图:l 数字1为一个标签,显示日志文件的数量;l 显示succeed的单行文本框用来输入包含的指定信息;l 显示kernel的单行文本框用来输入不包含的指定信息;l 点击标签为“/var/log/messages”的按钮后,可以选择日志文件;l 点击标签为“View”的按钮后,可以根据输入的条件查看日志内容;下面的多行文本框用来显示日志内容。图5-1程序效果图程序目录结构如Error! Reference source not found.所示:图 5 1程序目录结构图其中:l 文件main.cpp:为程序的主函数所在文件,通过对其它文件的调用启动和结束程序;l 目录core:其中的文件分为三组,每一组的一个.h文件和一个.cpp文件共同定义了一个类,其中的类名和对应的文件名相同。目录core下定义的类实现了与界面无关的大部分功能。包括:检索日志文件个数、检索和根据条件过滤日志内容等作用。l 目录widgets:包括两个文件,实现程序界面,并和目录core下的类交互,利用图形界面接收用户的输入和显示程序的运行结果。实现步骤:1) 根据目录结构创建目录和文件;为了方便组织程序代码,可以将本实验的代码放到单独的目录下。因此,先建立一个目录作为项目的根目录,本例中根目录命名为:ViewLogGtk。· 在当前工作目录下,建立项目根目录:mkdir ViewLogGtk· 进入根目录:cd ViewLogGtk· 创建空白主程序文件:touch main.cpp· 创建目录core:mkdir core· 创建目录widgets:mkdir widgets· 进入目录core:cd core· 创建目录core下的空白程序文件:touch Util.htouch Util.cpptouch LogRecord.htouch LogRecord.cpptouch LogContent.htouch LogContent.cpp· 进入目录widgets:cd ./widgets· 创建目录widgets下的空白程序文件:touch widget.htouch widget.cpp· 目录文件创建完毕。Util.h1#ifndef UTIL_H2#define UTIL_H3class Util4 public: 5 static int queryFileCount(const char* dir,const char* keyword);6 ;7#endif2) 编辑并实现代码文件:这里仅给出关键部分的代码。Util.h定义了类Util: 类Util中只定义了一个静态的方法:queryFileCount()用来查询指定目录下指定类型的文件个数。其中方法的第一个参数为指定查询文件的目录,第二个参数为指定文件名中包含的字符串。对于本例,第一参数固定的传入字符串“/var/log/”,第二个参数固定的传入字符串“message”,即查询目录/var/log/下文件名中包含message的文件。LogRecord.h1#ifndef LOGRECORD_H2#define LOGRECORD_H3#include <string>4using namespace std;5class LogRecord67private:8string contents;9public:10LogRecord(char* contents);11LogRecord(void);12string getContents(void);13LogRecord(string contents);14;15#endif类LogRecord代表日志中每一行。构造函数LogRecord(char*)和LogRecord(string)分别提供了利用char*类型和string类型形成日志行记录的两种方法。其中私有字符串成员contents储存日志记录的一行字符串,公有方法getContents()对外提供了一个获得字符串记录内容的接口。LogContent.h1#ifndef LOGCONTENT_H2#define LOGCONTENT_H3#include<string>4#include<list>5#include"LogRecord.h"6using namespace std;7class LogContent89private:10string contains; /记录中需要出现的关键字11string notcontains; /记录中不能出现的关键字12string file_name; /记录文件名13list<LogRecord> records; /符合过滤条件的记录集合14public:15LogContent(void);16LogContent(void);17void setFilter(string contains, string not_contains); /设置过滤条件18void set_file_name(string file_name); /设置检索的日志记录文件名19int fill_records(void); /根据文件、过滤条件填充记录集合20private:21int filter_record(LogRecord record); /判断记录行是否满足过滤条件22public:23list<LogRecord> get_records(void); /得到记录集合24;25#endif 类LogContent是检索日志文件、过滤日志行记录的主要场所。它利用setFilter(string,string),设置日志行记录中必须出现的关键字和必须不出现的关键字,利用set_file_name(string)设置日志文件的文件名称。检索关键字和日志文件设置完毕后,就可以利用fill_record()检索日志文件并填充日志行记录集合。填充完毕,可以使用方法get_recore()得到检索的结果。widget.h1#ifndef WIDGET_H2#define WIDGET_H3#include <string>4#include <iostream>5#include <gtk/gtk.h>6#include "LogContent.h"7using namespace std;8/fields9string file_name; /日志文件名10string kw_contains; /日志过滤条件中,需要包含的关键字11string kw_not_contains; /日志过滤条件中,不需要包含的关键字12int file_num; /指定目录下,特定文件的个数13GtkWidget* window; /主界面窗口14GtkWidget* lbl_file_num; /文件个数标签15GtkWidget* btn_choose_file; /选择文件按钮16GtkWidget* btn_view; /查看日志文件按钮17GtkWidget* ety_contains; /包含关键字输入文本框18GtkWidget* ety_not_contains; /不包含关键字输入文本框19GtkWidget* scroll_win; /用于显示日志的滚动窗口20GtkWidget* text; /显示日志多行文本框21GtkWidget* table; /用于摆放界面控件的表格布局22GtkWidget* dialog; /用于选择文件的对话框23GtkTextBuffer* buf; /显示日志的文字缓冲区24LogContent logContent; /完成文件检索、过滤填充的对象25/functions26void layout_ctrls(); /放置界面控件27void onChooseFile(GtkWidget* sender,gpointer data); /点击选择文件时的动作28void onView(GtkWidget* sender,gpointer data); /点击查看日志文件按钮的动作29void onFileSelect(GtkWidget* widget,GtkFileSelection* fs);/在对话框中选择文件的动作30void dispLogNum(int num); /显示日志文件个数31void connectHandlers(); /关联界面控件和相应的事件处理程序32#endif33#ifndef WIDGET_Hwidget.h声明了与程序界面直接相关的变量和方法,其中的方法的实现部分即函数体在widget.cpp中。两个文件相结合,完成了程序界面的生成、界面控件元素和事件处理函数的关联、接收用户输入并反馈处理结果的功能,是用户之间交互的部分。main.cpp1#include "widget.h"2#include "widget.cpp"3int main(int argc, char* argv)4 gtk_set_locale();5 gtk_init(&argc,&argv);6 layout_ctrls(); /调用布局界面的方法,形成并显示图形用户界面7 gtk_main();8 return 0;9 main.cpp功能代码都很简单,除了常规的初始化程序环境的功能外,唯一特殊的就是调用widget.h中定义的layout_ctrils()方法,形成并显示界面。3) 编译程序:程序包含文件较多,可以采取分步编译的方式。由于代码中用到了类、string等概念,是C+风格的代码,因此,编译时采用g+命令,而不是gcc命令。g+命令和gcc命令使用方法参数信息都相同,g+用于C+风格代码而gcc常用于c风格的代码。假设当前工作目录为项目的根目录即ViewLogGtk目录下,首先编译core目录下文件:· 编译类Util:g+ -c core/Util.cpp· 编译类LogRecord:g+ -c core/LogRecord.cpp· 编译类LogContent:g+ -c core/LogContent.cpp然后,编译main.cpp和widgets目录下的文件:· g+ -c main.cpp -Icore -Iwidgets pkg-config gtk+-2.0 -cflags -libs 由于widges目录下的文件涉及到了Gtk+的界面部分,因此,在编译时需要加入pkg-config .参数。最后,将得到的目标文件编译为统一的可执行文件,并将可执行文件命名为ViewLog,命令:· g+ LogRecord.o LogContent.o Util.o main.o -o ViewLog -Icore -Iwidgets pkg-config gtk+-2.0 -cflags -libs 4) 运行程序:· ./ViewLog实验6目的:练习Qt编程和qmake工具的使用。需要的知识:C/C+语言的基本技能、第14章Qt图形程序设计;题目:日志的查询统计是系统管理的一项重要任务。Linux系统的日志以文本文件的形式存在,使用Qt编写一个图形界面的系统日志管理器(针对日志文集/var/log/messages*),它可以列出系统当前的日志个数(/var/log/message, /var/log/message.1, /var/log/message.2,共多少个),对指定日志文件可以查询哪些条目含有(include)指定信息(比如含有“succeed”的条目),哪些不含有(exclude)指定信息。图61Error! Reference source not found.是一个示例程序的效果图:l 数字1是一个Qt的LCD数码显示控件;l 显示succeed的单行文本框用来输入包含的指定信息;l 显示kernel的单行文本框用来输入不包含的指定信息;l 点击标签为“/var/log/messages”的按钮后,可以选择日志文件;l 点击标签为“View”的按钮后,可以根据输入的条件查看日志内容;l 下面的多行文本框用来显示日志内容。图6-1程序效果图程序的目录结构如图6-2所示:图6-2程序目录结构图其中:l 目录core及其中文件的功能和实验5相同;l 目录widgets及其中的文件功能和实验5相同,由于本实验不采用Gtk界面工具包,而是采用Qt界面工具包。因此,widgets目录下两个文件共同定义了一个类QtLogViewer,该类派生字QWidget类,完成图形界面构成、交互的功能;l 文件main.cpp:为程序的主函数所在文件,通过对QtLogViewer的调用,完成程序的启动、交互和退出。实现步骤:1) 根据目录结构创建目录和文件:为了方便组织程序代码,可以将本实验的代码放到单独的目录下。因此,先建立一个目录作为项目的根目录,本例中根目录命名为:ViewLogQt。· 在当前工作目录下,建立项目根目录:mkdir ViewLogQt· 进入根目录:cd ViewLogQt· 创建空白主程序文件:touch main.cpp· 创建目录core:mkdir core· 创建目录widgets:mkdir widgets· 进入目录core:cd core· 创建目录core下的空白程序文件:touch Util.htouch Util.cpptouch LogRecord.htouch LogRecord.cpptouch LogContent.htouch LogContent.cpp· 进入目录widgets:cd ./widgets· 创建目录widgets下的空白程序文件:touch QtLogViewer.htouch QtLogViewer.cpp· 目录文件创建完毕。2) 编辑文件:这里仅给出关键部分的代码。也可以参考实验5的代码。QtLogViewer.h1#ifndef QTLOGVIEWER_H2#define QTLOGVIEWER_H3#include <qlcdnumber.h>4#include <qlabel.h>5#include <qlineedit.h>6#include <qtextedit.h>7#include <qpushbutton.h>8#include <qlayout.h>9#include <string>10#include "LogContent.h"11using namespace std;12class QtLogViewer:public QWidget13Q_OBJECT14private:15string file_name; /记录文件名16string kw_contains; /日志过滤条件中,需要包含的关键字17string kw_not_contains; /日志过滤条件中,不需要包含的关键字18int file_num; /指定目录中,特定日志文件的个数19QLCDNumber* lcd_file_num; /用于显示文件个数的数码显示器20QLabel* lbl_file_name;21QLineEdit* le_contains; /包含关键字输入文本框22QLineEdit* le_not_contains; /不包含关键字输入文本框23QTextEdit* te_logs; /显示日志的多行文本框24QPushButton* btn_choose_file; /选择文件按钮25QPushButton* btn_view; /查看日志按钮26QGridLayout* grid; /摆放界面控件的表格布局27 LogContent log; /检索、过滤并填充日志记录集合的对象28public:29QtLogViewer( QWidget *parent=0, const char *name=0 );30public slots: /定义的信号槽31void onChooseFile(); /选择文件按钮的事件处理函数32void onView(); /查看日志条目按钮的事件处理函数33private:34void init(); /初始化界面和关联事件处理函数35int getFilesNumer(); /查询日志文件个数36string getFileName(); /检索日志文件名称37;38#endifQtLogViewer派生自QWidget,集成了程序中所有的界面控件,并完成界面事件及其处理函数之间的关联。通过对LogContent的引用(引入log对象)组合进来了记录检索、过滤和填充的功能。main.cpp1#include <qapplication.h>2#include "QtLogViewer.h"3int main(int argc, char *argv)4QApplication app(argc, argv);5QtLogViewer viewer;6app.setMainWidget(&viewer);7viewer.show();8return app.exec();9main.cpp功能代码都很简单,除了常规的初始化程序环境的功能外,唯一特殊的就是将QtLogViewer设为程序的主界面,利用QtLogViewer形成并显示界面。3) 编译文件:利用qmake功能编译程序,首先创建qmake的工程文件,这里将工程文件命名为LogViewer.pro:l 生成项目文件,在项目根目录(ViewLogQt)下运行:qmake -project -o LogViewer.prol 生成Makefile:qmake o Makefile LogViewer.prol 生成程序:make4) 运行程序:l ./LogViewer提示:由于目录core下的程序代码采用标准C+规范而没有用到Gtk+或者Qt的扩展功能。因此,可以重用实验5中core目录下的代码,即,本实验core目录下的代码和实验5中core目录下的代码相同。