Tuesday, June 28, 2005

谈ug_import脚本的自动生成

ug_import是我们经常会用到的一个工具,它用于将UG文件批量地导入到IMAN系统中,很多客户往往会有很多UG文件,将这些文件导入到IMAN 里之前,我们必须要知道每一个UG文件导进去之后所使用的ITEM ID, ITEM名称, ITEM版本以及ITEM类型等信息,这就是mapping文件(映射文件),因此,我们通常要作的工作就是根据某个文件夹中成百上千个UG文件编写一份 mapping文件,如果让我们一行一行的敲出来,那八成是要死人的,所以我们需要借助工具来使它自动生成。
这里介绍一下如何使用免费的GNU工具来生成UG的mapping文件。


这里所说的GNU工具,其实是一个完整的UNIX环境,它可以运行于WIN32平台。我们没有必要将整个环境都搬到我们的WINDOWS里来,我们只要将我们需要用到的有限的几个工具拆下来就可以了,一般只要2-3MB的空间即可,主要包括如下几个命令:

bash : 所编写的脚本的解析器
awk : 强大的脚本语言工具
sed : 模式过滤工具
sort : 排序工具
ls : 生成目录列表工具
tee : Dual Output工具

除了以上工具之外,还有几个执行它们需要的库文件。

对于这些工具的安装,我们需要做以下两件事:
(1)将含有这些工具的目录(如gnu_tools)放到某个位置,如c:\gnu_tools;
(2)将该目录加到PATH环境变量中,如 set PATH=c:\gnu_tools;%PATH%
就这么简单。

有了这些工具之后,我们只要稍稍具备一些UNIX脚本知识,就可以使用它们来编写SHELL脚本了,在你试过之后,你会觉得整个过程是那么的perfect。

还有一个问题,如果根据目录中的所有UG文件能够“自动地”生成导入脚本,我们必须根据UG文件名能够转换成导入之后的ITEM ID,ITEM名称以及ITEM类型等属性值,如果UG文件名五花八门,那么一份文件名与ITEM信息的对照表可能是必须的。

下面举个简单的例子。

假设目录c:\ug_files下有如下一些UG文件:

0123456.prt
2020395.prt
2023952.prt
2023952_a_dtes.prt
2039652.prt
4012362.prt
4012362_s_asdf.prt
8023425.prt
8023425_a_tsef.prt
9023425_s_keis.prt
9023862.prt
9023862_s_ssss.prt

处理规则:
文件名含有"_s_"的为UGPART文件,含有"_a_"的为UGALTREP,其余为UGMASTER。
对于UG文件名以0开头的,认为是顶层装配,赋予ITEM类型为Product;
对于UG文件名以1-3开头的,认为是部件,赋予ITEM类型为Assembly;
对于UG文件名以4-9开头的,认为是零件,赋予ITEM类型为Part;

针对以上UG文件,编写如下脚本(主要使用AWK工具):


#!/usr/bin/bash

PWD=`pwd | awk -F/ '{print $NF}'`

ls *.prt | awk -v THE_PWD=$PWD '

BEGIN{
print "[Defaults]"
print "\timport_folder=" "\"" THE_PWD "\""
print "\tdb_part_no=$STRIPPED_LEAFNAME"
print "\texisting_data=$USE_EXISTING"
printf("@echo off\n")>"import_script.bat"
printf("@if x%%1x == xx goto error\n")>>"import_script.bat"
printf("@if x%%2x == xx goto error\n")>>"import_script.bat"
printf("@if x%%3x == xx goto error\n")>>"import_script.bat"

}

