本系列文章阐释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/










