本系列文章阐释AIX中对象数据库管理器(Object Database Manager)的结构,操作 ODM 数据库的命令,工具,以及 ODM 的一些实际应用举例。第 2 部分向您详细介绍 ODM 的命令以及一些关于 ODM 的实际应用中的例子,即带您实践在本系列文章的第 1 部分中学习到的所有关于 ODM 的知识。要了解关于ODM的详细信息,请阅读本系列文章的第 1 部分:ODM的基本组件,ODM负责的数据,ODM数据库文件和ODM数据库的对象类
ODM数据库中存放着系统中的重要信息,在系统出现故障时,如果对ODM数据库进行直接的维护,则有利于问题的解决,也方便查出问题出现的原因所在。在ODM数据库可以通过手工方式进行维护,AIX提供了一些维护命令,下面介绍这些命令的作用和用法。
odmadd | 添加对象到对象类。odmadd命令使用一个ASCII码节文件作为输入并将在节文件中发现的ODM对象组织到ODM对象类。 |
odmchange | 改变指定的ODM对象类中指定的ODM对象。 |
odmcreate | 创建空的对象类。odmcreate命令使用描述对象类的ASCII码文件作为输入并产生应用访问该对象类中的对象时使用的C语言文件(.h和.c文件)。 |
odmdelete | 从ODM对象类中删除ODM对象。 |
odmdrop | 删除整个ODM对象类。 |
odmget | 得到对象类的信息并将对象信息变成odmadd命令格式。 |
odmshow | 显示ODM对象类的描述。odmshow命令使用对象名称作为输入并将对象信息变成odmcreate命令格式。 |
这些ODM命令顾名思义,接近关系型数据库的DML、DDL、DCL语言,非常容易理解。
注意:ODM命令应该仅在传统的系统维护方式如SMIT无效时才能被使用。对于一个刚入门的系统管理员,建议在使用这些命令前要多加阅读和练习。对这些命令使用不正确可能导致系统不可用。一般ODM主要是针对有相当AIX系统管理经验的系统管理员来使用的,主要运用于复杂的Trouble Shooting,或Problem Determination。ODM数据库为AIX实现许多先进的功能提供了一块重要的基石。
在使用ODM命令之前,首先检查$ODMDIR环境变量设置是否正确(AIX默认已经设置好了此环境变量),方法如下:
# echo $ODMDIR /etc/objrepos |
如果您的系统没有设置这个环境变量,请自行设置,方法如下:
# export ODMDIR=/etc/objrepos |
odmcreate命令以描述用户希望在特定的应用程序中使用的对象的 ASCII 文件为输入。产生 .c (源)和 .h(包含)文件,对于 ODM 应用程序开发和创建空的对象类是必要的。它的命令格式如下:
odmcreate [ -p ] [ -c | -h ] ClassDescriptionFile |
ClassDescriptionFile 参数指定了包含一个或多个对象类的描述的 ASCII 文件。ClassDescriptionFile 文件的缺省后缀是 .cre。 如果在 odmcreate 命令中没有指定后缀,那么附加一个.cre 后缀。文件能够有 C 语言注释,如果运行时带有 -p 标志,并能预先包含 #define 和 #include 行,这些可以被预处理的,如果在文件中使用了 -p 标志运行 C 语言预处理器。
odmcreate 命令的输出是 .h 文件(一个包含文件),它包含了定义在 ASCII ClassDescriptionFile 文件中的对象类的 C 语言定义。结果包含文件使用在访问存储在 ODM 中对象的应用程序中。odmcreate 命令也产生需要编译和绑定在应用程序中的 .c 文件。 .c 文件包含在运行时由 ODM 内部使用的结构和定义。
如果使用-c参数,只创建空的对象类;不生成 C 语言 .h 和 .c 文件。
如果使用-h参数,只生成 .c 和 .h 文件;不创建空类。
如果使用-p参数,对 ClassDescriptionFile 文件运行 C 语言预处理器。这时ClassDescriptionFile 文件中就可以包含C语言的注释,例如可以包含#define 和 #include等关键字。
注意: ODM 数据库是 32 位的数据库。长型当在类描述文件中使用时,它是 32 位的数据项。长型 64 或整型 64 当在类描述文件中使用时,它是 64 位的数据项。生成的文件对于 32 位和 64 位应用程序具有相同功能。
odmcreate命令举例
假定存在 ClassDescriptionFile 文件,命名为 MyObjects.cre ,下列命令创建对象类:
odmcreate MyObjects.cre
以下是 MyObjects.cre 源文件和结果 .h 文件:
/* 这是一个示例 odmcreate 输入文件 */ * MyObjects.cre * An input file for ODM create utilities. * Creates three object classes: * Friend_Table * Enemy_Table * Fictional_Characters class Friend_Table { char Friend_of[20]; char Friend[20]; }; class Enemy_Table { char Enemy_of[20]; char Enemy[20]; }; class Fictional_Characters { char Story_Star[20]; char Birthday[20]; short Age; link Friend_Table Friend_Table Friend_of Friends_of; link Enemy_Table Enemy_Table Enemy_of Enemies_of; method Do_This; }; * End of MyObjects.cre input file for ODM create utilities. * |
按照上面文件所定义的结构创建新对象类,运行下面的命令生成头文件 file MyObjects.h。
# odmcreate FineName.cre
* MyObjects.h * The file output from ODM processing of the MyObjects.cre input * file. Defines structures for the three object classes: * Friend_Table * Enemy_Table * Fictional_Characters #include <odmi.h> struct Friend_Table { long _id; * unique object id within object class * long _reserved; * reserved field * long _scratch; * extra field for application use * char Friend_of[20]; char Friend[20]; }; #define Friend_Table_Descs 2 extern struct Class Friend_Table_CLASS[]; #define get_Friend_Table_list(a,b,c,d,e) (struct Friend_Table * ) odm_get_list (a,b,c,d,e) struct Enemy_Table { long _id; long _reserved; long _scratch; char Enemy_of[20]; char Enemy[20]; }; #define Enemy_Table_Descs 2 extern struct Class Enemy_Table_CLASS[]; #define get_Enemy_Table_list(a,b,c,d,e) (struct Enemy_Table * ) odm_get_list (a,b,c,d,e) struct Fictional_Characters { long _id; long _reserved; long _scratch; char Story_Star[20]; char Birthday[20]; short Age; struct Friend_Table *Friends_of; * link * struct listinfo *Friends_of_info; * link * char Friends_of_Lvalue[20]; * link * struct Enemy_Table *Enemies_of; * link * struct listinfo *Enemies_of_info; * link * char Enemies_of_Lvalue[20]; * link * char Do_This[256]; * method * }; #define Fictional_Characters_Descs 6 extern struct Class Fictional_Characters_CLASS[]; #define get_Fictional_Characters_list(a,b,c,d,e) (struct Fictional_Characters * )odm_get_list (a,b,c,d,e) * End of MyObjects.h structure definition file output from ODM * processing. |
odmadd 命令以一个或多个InputFile 文件为输入,并且添加对象到带有节文件数据的对象类中。每个 InputFile 文件是 ASCII 文件,包含有描述要添加到对象类中的对象的数据。如果没有指定文件,从标准输入中获取输入。
下面是它的格式:
odmadd [ InputFile ... ]
要添加的类在 ASCII 输入文件中指定。文件的常规格式如下:
class1name: descriptor1name = descriptor1value descriptor2name = descriptor2value descriptor3name = descriptor3value class2name: descriptor4name = descriptor4value .. |
输入文件能够包含 \ (反斜杠),它的处理和在 C 语言中一样。输入文件中字符串和方法的值必须用 " " (双引号)括起来。描述符值能够跨越多行。
odmcreate命令举例
ASCII 输入文件MyObjects.add由 odmadd 命令使用,如下所示:
# odmadd MyObjects.add
* MyObjects.add * An input file for ODM add utilities. * Populates three created object classes: * Friend_Table * Enemy_Table * Fictional_Characters Fictional_Characters: Story_Star = "Cinderella" #a comment for the MyObjects.add file. Birthday = "Once upon a time" Age = 19 Friends_of = "Cinderella" Enemies_of = "Cinderella" Do_This = "echo Cleans house" Fictional_Characters: Story_Star = "Snow White" Birthday = "Once upon a time" Age = 18 Friends_of = "Snow White" Enemies_of = "Snow White" Do_This = "echo Cleans house" Friend_Table: Friend_of = "Cinderella" Friend = "Fairy Godmother" Friend_Table: Friend_of = "Cinderella" Friend = "mice" Friend_Table: Friend_of = "Snow White" Friend = "Sneezy" Friend_Table: Friend_of = "Snow White" Friend = "Sleepy" Friend_Table: Friend_of = "Cinderella" Friend = "Prince" Friend_Table: Friend_of = "Snow White" Friend = "Happy" Enemy_Table: Enemy_of = "Cinderella" Enemy = "midnight" Enemy_Table: Enemy_of = "Cinderella" Enemy = "Mean Stepmother" Enemy_Table: Enemy_of = "Snow White" Enemy = "Mean Stepmother" * End of MyObjects.add input file for ODM add utilities. * |
odmget 命令以搜索规则和对象类列表为输入,从指定的对象类中检索选定的对象,并写 ASCII odmadd 输入文件到标准输出。
下面是它的命令格式:
odmget [ -q Criteria ] ObjectClass ...
其中,-q Criteria指定用于从对象类中选择对象的搜索标准。Criteria是一个用双引号括起来的字符串,类似于SQL语言的查询条件,符合条件的纪录就会显示出来。如果没有指定标准(没有 -q 标志),检索对象类中的所有对象。
与SQL语句类似,Criteria参数指定的查询条件可以使用关系运算符和布尔运算符,象=,!=,>,>=,<,<=,like,and等。
下面是一些使用运算符的例子:
Name like '?B?' ? 表示一个字符 Name like '*ot*' * 表示0到多个字符 Name like '[ST]*' [ST]* 表示以"S"或"T"开头的任意多个字符串 Name like '[AD-GST]*' D-G表示范围,可以是D、E、F、G(从D到G)中任一字符。 Name like '[!ST]*' [!ST]*表示不以"S"或"T"打头的任意字符串 |
从PdAt对象类查找uniquetype为"tape/scsi/8mm",而且attribute为"block_size"的所有对象:
odmget命令举例:
# odmget -q "uniquetype=tape/scsi/8mm and attribute=block_size" PdAt
bash-3.00# odmget -q "uniquetype=tape/scsi/8mm and attribute=block_size" PdAtPdAt: uniquetype = "tape/scsi/8mm" attribute = "block_size" deflt = "1024" values = "0-245760,1" width = "" type = "R" generic = "DU" rep = "nr" nls_index = 6 |
odmdelete命令给定了要从中删除的对象类和搜索规则后,odmdelete 命令删除所有满足那些标准的对象。
下面是它的命令格式:
odmdelete -o ObjectClass [ -q Criteria ] |
其中,-o ObjectClass指定要从中删除的对象类。-q标准指定用于从对象类中选择对象的标准。 如果没有指定标准(没有 -q 标志),删除所有对象。
odmdelete命令举例:
从PdAt对象类中删除uniquetype为"tape/scsi/8mm",而且attribute为"block_size"的所有对象:
# odmdelete -o PdAt -q "uniquetype=tape/scsi/8mm and attribute=block_size" |
如果给定了修改的对象类、搜索规则和新对象(仅对需要更改的属性),odmchange 命令将修改所有满足搜索规则的对象。InputFile 文件和用于 odmadd 命令的 InputFile 文件(ASCII 输入文件)有同样的格式。
odmchange -o ObjectClass [ -q Criteria] [ InputFile] |
其中-o ObjectClass和-q Criteria参数同上。如果不指定-q Criteria参数,则修改指定对象类中所有对象。
odmshow 命令以对象类名称(ObjectClass)为输入并在屏幕上显示类描述。 类描述的格式采用 odmcreate 命令的输入格式。
odmshow ObjectClass |
odmshow命令举例:
例如显示CuDv对象类的结构:
# odmshow CuDv
bash-3.00# odmshow CuDv class CuDv { char name[16]; /* offset: 0xc ( 12) */ short status; /* offset: 0x1c ( 28) */ short chgstatus; /* offset: 0x1e ( 30) */ char ddins[16]; /* offset: 0x20 ( 32) */ char location[16]; /* offset: 0x30 ( 48) */ char parent[16]; /* offset: 0x40 ( 64) */ char connwhere[16]; /* offset: 0x50 ( 80) */ link PdDv PdDv uniquetype PdDvLn[48]; /* offset: 0x60 ( 96) */ }; /* descriptors: 8 structure size: 0x98 (152) bytes data offset: 0x200030e8 population: 71 objects (71 active, 0 deleted) */ |
odmdrop 命令除去整个对象类和它所有的对象。其它对象类是否链接了本对象类,不用进行检查。
它的命令格式如下:
odmdrop -o ClassName |
odmdrop命令举例:
假定存在一个名字为 MyObjectClass 的对象类,下列命令除去对象类:odmdrop -o MyObjectClass
|
下面描述一些不同的ODM使用的例子。
ODM维护一个您的系统安装的所有软件的详细目录。
例如,一个名为lpp的类包含当前安装的软件产品的信息,像软件ID、名称、版本和发行版本。我们可以使用命令odmget来查询lpp ODM类关于系统安装的所有软件的信息并指定只输出前30行,如下所示:
# odmget lpp|head -40
bash-3.00# odmget lpp|head -40 lpp: name = "__SWVPD_CTL__" size = 0 state = 0 cp_flag = 0 group = "" magic_letter = "" ver = 0 rel = 0 mod = 0 fix = 0 description = "" lpp_id = 230 lpp: name = "bos.rte" size = 0 state = 5 cp_flag = 262419 group = "" magic_letter = "I" ver = 5 rel = 3 mod = 0 fix = 0 description = "Base Operating System Runtime" lpp_id = 1 lpp: name = "bos.rte.Dt" size = 0 state = 5 cp_flag = 262419 group = "" magic_letter = "I" ver = 5 rel = 3 mod = 0 fix = 0 |
ODM保存所有设备配置所必须的数据。例如,名为预定义设备(PdDv)的类包括AIX 5L支持的所有设备的条目。在这个类中重要的属性包括类型,子类,缀,基础,可检测性,led,steno,编目,DvDr,定义,配置,改变,未配置,未定义,启动,停止和唯一类型。我们可以使用命令odmget来查询在ODM PdDv类中类型以lv开头的所有对象如下所示:
bash-3.00# odmget -q "type LIKE lv*" PdDv
bash-3.00# odmget -q "type LIKE lv*" PdDv PdDv: type = "lvtype" class = "logical_volume" subclass = "lvsubclass" prefix = "lv" devid = "" base = 1 has_vpd = 0 detectable = 0 chgstatus = 0 bus_ext = 0 fru = 0 led = 0 setno = 1 msgno = 699 catalog = "cmdlvm.cat" DvDr = "" Define = "" Configure = "" Change = "" Unconfigure = "" Undefine = "" Start = "" Stop = "" inventory_only = 0 uniquetype = "logical_volume/lvsubclass/lvtype" PdDv: type = "lvdd" class = "lvm" subclass = "lvm" prefix = "" devid = "" base = 1 has_vpd = 0 detectable = 0 chgstatus = 1 bus_ext = 0 fru = 0 led = 1425 setno = 1 msgno = 52 catalog = "devices.cat" DvDr = "hd_pin" Define = "/usr/lib/methods/deflvm" Configure = "/usr/lib/methods/cfglvdd" Change = "" Unconfigure = "" Undefine = "" Start = "" Stop = "" inventory_only = 0 uniquetype = "lvm/lvm/lvdd" PdDv: type = "lv" class = "virtual_target" subclass = "vtdev" prefix = "vtscsi" devid = "" base = 0 has_vpd = 0 detectable = 0 chgstatus = 0 bus_ext = 0 fru = 0 led = 9656 setno = 1 msgno = 1 catalog = "vtdev.cat" DvDr = "" Define = "/usr/lib/methods/define -g -d" Configure = "/usr/lib/methods/cfg_vt_lvm" Change = "" Unconfigure = "/usr/lib/methods/ucfg_vtdev" Undefine = "/usr/lib/methods/undefine" Start = "" Stop = "" inventory_only = 0 uniquetype = "virtual_target/vtdev/lv" |
ODM同样维护一个LVM使用的所有数据的拷贝。对LVM有影响的命令被设计为硬盘上的VGDA数据总是和ODM中保存的信息同步。例如,名为CuAt的ODM类包含自定义的指定设备的属性信息。我们可以使用命令odmget来查询CuAt ODM类中关于hdsik0的所有属性信息如下所示:
# odmget -q name=hdisk0 CuAt
bash-3.00# odmget -q name=hdisk0 CuAt CuAt: name = "hdisk0" attribute = "unique_id" value = "2708E6WZGWBC10IC35L073UCDY10-003IBMscsi" type = "R" generic = "" rep = "nl" nls_index = 79 CuAt: name = "hdisk0" attribute = "pvid" value = "0059041d3be9d3090000000000000000" type = "R" generic = "D" rep = "s" nls_index = 2 CuAt: name = "hdisk0" attribute = "size_in_mb" value = "73400" type = "R" generic = "D" rep = "nr" nls_index = 60 CuAt: name = "hdisk0" attribute = "led" value = "0x57D" type = "Z" generic = "" rep = "nr" nls_index = 0 CuAt: name = "hdisk0" attribute = "message_no" value = "87" type = "T" generic = "" rep = "nl" nls_index = 0 CuAt: name = "hdisk0" attribute = "diag_scsd" value = "a500000107000507000c0b" type = "R" generic = "" rep = "s" nls_index = 0 |
名为history的类包含所有软件产品的安装和更新的相关信息。我们可以使用命令odmget来查询history ODM类关于系统安装的lpp_id=100的软件的安装和更新信息如下所示:
# odmget history|grep -p "lpp_id = 100"
bash-3.00# odmget history|grep -p "lpp_id = 100" history: lpp_id = 100 event = 1 ver = 5 rel = 3 mod = 0 fix = 0 ptf = "" corr_svn = "" cp_mod = "" cp_fix = "" login_name = "root" state = 1 time = 1102919663 comment = "" history: lpp_id = 100 event = 1 ver = 5 rel = 3 mod = 0 fix = 30 ptf = "" corr_svn = "" cp_mod = "" cp_fix = "" login_name = "root" state = 1 time = 1129166921 comment = "" history: lpp_id = 100 event = 2 ver = 5 rel = 3 mod = 0 fix = 30 ptf = "" corr_svn = "" cp_mod = "" cp_fix = "" login_name = "root" state = 1 time = 1129167257 comment = "" |
当用户添加一个新设备时,如果AIX系统的ODM数据库不支持该新设备,则可以向PdDv,PdAt和PdCn对象类中添加这个新设备对象。
首先,用odmget命令从PdDv,PdAt 和PdCn对象类中复制一份已存在设备的纪,并分别保存在临时文件中。
然后,用Vi分别编辑上一步生成的临时文件,按照新设备说明书中所列示的属性参数修改每个字段的值,并确保该设备在PdDv对象类中的配置是正确的。
再用odmadd命令从编辑好的临时文件中向PdDv,PdAt 和PdCn对象类添加新设备对象。
最后,安装新设备的驱动程序,确保系统中有合适的设备驱动程序。如果系统引导时需要该设备,则创建一个新的引导逻辑卷。
用odmchange命令修改磁带机rmt0的属性block_size的值
要修改某个设备的属性值,可以使用chdev命令来完成,也可通过直接修改ODM中的内容来实现。
1.从ODM数据库的CuAt对象类中取出SCSI接口的8mm磁带机rmt0的block_size属性,存入tapeattr文件中。
odmget -q "name=rmt0 and attribute=block_size" PdAt >tapeattr |
2.vi tapeattr (用vi修改tapeattr文件中的attribute属性的值为512,并保存修改结果并退出vi)
PdAt: uniquetype = "tape/scsi/8mm" attribute = "block_size" deflt = "1024" values = "0-245760,1" width = "" type = "R" generic = "DU" rep = "nr" nls_index = 6 |
3.执行odmchange命令,用tapeattr文件的内容来修改磁带机的属性值。
# odmchange -o CuAt -q "name=rmt0 and attribute=block_size" tapeattr |
用odmdelete,odmadd命令把磁带机上的block_size属性值从1024改为512。
1.odmget -q "name=rmt0 and attribute=block_size" PdAt >tapeattr
2.vi tapeattr (用vi修改tapeattr文件并保存修改结果并退出vi)
PdAt: uniquetype = "tape/scsi/8mm" attribute = "block_size" deflt = "1024" values = "0-245760,1" width = "" type = "R" generic = "DU" rep = "nr" nls_index = 6 |
3.将rmt0设备的block_size 属性从ODM数据库CuAt对象类中删除。
odmdelete -o CuAt -q "name=rmt0 and attribute=block_size" |
4.按照修改后的tapeattr文件内容创建新的对象。
odmadd tapeattr |
|
手工删除smit菜单的步骤如下:
1.export ODMDIR=/usr/lib/objrepos
2.rm $HOME/smit.log
3.smit -D
并执行想删除的一些菜单命令,查看smit.log中id的值
4.odmget -q id=*** sm_menu_opt >/tmp/smit
5.odmdelete -q id=*** -o sm_menu_opt
6.vi /tmp/smit
7.odmadd /tmp/smi
|
当您的硬盘处于无序状态时,如为 hdisk0, hdisk2, hdisk3 而不是hdisk0, hdisk1, hdisk2,可以用以下的脚本来改正。
lsdev -Cc disk | awk '{ print $1 }' | while read HDname; do odmdelete -q "name = $HDname" -o CuAt odmdelete -q "value = $HDname" -o CuAt odmdelete -q "name = $HDname" -o CuDv odmdelete -q "value3 = $HDname" -o CuDvDr odmdelete -q "name = $HDname" -o CuVPD done rm -f /dev/hdisk* rm -f /dev/rhdisk* savebase |
执行完后,用以下命令重启机器,之后硬盘顺序将变为有序状态:
shutdown -Fr |
|
在/usr/lib/objrepos下,与SMIT相关的文件有:sm_cmd_hdr, sm_cmd_hdr.vc, sm_cmd_opt, sm_cmd_opt.vc, sm_menu_opt, sm_menu_opt.vc, sm_name_hdr, sm_name_hdr.vc. 如果您的SMIT由于某种原因不能用了,比如说由于在/usr/lib/objrepos下的与SMIT相关的文件不慎删除或者损坏,这个时候smit是不能用了,即使您从别处拷来这些文件,一样不可用,您只有重建smit class了。
恢复步骤:
1)建立smit空对象类
安装bos.adt.samples包后,在/usr/samples/smit下可以找到smit_class.cre类描述文件。然后建立smit空对象类。
#odmcreate smit_class.cre sm_cmd_opt sm_cmd_hdr sm_menu_opt sm_name_hdr |
2)从其他主机提取smit对象
#odmget sm_cmd_hdr >sm_cmd_hdr.add #odmget sm_cmd_opt >sm_cmd_opt.add #odmget sm_menu_opt >sm_menu_opt.add #odmget sm_name_hdr >sm_name_hdr.add |
3)将第2步提取的四个文件ftp到您想要恢复的主机上
4)将提取的对象添加到第1步产生的对象类中
#odmadd sm_cmd_hdr.add #odmadd sm_cmd_opt.add #odmadd sm_menu_opt.add #odmadd sm_name_hdr.add |
|
拥有较好 ODM 知识对于理解您的系统作用和分析问题以及故障排除都是很重要的,然而,您应该知道当使用通常的命令行命令管理系统时,改变 ODM 数据的内容是不可能的,这时您得使用 ODM 命令,这里不管是使用 SMIT 还是命令行,它们都能够保持 ODM 和系统状态在任何时候都同步,它是如此完美以至于您可能永远不必使用 ODM 命令。错误的使用 ODM 命令会造成系统不可用,因此使用 ODM 命令时您一定要明白您在干什么。即便如此,您还是应该知道这些命令的存在并对它们有一定的了解。
文章来源于领测软件测试网 https://www.ltesting.net/