{
if ( $0 ~ /_s_/ ) {

# UGPART dataset
print "[" $0 "]"
print "\tdb_part_no=" "\"" gensub("(.*)_s_.*","\\1",$0) "\""
# db_part_name are same with db_part_no
print "\tdb_part_name=" "\"" gensub("(.*)_s_.*","\\1",$0) "\""
if ( $0 ~ /^[0]/ )
{
print "\tdb_part_type=Product"
}
else if ( $0 ~ /^[123]/ )
{
print "\tdb_part_type=Assembly"
}
else if ( $0 ~ /^[456789]/ )
{
print "\tdb_part_type=Part"
}
else
{
i dont know how to deal with it.
}
print "\tdb_part_rev=01"
print "\tdb_model_type=spec"
print "\tdb_model_name=" "\"" gensub(".*_s_(.*).prt","\\1",$0) "\""

# Generate all_in_one script
printf("%%UGII_BASE_DIR%%\\UGMANAGER\\ug_import -part=%s -mapping=mapping.txt -u=%%1 -p=%%2 -g=%%3\n",$0)>>"import_script.bat"

}
else if ( $0 ~ /_a_/ ) {

# UGALTREP dataset
print "[" $0 "]"
print "\tdb_part_no=" "\"" gensub("(.*)_s_.*","\\1",$0) "\""
# db_part_name are same with db_part_no
print "\tdb_part_name=" "\"" gensub("(.*)_s_.*","\\1",$0) "\""
if ( $0 ~ /^[0]/ )
{
print "\tdb_part_type=Product"
}
else if ( $0 ~ /^[123]/ )
{
print "\tdb_part_type=Assembly"
}
else if ( $0 ~ /^[456789]/ )
{
print "\tdb_part_type=Part"
}
else
{
i dont know how to deal with it.
}
print "\tdb_part_rev=01"
print "\tdb_model_type=alt"
print "\tdb_model_name=" "\"" gensub(".*_s_(.*).prt","\\1",$0) "\""

# Generate all_in_one script
printf("%%
UGII_BASE_DIR%%\\UGMANAGER\\ug_import -part=%s -mapping=mapping.txt -u=%%1 -p=%%2 -g=%%3\n",$0)>>"import_script.bat"

}

else {
# UGMASTER datasets
print "[" $0 "]"
print "\tdb_part_no=" "\"" gensub("(.*).prt","\\1",$0) "\""
print "\tdb_part_rev=01"
print "\tdb_part_name=" "\"" gensub("(.*).prt","\\1",$0) "\""
if ( $0 ~ /^[0]/ )
{
print "\tdb_part_type=Product"

# Generate all_in_one script
printf("%%UGII_BASE_DIR%%\\UGMANAGER\\ug_import -part=%s -mapping=mapping.txt -u=%%1 -p=%%2 -g=%%3\n",$0)>>"import_script.bat"

}
else if ( $0 ~ /^[123]/ )
{
print "\tdb_part_type=Assembly"
}
else if ( $0 ~ /^[456789]/ )
{
print "\tdb_part_type=Part"
}
else
{
# i dont know how to deal with it.
}

}

}

END {

# all_in_one script
printf("goto end\n")>>"import_script.bat"
printf(":error\n")>>"import_script.bat"
printf("echo Syntax error : %%0 username password group\n")>>"import_script.bat"
printf(":end\n")>>"import_script.bat"

}

' | tee mapping.txt

假设以上脚本名称为 "do_it.sh",编写完成后,将该脚本文件放置于与gnu_tools相同的目录中(目的是使它也在PATH中),然后,我们需要到UG文件所在目录中执行以下命令:
c:\ug_files>
bash do_it.sh

命 令执行过程中,会在标准输出(屏幕)上输出mapping文件的具体内 容,同时生成一个mapping.txt文件和import_script.bat文件,在import_script.bat文件中,同时包含了 ugmaster, ugpart,ugaltrep文件的导入脚本。

生成的导入脚本是酱紫的:
MAPPING.txt
===================
[Defaults]
import_folder="文件夹名"
db_part_no=$STRIPPED_LEAFNAME
existing_data=$USE_EXISTING
[0123456.prt]
db_part_no="0123456"
db_part_rev=01
db_part_name="0123456"
db_part_type=Product
[2020395.prt]
db_part_no="2020395"
db_part_rev=01
db_part_name="2020395"
db_part_type=Assembly
[2023952.prt]
db_part_no="2023952"
db_part_rev=01
db_part_name="2023952"
db_part_type=Assembly
[2023952_a_dtes.prt]
db_part_no="2023952"
db_part_rev=01
db_model_type=alt
db_model_name="
dtes"
[2039652.prt]
db_part_no="2039652"
db_part_rev=01
db_part_name="2039652"
db_part_type=Assembly
[4012362.prt]
db_part_no="4012362"
db_part_rev=01
db_part_name="4012362"
db_part_type=Part
[4012362_s_asdf.prt]
db_part_no="4012362"
db_part_rev=01
db_model_type=spec
db_model_name="asdf"
......

import_script.bat
======================
@echo off
@if x%1x == xx goto error
@if x%2x == xx goto error
@if x%3x == xx goto error

CALL %UGII_BASE_DIR%\UGMANAGER\ug_import -part=0123456.prt -mapping=mapping.txt -u=%1 -p=%2 -g=%3
CALL %UGII_BASE_DIR%\UGMANAGER\ug_import -part=2023952_a_dtes.prt -mapping=mapping.txt -u=%1 -p=%2 -g=%3
CALL %UGII_BASE_DIR%\UGMANAGER\ug_import -part=8023425_a_tsef.prt -mapping=mapping.txt -u=%1 -p=%2 -g=%3
CALL %UGII_BASE_DIR%\UGMANAGER\ug_import -part=9023425_s_keis.prt -mapping=mapping.txt -u=%1 -p=%2 -g=%3
CALL %UGII_BASE_DIR%\UGMANAGER\ug_import -part=4012362_s_asdf.prt -mapping=mapping.txt -u=%1 -p=%2 -g=%3
CALL %PATH_TO_UG%\UGMANAGER\ug_import -part=9023862_s_ssss.prt -mapping=mapping.txt -u=%1 -p=%2 -g=%3
goto end
:error
echo Syntax error : %0 username password group
:end

然后,只要对生成的import_script.bat稍做修改(主要是ug_import的路径),就可以在IMAN_SHELL的环境下执行导入了。

在上面的例子中,我们为了简化处理过程,做了如下假设:
所有的UGPART文件与UGALTREP文件,都有相应的UGMASTER存在!

这 样的假设实际上是非常重要的,如果我们不能保证以上条件,我们就要额外写些代码来处理UG文件,以保证满足上述条件,同时,如果满足上述条件,我们可以 确保在生成的导入脚本import_script.bat中,导入的顺序是按照 “先UGMASTER,再UGALTREP,最后UGPART”的顺序排列的,而这种导入顺序也是我们所需要的,否则就会出错。



更多信息,refer to ug_import help document & gnu manpages


Thursday, June 02, 2005

Teamcenter瘦身运动:合并ORACLE实例

经常参加Teamcenter项目实施的朋友,你是不是遇到跟我一样的烦恼呢?

ORACLE实例多达十几个


磁盘空量占据10+ Gigabytes


一般我们所参与的每个项目,至少都会有一个oracle实例,那么我们是不是有必要为每个项目数据都建一个独立的实例呢?答案是否定的。



实 际上,对于我们实施方来说,每个项目我们只需要一点点示例数据就够用了,如果为了这一点点数据建创建一个几百兆甚至上G的数据库实例,那我们的硬盘就装 不了多少东西了。 为了使我们的Teamcenters能够瘦下来,可以通过合并数据库的方式,将所有的项目所需要的数据都存放于同一个数据库实例中,然后使用不同的数据库 用户 加以区分。

此方法不仅仅适用于Teamcenter Engineering的所有版本, 甚至所有需要oracle数据库支持的应用都可以采用此方法,比如Teamcenter Enterprise, Teamcenter Project 等等。

下面介绍具体的操作方法:

(为描述方便,我们把那些“在数据上独立,但以共享方式使用ORACLE实例”的情形称为“数据实例”)

1. 假设我们的oracle已经安装完毕并正常工作 (oracle 9i / oracle 10g),然后使用warehouse模板创建一个空实例,实例名为 my_sid, 假设system帐号密码为system;

2. 使用数据库导出工具exp将数据库导出,导出前注意服务器端与客户端的字符集要保持一致,命令如下:
c:\exp system/system@my_sid file=c:\my_sid.dmp log=my_sid.log full=y grants=y

3. 为所需要的应用规划数据库。假设使用该数据库同时作为Tceng811, Tceng912, Tceng2005, TcProj6的数据库,接下来确定每个应用所使用的数据库帐号,暂定如下:

Tceng811 : tceng811
Tceng912: tceng912
Tceng2005: tceng2k5
TcProj6: tcprj6

以上用户的时候的创建可以以INFODBA帐户为基础。

4. 使用数据库导入工具,为每个应用创建独立的用户空间、

c:\imp system/system@my_sid file=c:\my_sid.dmp log=my_sid.log fromuser=system touser=tceng811 commit=y ignore=y
c:\imp system/system@my_sid file=c:\my_sid.dmp log=my_sid.log fromuser=system touser=tceng912 commit=y ignore=y
c:\imp system/system@my_sid file=c:\my_sid.dmp log=my_sid.log fromuser=system touser=tceng2k5 commit=y ignore=y
c:\imp system/system@my_sid file=c:\my_sid.dmp log=my_sid.log fromuser=system touser=tcprj6 commit=y ignore=y

5. 为方便记忆,可以将所有用户的密码统一为"infodba",这样加密后的connect string 均为 "tbwiabd"。

6. 接下来,就根据不同应用的需要,创建相应的schema,如安装tceng811时,在configure or new db步骤时,选择用户tceng811进行操作, 安装tceng912时, 则使用tceng912用户, 当配置TcProj6.0的数据库时,使用tcprj6这个用户, 千万不要选错了

7. 接下来就是如何处理PORTAL端连接的问题,包括两个部分的内容,分别要处理 start_my_sid_PortalServer.bat文件与my_sid_PortalServer.imp文件。

我们在配置第一个“数据实例” 的时候,生成了start_my_sid_PortalServer.bat 与 my_sid_PortalServer.imp,如果按传统方法配置后面的“数据实例”就会出问题,因为这两个文件只有一份, 要想处理多个“数据实例”登录的问题,必须将其分开,方法如下:

假设我们现在有两个客户数据,一是aaa, 另一个是bbb,我们需要将以上两个文件复制为以下两份:
start_my_sid_PortalServer_aaa.bat
start_my_sid_PortalServer_bbb.bat
my_sid_PortalServer_aaa.imp
my_sid_PortalServer_bbb.imp
修改前两个文件中iman_data 的路径,再修改后两个文中的IMP文件名,使其与“数据实例”相对应。

8. 将%IPR%下的client_specific.properties复制为client_specific_aaa.properties与 client_specific_bbb.properties,修改文件中的"ServerName ServerMarker", 使其与“数据实例”相对应。

9. 将portal.bat 复制为portal_aaa.bat, portal_bbb.bat, 用于处理有独立的客户化包的问题和数据库的选择问题,然后按如下进行修改:

在portal_aaa.bat的"set IDR=%IPR%"之后添加以下内容:
xcopy %IPR%\client_specific_aaa.properties %IPR%\client_specific.properties /y >NUL 2>&1
在portal_bbb.bat的"set IDR=%IPR%"之后添加以下内容:
xcopy %IPR%\client_specific_bbb.properties %IPR%\client_specific.properties /y >NUL 2>&1

之后,我们就可以分别使用portal_aaa.bat与portal_bbb.bat进入不同的“数据实例”了。

10. 差不多了, 哪个不怕死的有空就试试吧~

( Many thanks to Dr. Frank Feng sharing this solution to me ! )