应用程序包开发者指南

crontab用法  时间:2021-01-16  阅读:()

SunMicrosystems,Inc.
4150NetworkCircleSantaClara,CA95054U.
S.
A.
文件号码820–5500–122009年4月版权所有2009SunMicrosystems,Inc.
4150NetworkCircle,SantaClara,CA95054U.
S.
A.
保留所有权利.
对于本文档中介绍的产品,SunMicrosystems,Inc.
对其所涉及的技术拥有相关的知识产权.
需特别指出的是(但不局限于此),这些知识产权可能包含一项或多项美国专利,或在美国和其他国家/地区申请的待批专利.
美国政府权利-商业软件.
政府用户应遵循SunMicrosystems,Inc.
的标准许可协议,以及FAR(FederalAcquisitionRegulations,即"联邦政府采购法规")的适用条款及其补充条款.
本发行版可能包含由第三方开发的内容.
本产品的某些部分可能是从BerkeleyBSD系统衍生出来的,并获得了加利福尼亚大学的许可.
UNIX是X/OpenCompany,Ltd.
在美国和其他国家/地区独家许可的注册商标.
Sun、SunMicrosystems、Sun徽标、Solaris徽标、Java咖啡杯徽标、docs.
sun.
com、SunOS、JumpStart、Java和Solaris是SunMicrosystems,Inc.
或其子公司在美国和其他国家/地区的商标或注册商标.
所有SPARC商标的使用均已获得许可,它们是SPARCInternational,Inc.
在美国和其他国家/地区的商标或注册商标.
标有SPARC商标的产品均基于由SunMicrosystems,Inc.
开发的体系结构.
OPENLOOK和SunTM图形用户界面是SunMicrosystems,Inc.
为其用户和许可证持有者开发的.
Sun感谢Xerox在研究和开发可视或图形用户界面的概念方面为计算机行业所做的开拓性贡献.
Sun已从Xerox获得了对Xerox图形用户界面的非独占性许可证,该许可证还适用于实现OPENLOOKGUI和在其他方面遵守Sun书面许可协议的Sun许可证持有者.
本出版物所介绍的产品以及所包含的信息受美国出口控制法制约,并应遵守其他国家/地区的进出口法律.
严禁将本产品直接或间接地用于核设施、导弹、生化武器或海上核设施,也不能直接或间接地出口给核设施、导弹、生化武器或海上核设施的最终用户.
严禁出口或转口到美国禁运的国家/地区以及美国禁止出口清单中所包含的实体,包括但不限于被禁止的个人以及特别指定的国家/地区的公民.

本文档按"原样"提供,对于所有明示或默示的条件、陈述和担保,包括对适销性、适用性或非侵权性的默示保证,均不承担任何责任,除非此免责声明的适用范围在法律上无效.
090511@22510目录前言91设计软件包13在何处找到打包任务13什么是软件包13软件包组件14必需的软件包组件15可选软件包组件15生成软件包之前的注意事项16使软件包可远程安装17针对客户机/服务器配置进行优化17根据功能边界打包17根据版税边界打包17根据系统相关性打包17消除软件包中的重叠18根据本地化边界打包18映像包管理系统(ImagePackagingSystem,IPS)软件包18打包命令、文件和脚本192生成软件包21软件包生成过程(任务图)21软件包环境变量22关于使用环境变量的一般规则22软件包环境变量汇总23创建pkginfo文件23定义软件包实例24定义软件包名称(NAME)253定义软件包类别(CATEGORY)26如何创建pkginfo文件26组织软件包的内容27如何组织软件包的内容27创建prototype文件28prototype文件的格式28从头创建prototype文件33示例-使用pkgproto命令创建prototype文件33优化使用pkgproto命令创建的prototype文件34向prototype文件添加功能36如何使用pkgproto命令创建prototype文件38生成软件包40使用最简单的pkgmk命令40pkgmap文件40如何生成软件包413增强软件包的功能(任务)45创建信息文件和安装脚本(任务图)45创建信息文件46定义软件包相关性46如何定义软件包相关性47编写版权信息49如何编写版权信息49在目标系统上保留额外空间50如何在目标系统上保留额外空间51创建安装脚本52软件包安装期间的脚本处理52软件包删除期间的脚本处理53对脚本可用的软件包环境变量53为脚本获取软件包信息55脚本的退出代码55编写request脚本56如何编写request脚本57使用checkinstall脚本收集文件系统数据58如何收集文件系统数据59目录应用程序包开发者指南2009年4月4编写过程脚本60如何编写过程脚本61编写类操作脚本62如何编写类操作脚本68创建带签名的软件包69带签名的软件包69证书管理70创建带签名的软件包72如何创建不带签名的目录格式的软件包72如何将证书导入到软件包密钥库73如何对软件包签名744验证和转换软件包77验证和转换软件包(任务图)77安装软件包78安装软件数据库78与pkgadd命令交互78在同构环境中的独立系统或服务器上安装软件包79如何在独立系统或服务器上安装软件包79验证软件包的完整性80如何验证软件包的完整性80显示有关已安装的软件包的附加信息81pkgparam命令81如何使用pkgparam命令获取信息82pkginfo命令83如何使用pkginfo命令获取信息86删除软件包86如何删除软件包86将软件包转换为分发介质87如何将软件包转换为分发介质875软件包创建案例研究89请求来自管理员的输入89技术89方法90目录5案例研究文件91在安装时创建文件并在删除期间保存文件92技术92方法93案例研究文件94定义软件包兼容性和相关性95技术95方法96案例研究文件96使用标准类和类操作脚本修改文件97技术97方法97案例研究文件98使用sed类和postinstall脚本修改文件100技术100方法100案例研究文件101使用build类修改文件102技术102方法102案例研究文件103在安装期间修改crontab文件103技术103方法104案例研究文件104使用过程脚本安装和删除驱动程序106技术106方法106案例研究文件107使用sed类和过程脚本安装驱动程序109技术109方法109案例研究文件110目录应用程序包开发者指南2009年4月66创建软件包的高级技术115指定基目录115缺省管理文件115使用BASEDIR参数117使用参数化基目录117管理基目录119适应重定位119遍历基目录120在异构环境中支持重定位127传统方法128超越传统131使软件包可远程安装136示例-安装到客户机系统136示例-安装到服务器或独立系统137示例-挂载共享文件系统137修补软件包138checkinstall脚本139preinstall脚本143类操作脚本148postinstall脚本153patch_checkinstall脚本158patch_postinstall脚本160升级软件包161request脚本162postinstall脚本163创建类归档软件包163归档软件包目录的结构164支持类归档软件包的关键字165faspac实用程序166词汇表169索引173目录78前言《应用程序包开发者指南》提供设计、生成和验证软件包的逐步说明以及相关的背景信息.
本指南还包括在软件包创建过程中可能非常有用的高级技术.
注–此SolarisTM发行版支持使用以下SPARC和x86系列处理器体系结构的系统:UltraSPARC、SPARC64、AMD64、Pentium和XeonEM64T.
支持的系统可以在http://www.
sun.
com/bigadmin/hcl上的SolarisOS:HardwareCompatibilityLists中找到.
本文档列举了在不同类型的平台上进行实现时的所有差别.
在本文档中,这些与x86相关的术语表示以下含义:"x86"泛指64位和32位的x86兼容产品系列.
"x64"指出了有关AMD64或EM64T系统的特定64位信息.
"32位x86"指出了有关基于x86的系统的特定32位信息.
若想了解本发行版支持哪些系统,请参见SolarisOS:HardwareCompatibilityLists.
目标读者本书面向负责设计和生成软件包的应用程序开发者.
虽然本书的许多内容都针对软件包开发新手,但也包含对经验丰富的软件包开发者有用的信息.
本书的结构下表介绍了本书中的各章.
章节名称章节说明第1章,设计软件包介绍软件包组件和软件包设计准则,此外还介绍了相关的命令、文件和脚本.
9章节名称章节说明第2章,生成软件包介绍生成软件包的过程和所需任务,此外还提供了每项任务的逐步说明.
第3章,增强软件包的功能(任务)提供向软件包中添加可选功能的逐步说明.
第4章,验证和转换软件包介绍如何验证软件包的完整性,以及如何将软件包转换为分发介质.
第5章,软件包创建案例研究提供创建软件包的案例研究.
第6章,创建软件包的高级技术介绍创建软件包的高级技术.
词汇表定义本书中使用的术语.
相关书籍以下文档可从零售书商处购买,这些书籍可以提供有关生成SystemV软件包的其他背景信息.
《SystemVApplicationBinaryInterface》《SystemVApplicationBinaryInterface-SPARCProcessorSupplement》《SystemVApplicationBinaryInterface-Intel386ProcessorSupplement》文档、支持和培训SunWeb站点提供有关以下附加资源的信息:文档(http://www.
sun.
com/documentation/)支持(http://www.
sun.
com/support/)培训(http://www.
sun.
com/training/)Sun欢迎您提出意见Sun致力于提高其文档的质量,并十分乐意收到您的意见和建议.
要分享您的意见,请访问http://docs.
sun.
com并单击"Feedback".
前言应用程序包开发者指南2009年4月10印刷约定下表介绍了本书中的印刷约定.
表P–1印刷约定字体或符号含义示例AaBbCc123命令、文件和目录的名称;计算机屏幕输出编辑.
login文件.
使用ls-a列出所有文件.
machine_name%youhavemail.
AaBbCc123用户键入的内容,与计算机屏幕输出的显示不同machine_name%suPassword:aabbcc123要使用实名或值替换的命令行占位符删除文件的命令为rmfilename.
AaBbCc123保留未译的新词或术语以及要强调的词这些称为Class选项.
注意:有些强调的项目在联机时以粗体显示.
新词术语强调新词或术语以及要强调的词高速缓存是存储在本地的副本.
请勿保存文件.
《书名》书名阅读《用户指南》的第6章.
命令中的shell提示符示例下表列出了Cshell、Bourneshell和Kornshell的缺省UNIX系统提示符和超级用户提示符.
表P–2shell提示符shell提示符Cshell提示符machine_name%Cshell超级用户提示符machine_name#Bourneshell和Kornshell提示符$Bourneshell和Kornshell超级用户提示符#前言1112设计软件包在生成软件包之前,您需要了解需要创建哪些文件以及需要执行哪些命令.
您还需要考虑您的应用程序软件的要求以及客户的需要.
您的客户是将要安装您的软件包的管理员.
本章讨论生成软件包之前您应该了解和考虑的文件、命令和准则.

以下是本章中信息的列表.
第13页中的"在何处找到打包任务"第13页中的"什么是软件包"第14页中的"软件包组件"第16页中的"生成软件包之前的注意事项"第19页中的"打包命令、文件和脚本"在何处找到打包任务使用以下任务图可以找到用于生成和验证软件包的逐步说明.
第21页中的"软件包生成过程(任务图)"第45页中的"创建信息文件和安装脚本(任务图)"第77页中的"验证和转换软件包(任务图)"什么是软件包应用程序软件是以被称为软件包的单位交付的.
软件包是软件产品所需的文件和目录的集合.
软件包通常是在完成应用程序代码开发后由应用程序开发者设计和生成的.
软件产品需要生成到一个或多个软件包中,以便可以轻松地将其转换为分发介质.
然后,便可以大量生产该软件产品,并由管理员进行安装.
软件包是具有所定义格式的文件和目录的集合.
该格式符合应用程序二进制接口(applicationbinaryinterface,ABI),ABI是对系统V接口定义的补充.
1第1章13软件包组件软件包组件分为两类.
软件包对象是要安装的应用程序文件.
控制文件控制是否安装软件包以及软件包的安装方式和位置.
控制文件又分为两类:信息文件和安装脚本.
有些控制文件是必需的,有些控制文件是可选的.
要打包您的应用程序,必须首先创建组成软件包所必需的组件以及任何可选组件.
然后,您可以使用pkgmk命令来生成软件包.
要生成软件包,您必须提供以下各项:软件包对象(应用程序软件的文件和目录)两个必需的信息文件(pkginfo和prototype文件)可选的信息文件可选的安装脚本下图描述了软件包的内容.
图1–1软件包的内容软件包组件应用程序包开发者指南2009年4月14必需的软件包组件在生成软件包之前,必须创建以下组件:软件包对象这些组件用于组成应用程序.
它们可由以下各项组成:文件(可执行文件或数据文件)目录命名管道链接设备pkginfo文件pkginfo文件是必需的软件包信息文件,用于定义参数值.
参数值包括软件包缩写、软件包全名和软件包体系结构.
有关更多信息,请参见第23页中的"创建pkginfo文件"和pkginfo(4)手册页.
注–有两个pkginfo(1)手册页.
第一个手册页介绍了用于显示有关已安装软件包信息的第1节中的命令.
第二个手册页介绍了用于描述软件包特征的第4节中的文件.
访问手册页时,请确保指定适用的手册页节.
例如:man-s4pkginfo.
prototype文件prototype文件是必需的软件包信息文件,用于列出软件包的组件.
每个软件包对象、信息文件和安装脚本都存在一个相应的条目.
这类条目由描述各个组件的若干信息字段组成,包括组件的位置、属性和文件类型.
有关更多信息,请参见第28页中的"创建prototype文件"和prototype(4)手册页.
可选软件包组件软件包信息文件您可以在软件包中包含四个可选软件包信息文件:compver文件定义与此版本软件包兼容的以前软件包版本.
depend文件指出与您的软件包有特殊关系的其他软件包.
space文件定义目标环境的磁盘空间要求,这会超过prototype文件中定义的对象所要求的空间.
例如,对于在安装时动态创建的文件,可能需要额外的空间.
软件包组件第1章设计软件包15copyright文件定义安装软件包时所显示的版权信息文本.
每个软件包信息文件都应在prototype文件中有一个对应条目.
关于创建这些文件的更多信息,请参见第46页中的"创建信息文件".
软件包安装脚本安装脚本并不是必需的.
但是,您可以提供可在安装软件包期间执行自定义操作的脚本.
安装脚本具有以下特征:该脚本由Bourneshell命令组成.
该脚本的文件权限应设为0644.
该脚本不需要包含shell标识符(#!
/bin/sh).
四种脚本类型如下:request脚本request脚本请求来自要安装软件包的管理员的输入.
checkinstall脚本checkinstall脚本执行特殊的文件系统验证.
注–checkinstall脚本仅在SolarisTM2.
5发行版和兼容发行版中可用.
过程脚本过程脚本定义在软件包安装和删除过程中的特定时刻所发生的操作.
您可以使用这些预定义的名称创建四个过程脚本:preinstall、postinstall、preremove和postremove.
类操作脚本类操作脚本定义一组要对对象组执行的操作.
有关安装脚本的更多信息,请参见第52页中的"创建安装脚本".
生成软件包之前的注意事项生成软件包之前,您需要确定您的产品将由一个还是多个软件包组成.
请注意,许多小软件包会比一个大软件包需要更长的安装时间.
虽然创建单个软件包是一个不错的主意,但不一定总能实现.
如果您决定生成多个软件包,则需要确定如何对应用程序代码分段.
本节提供了计划生成软件包时使用的准则列表.
生成软件包之前的注意事项应用程序包开发者指南2009年4月16许多打包准则在彼此之间都存在着一定的折衷.
均衡地满足所有要求通常很困难.
这些准则是按重要性顺序呈现的.
不过,需要根据具体环境将此顺序用作灵活的指导.
虽然每个准则都很重要,但终究取决于您来优化这些要求,以生成一组优质的软件包.
有关更多设计理念,请参见第6章,创建软件包的高级技术.
使软件包可远程安装所有软件包必须可远程安装.
可远程安装是指要安装软件包的管理员可以尝试将其安装在客户机系统上,而不一定安装到执行pkgadd命令的根(/)文件系统.
针对客户机/服务器配置进行优化布置软件包时,请考虑不同类型的系统软件配置(例如,独立系统和服务器).
良好的打包设计会分离受影响的文件,以优化每个配置类型的安装.
例如,应该将根(/)和/usr文件系统的内容进行分段,以便可以轻松地支持服务器配置.
根据功能边界打包软件包应该是一个独立的整体,并且可通过一组功能清楚地标识.
例如,一个包含UFS的软件包应包含所有UFS实用程序,并只限于采用UFS二进制代码.
应该根据客户的视角将软件包组织成功能单元.
根据版税边界打包将因有合同而需要支付版税的代码放到专用软件包或软件包组中.
请勿将代码分散放到并非必需的多个软件包中.
根据系统相关性打包将系统相关的二进制代码保存在专用软件包中.
例如,应该将内核代码放在专用软件包中,使每个实现体系结构都由不同的软件包实例组成.
本规则也适用于不同体系结构的二进制代码.
例如,SPARC系统的二进制代码应放在一个软件包中,而x86系统的二进制代码应放在另一个软件包中.
生成软件包之前的注意事项第1章设计软件包17消除软件包中的重叠构建软件包时,请尽一切可能消除重复的文件.
不必要的文件重复会导致支持和版本方面的困难.
如果您的产品有多个软件包,请反复比较这些软件包的内容以查看是否存在重复的文件.
根据本地化边界打包本地化特定的项目应放在其自己的软件包中.
理想的软件包模型应根据每种语言环境将产品的本地化项目作为一个软件包交付.
遗憾的是,在某些情况下组织边界与功能和产品边界准则相冲突.
国际缺省设置也可以在一个软件包中交付.
此设计可以将需要本地化更改的文件隔离开来,并对本地化软件包的交付格式进行标准化.
映像包管理系统(ImagePackagingSystem,IPS)软件包本文档讨论SVR4软件包.
如果要交付到OpenSolarisOS,请考虑使用映像包管理系统(ImagePackagingSystem,IPS)软件包.
OpenSolarisOS既支持SVR4,又支持IPS软件包.
IPS软件可与网络系统信息库进行交互,并使用ZFS文件系统.
在OpenSolarisOS中,可以使用pkgsend(1)命令将现有的SVR4软件包发布到IPS系统信息库.
下表对SVR4包管理系统和IPS包管理系统所使用的命令进行了比较.
有关IPS的详细信息,请参见GettingStartedWiththeImagePackagingSystem(http://dlc.
sun.
com/osol/docs/content/IPS/ggcph.
html)(映像包管理系统入门).
表1–1打包任务:IPS和SVR4任务IPS命令SVR4命令安装新软件包pkginstallpkgadd-a显示有关软件包状态的信息pkglistpkginfo验证软件包安装是否正确pkgverifypkgchk-v显示有关软件包的信息pkginfopkginfo-l列出软件包的内容pkgcontentspkgchk-l卸载软件包pkguninstallpkgrm映像包管理系统(ImagePackagingSystem,IPS)软件包应用程序包开发者指南2009年4月18打包命令、文件和脚本本节介绍在处理软件包时可能会用到的命令、文件和脚本.
手册页中会对这些内容进行介绍,本书也将对这些内容进行详细介绍,以及其执行的特定任务.
下表显示的命令可帮助您生成、验证、安装软件包并获取有关软件包的信息.

表1–2打包命令任务命令/手册页说明更多信息创建软件包pkgproto(1)生成prototype文件以作为pkgmk命令的输入第33页中的"示例-使用pkgproto命令创建prototype文件"pkgmk(1)创建可安装的软件包第40页中的"生成软件包"安装、删除和转换软件包pkgadd(1M)将软件包安装到系统中第78页中的"安装软件包"pkgask(1M)将答复存储到request脚本第56页中的"request脚本的设计规则"pkgtrans(1)将软件包复制到分发介质第87页中的"将软件包转换为分发介质"pkgrm(1M)从系统中删除软件包第86页中的"删除软件包"获取有关软件包的信息pkgchk(1M)验证软件包的完整性第80页中的"验证软件包的完整性"pkginfo(1)显示软件包信息第83页中的"pkginfo命令"pkgparam(1)显示软件包参数值第81页中的"pkgparam命令"修改已安装的软件包installf(1M)将新软件包对象并入到已安装的软件包中第61页中的"过程脚本的设计规则"和第5章,软件包创建案例研究removef(1M)从已安装的软件包中删除软件包对象第61页中的"过程脚本的设计规则"下表显示的信息文件可帮助您生成软件包.
表1–3软件包信息文件文件说明更多信息admin(4)软件包安装缺省文件第115页中的"缺省管理文件"compver(4)软件包兼容性文件第46页中的"定义软件包相关性"copyright(4)软件包版权信息文件第49页中的"编写版权信息"打包命令、文件和脚本第1章设计软件包19表1–3软件包信息文件(续)文件说明更多信息depend(4)软件包相关性文件第46页中的"定义软件包相关性"pkginfo(4)软件包特征文件第23页中的"创建pkginfo文件"pkgmap(4)软件包内容说明文件第40页中的"pkgmap文件"prototype(4)软件包信息文件第28页中的"创建prototype文件"space(4)软件包磁盘空间要求文件第50页中的"在目标系统上保留额外空间"下表介绍了一些可选安装脚本,您可以编写这样的脚本以影响是否以及如何安装软件包.
表1–4软件包安装脚本脚本说明更多信息request请求来自安装人员的信息第56页中的"编写request脚本"checkinstall收集文件系统数据第58页中的"使用checkinstall脚本收集文件系统数据"preinstall在安装类之前执行任何自定义安装要求第60页中的"编写过程脚本"postinstall在安装所有卷之后执行任何自定义安装要求第60页中的"编写过程脚本"preremove在删除类之前执行任何自定义删除要求第60页中的"编写过程脚本"postremove在删除所有类之后执行任何自定义删除要求第60页中的"编写过程脚本"类操作对特定对象组执行一系列操作.
第62页中的"编写类操作脚本"打包命令、文件和脚本应用程序包开发者指南2009年4月20生成软件包本章介绍生成软件包涉及的过程和任务.
其中一些任务是必需的,一些任务是可选的.
必需的任务会在本章中进行详细讨论.
有关可选任务(可用于为软件包添加更多功能)的信息,请参见第3章,增强软件包的功能(任务)和第6章,创建软件包的高级技术.
以下是本章中信息的列表.
第21页中的"软件包生成过程(任务图)"第22页中的"软件包环境变量"第23页中的"创建pkginfo文件"第27页中的"组织软件包的内容"第28页中的"创建prototype文件"第40页中的"生成软件包"软件包生成过程(任务图)表2–1描述了生成软件包时所需遵循的过程,特别是如果您没有丰富的软件包生成经验时更应该遵循该过程.
虽然您不必完全按照前四个任务的列出顺序来完成这些任务,但是如果遵循此顺序,您将可以更轻松地体验软件包的生成过程.
一旦您成为经验丰富的软件包设计员,就可以根据您的需要重排这些任务的顺序.
作为一位经验丰富的软件包设计员,您可以使用make命令和makefile来自动化软件包生成过程.
有关更多信息,请参见make(1S)手册页.
表2–1软件包生成过程任务图任务说明参考1.
创建一个pkginfo文件创建pkginfo文件以描述软件包的特征.
第26页中的"如何创建pkginfo文件"2第2章21表2–1软件包生成过程任务图(续)任务说明参考2.
组织软件包内容将软件包组件安排为分层目录结构.
第27页中的"组织软件包的内容"3.
(可选)创建信息文件定义软件包相关性,提供版权信息,并在目标系统上保留额外空间.
第3章,增强软件包的功能(任务)4.
(可选)创建安装脚本定制软件包的安装和删除过程.
第3章,增强软件包的功能(任务)5.
创建一个prototype文件在prototype文件中描述软件包中的对象.
第28页中的"创建prototype文件"6.
生成软件包使用pkgmk命令生成软件包.
第40页中的"生成软件包"7.
验证并转换软件包在将软件包复制到分发介质之前验证其完整性.
第4章,验证和转换软件包软件包环境变量您可以使用必需的信息文件pkginfo和prototype中的变量.
也可以使用pkgmk命令的选项,该命令用于生成软件包.
随着本章对这些文件和命令的讨论,将会提供更多有关这些变量的上下文相关信息.
不过,在开始生成软件包之前,您应该了解不同类型的变量,以及它们如何影响软件包的成功创建.
变量可以分为两种类型:生成变量生成变量以小写字母开头,并在生成时(当使用pkgmk命令生成软件包时)进行计算.
安装变量安装变量以大写字母开头,并在安装时(当使用pkgadd命令安装软件包时)进行计算.
关于使用环境变量的一般规则在pkginfo文件中,变量定义采用PARAM=value形式,其中,PARAM的首字母是大写字母.
仅在安装时对这些变量进行计算.
如果这些变量中的任一个不能被计算,则pkgadd命令将出错而异常中止.
在prototype文件中,变量定义可采用!
PARAM=value或$variable形式.
PARAM和variable均可以一个大写或小写字母开头.
只有在生成时值已知的变量才会被计算.
如果PARAM或variable是在生成时值未知的生成变量或安装变量,则pkgmk命令将出错而异常中止.
您还可以将PARAM=value选项用作pkgmk命令的选项.
此选项的作用与在prototype文件中基本相同,只不过其作用域是全局的,适用于整个软件包.
prototype文件中的!
PARAM=value定义是局部的,仅适用于该文件及其所定义的软件包组成部分.
软件包环境变量应用程序包开发者指南2009年4月22如果PARAM是安装变量,而variable是值已知的安装变量或生成变量,则pkgmk命令会将定义插入到pkginfo文件中,以便该定义在安装时可用.
但是,pkgmk命令不会计算在prototype文件中指定的任何路径名中的PARAM变量.
软件包环境变量汇总下表汇总了变量的规范格式、位置和作用域.
表2–2软件包环境变量汇总变量的定义位置变量定义格式定义的变量类型变量计算时间变量计算位置变量可以替换的项目pkginfo文件PARAM=value生成在生成时忽略N/A无安装安装时在pkgmap文件中owner、group、path或链接目标prototype文件!
PARAM=value生成生成时在prototype文件和任何内含的文件中mode、owner、group或path安装生成时在prototype文件和任何内含的文件中仅!
search和!
command命令pkgmk命令行PARAM=value生成生成时在prototype文件中mode、owner、group或path安装生成时在prototype文件中仅!
search命令安装时在pkgmap文件中owner、group、path或链接目标创建pkginfo文件pkginfo文件是一种ASCII文件,用于描述软件包的特征以及帮助控制安装流程的信息.
pkginfo文件中的每个条目均占一行,使用PARAM=value格式设定参数值.
PARAM可以是在pkginfo(4)手册页中描述的任一个标准参数.
对于参数的指定顺序没有确定要求.
创建pkginfo文件第2章生成软件包23注–每个value可以由单引号或双引号括起(例如,'value'或"value").
如果value包含任何对shell环境而言被视为特殊字符的字符,您应该使用引号.
本书中的示例和案例分析不使用引号.
请参见pkginfo(4)手册页,了解使用双引号的示例.
您还可以通过在pkginfo文件中为软件包参数赋值,创建您自己的软件包参数.
您的参数必须以大写字母开头,后跟大写或小写字母.
大写字母表明参数(变量)将在安装时(与生成时相对)被计算.
有关安装变量与生成变量之间区别的信息,请参见第22页中的"软件包环境变量".
注–任何参数值之后的结尾空格都会被忽略.
您必须在pkginfo文件中定义以下五个参数:PKG、NAME、ARCH、VERSION和CATEGORY.
当生成软件包时,软件会自动插入PATH、PKGINST和INSTDATE参数.
不要修改这八个参数.
有关其余参数的信息,请参见pkginfo(4)手册页.
定义软件包实例同一个软件包可以有不同的版本,可以与不同的体系结构兼容,或者同时符合这两种情况.
软件包的每个变体称为一个软件包实例.
软件包实例通过组合pkginfo文件中的PKG、ARCH和VERSION参数定义来确定.
pkgadd命令可在安装时为每个软件包实例指定一个软件包标识符.
软件包标识符是软件包缩写后跟一个数字后缀,例如SUNWadm.
2.
此标识符可区分不同软件包的实例,还可区分同一个软件包的不同实例.
定义软件包缩写(PKG)软件包缩写是软件包的简短名称,由pkginfo文件中的PKG参数定义.
软件包缩写必须具有以下特征:缩写必须由字母数字字符组成.
第一个字符不能是数字.
缩写长度不能超过32个字符.
缩写不能是以下保留的缩写之一:install、new或all.
注–前四个字符对您公司来说应该是唯一的.
例如,由SunMicrosystemsTM生成的所有软件包均以"SUNW"作为其软件包缩写的前四个字符.
pkginfo文件中软件包缩写条目的示例为PKG=SUNWcadap.
创建pkginfo文件应用程序包开发者指南2009年4月24指定软件包体系结构(ARCH)pkginfo文件中的ARCH参数标识与软件包相关联的体系结构.
体系结构名称的最大长度为16个字母数字字符.
如果一个软件包与多个体系结构相关联,请以逗号分隔的列表形式指定这些体系结构.
以下是pkginfo文件中一个软件包体系结构规范的示例:ARCH=sparc指定软件包指令集体系结构(SUNW_ISA)pkginfo文件中的SUNW_ISA参数标识与SunMicrosystems软件包相关联的指令集体系结构.
值如下所示:sparcv9,表示包含64位对象的软件包sparc,表示包含32位对象的软件包例如,在pkginfo文件中,一个包含64位对象的软件包的SUNW_ISA值是:SUNW_ISA=sparcv9如果没有设置SUNW_ISA,则软件包的缺省指令集体系结构会设置为ARCH参数的值.
指定软件包版本(VERSION)pkginfo文件中的VERSION参数标识软件包的版本.
版本的最大长度为256个ASCII字符,且不能以左括号开头.
以下是pkginfo文件中的一个版本规范示例:VERSION=release1.
0定义软件包名称(NAME)软件包名称是软件包的全名,由pkginfo文件中的NAME参数定义.
由于系统管理员通常会根据软件包名称确定是否需要安装该软件包,因此使用清晰、简明且完整的软件包名称是很重要的.
软件包名称必须满足以下条件:指明什么时候需要软件包(例如,用于提供某些命令或功能,或者指明该软件包是否为特定硬件所需要).
指明软件包的用途(例如,用于设备驱动程序的开发).
包括软件包缩写助记符的说明,使用的关键字应该表明缩写是说明的简短形式.
例如,软件包缩写SUNWbnuu对应的软件包名称是"BasicNetworkingUUCPUtilities,(Usr)".
创建pkginfo文件第2章生成软件包25指定安装软件包的分区名称.
使用的术语符合其行业含义.
遵守256字符数限制.
以下是pkginfo文件中定义的软件包名称示例:NAME=ChipdesignersneedCADapplicationsoftwaretodesignabcchips.
Runsonlyonxyzhardwareandisinstalledintheusrpartition.
定义软件包类别(CATEGORY)pkginfo文件中的CATEGORY参数指定软件包所属的类别.
一个软件包至少必须属于system或application类别.
类别名称由字母数字字符组成.
类别名称的最大长度为16个字符,且不区分大小写.
如果一个软件包属于多个类别,请以逗号分隔的列表形式指定这些类别.

以下是pkginfo文件中的CATEGORY规范示例:CATEGORY=system如何创建pkginfo文件使用您喜爱的文本编辑器,创建一个名为pkginfo的文件.
可在系统上的任意位置创建此文件.
编辑该文件并定义五个必需的参数.
这五个必需的参数是:PKG、NAME、ARCH、VERSION和CATEGORY.
有关这些参数的更多信息,请参见第23页中的"创建pkginfo文件".
向文件中添加任何可选参数.
创建您自己的参数,或参见pkginfo(4)手册页了解有关标准参数的信息.
保存所做更改,然后退出编辑器.
创建pkginfo文件此示例显示了一个有效pkginfo文件的内容,其中定义了五个必需的参数以及BASEDIR参数.
将会在第30页中的"path字段"中更详细地讨论BASEDIR参数.
1234示例2–1创建pkginfo文件应用程序包开发者指南2009年4月26PKG=SUNWcadapNAME=ChipdesignersneedCADapplicationsoftwaretodesignabcchips.
Runsonlyonxyzhardwareandisinstalledintheusrpartition.
ARCH=sparcVERSION=release1.
0CATEGORY=systemBASEDIR=/opt请参见第27页中的"如何组织软件包的内容".
组织软件包的内容将软件包对象以分层目录结构进行组织,该结构会模仿软件包对象安装到目标系统上之后的结构.
如果您在创建prototype文件之前执行此步骤,可节省创建该文件的时间和工作量.
如何组织软件包的内容确定您需要创建的软件包数目,以及哪些软件包对象应位于每个软件包中.

要获得完成此步骤的帮助,请参见第16页中的"生成软件包之前的注意事项".
为每个需要生成的软件包创建一个目录.
可在系统上的任意位置创建该目录,并随意进行命名.
本章中的示例假定软件包目录的名称与软件包缩写相同.
$cd/home/jane$mkdirSUNWcadap将每个软件包中的软件包对象组织为相应软件包目录下的目录结构.
该目录结构必须模仿软件包对象在目标系统上的结构.
例如,CAD应用程序软件包SUNWcadap必须具有以下目录结构.
另请参见123组织软件包的内容第2章生成软件包27确定您将保存信息文件的位置.
如果合适,请创建一个目录,将这些文件保存在同一位置.
以下示例假定来自第26页中的"如何创建pkginfo文件"中的pkginfo示例文件在Jane的主目录中创建.
$cd/home/jane$mkdirInfoFiles$mvpkginfoInfoFiles请参见第38页中的"如何使用pkgproto命令创建prototype文件".
创建prototype文件prototype文件是一种ASCII文件,用于指定有关软件包中对象的信息.
prototype文件中的每个条目描述一个对象,例如数据文件、目录、源文件或可执行对象.
prototype文件中的条目由若干个用空格分隔的信息字段组成.
请注意,这些字段必须按特定顺序出现.
注释行以井号(#)开头,将被忽略.
您可以使用文本编辑器或使用pkgproto命令创建prototype文件.
首次创建此文件时,使用pkgproto命令可能更容易,因为该命令基于您先前创建的目录分层结构来创建文件.
如果您没有根据第27页中的"组织软件包的内容"中所述组织文件,您不得不使用喜爱的文本编辑器从头开始创建prototype文件,这一任务比较繁琐.
prototype文件的格式以下是prototype文件中每一行的格式:partftypeclasspathmajorminormodeownergroupmansrcfileswindexman1file3.
1file4.
1file5file6/home/janeSUNWcadaplibfile2demofile14另请参见创建prototype文件应用程序包开发者指南2009年4月28part可选的数字字段,可用于将软件包对象分组为各部分.
缺省值为part1(第1部分).
ftype单字符字段,用于指定对象类型.
请参见第29页中的"ftype字段".
class表示对象所属的安装类.
请参见第30页中的"class字段".
path绝对或相对路径名,指示软件包对象在目标系统上的驻留位置.
请参见第30页中的"path字段".
major块特殊设备或字符特殊设备的主设备编号.
minor块特殊设备或字符特殊设备的次要设备编号.
mode对象的八进制模式(例如,0644).
请参见第32页中的"mode字段".
owner对象的所有者(例如,bin或root).
请参见第33页中的"owner字段".
group对象所属的组(例如bin或sys).
请参见第33页中的"group字段".
通常,只会定义ftype、class、path、mode、owner和group字段.
以下各节将介绍这些字段.
有关这些字段的附加信息,请参见prototype(4)手册页.
ftype字段ftype(文件类型)字段是一个单字符字段,用于指定软件包对象的文件类型.
下表中介绍了有效的文件类型.
表2–3prototype文件中的有效文件类型文件类型字段值文件类型说明f标准可执行文件或数据文件e在安装或删除时将编辑的文件(可由几个软件包共享)v可变文件(其内容预计会更改,例如日志文件)d目录x只能由该软件包访问的专用目录(可能包含未注册的日志或数据库信息)l链接文件p命名管道c字符特殊设备创建prototype文件第2章生成软件包29表2–3prototype文件中的有效文件类型(续)文件类型字段值文件类型说明b块特殊设备i信息文件或安装脚本s符号链接class字段class字段用于指定对象所属的类.
使用类是一种可选的软件包设计功能.
将会在第62页中的"编写类操作脚本"中详细讨论此功能.
如果您不使用类,则对象属于none类.
当执行pkgmk命令生成软件包时,该命令会在pkginfo文件中插入CLASSES=none参数.
文件类型为i的文件必须有一个空的class字段.
path字段path字段用于定义软件包对象在目标系统上的驻留位置.
您可以使用绝对路径名(例如/usr/bin/mail)或相对路径名(例如bin/mail)来指示该位置.
使用绝对路径名意味着对象在目标系统上的位置是由软件包定义的,不能更改.
使用相对路径名的软件包对象表明该对象是可重定位的.
可重定位对象在目标系统上不需要绝对路径位置.
此类对象的位置是在安装过程中确定的.
可将所有软件包对象或某些软件包对象定义为可重定位.
在编写任何安装脚本或创建prototype文件之前,请确定软件包对象将有固定位置(例如/etc中的启动脚本)还是可重定位的.
可重定位对象分为两种:可共同重定位的对象和可单独重定位的对象.
可共同重定位的对象可共同重定位的对象相对于一个称作基目录的通用安装基本位置进行定位.
基目录在pkginfo文件中由BASEDIR参数定义.
例如,prototype文件中一个名为tests/generic的可重定位对象要求pkginfo文件定义缺省BASEDIR参数.
例如:BASEDIR=/opt此示例意味着,对象安装后将位于/opt/tests/generic目录中.
注–/opt目录是不属于基本Solaris软件的软件可以交付到的唯一目录.
创建prototype文件应用程序包开发者指南2009年4月30只要可能,请尽量使用可共同重定位的对象.
一般来说,可以使用指定了绝对路径的几个文件(例如/etc或/var中的文件)来重定位一个软件包的主要部分.
但是,如果一个软件包包含许多不同的重定位对象,请考虑将该软件包分成在pkginfo文件中具有明显不同BASEDIR值的多个软件包.
可单独重定位的对象可单独重定位的对象不限于定位到可共同重定位的对象所在的目录位置.
要定义一个可单独重定位的对象,需要在prototype文件的path字段中指定一个安装变量.
指定安装变量之后,创建一个request脚本来提示安装人员输入可重定位基目录,或者创建一个checkinstall脚本基于文件系统数据确定路径名.
有关request脚本的更多信息,请参见第56页中的"编写request脚本";有关checkinstall脚本的信息,请参见第59页中的"如何收集文件系统数据".
注意–可单独重定位的对象很难管理.
使用可单独重定位的对象可能导致软件包组件的位置四处分散,这样在安装软件包的多个版本或体系结构时很难分离这些组件.
只要可能,请尽量使用可共同重定位的对象.
参数化路径名参数化路径名是包含变量规范的路径名.
例如,/opt/$PKGINST/filename是一个参数化路径名,因为含有$PKGINST变量规范.
必须在pkginfo文件中为该变量规范定义一个缺省值.
然后可以通过request脚本或checkinstall脚本更改该值.
路径中的变量规范必须位于路径名的开头或结尾,或者由斜线(/)分隔.
有效的参数化路径名采用以下形式:$PARAM/teststests/$PARAM/generic/tests/$PARAM一旦定义了变量规范,可能会导致将路径计算为绝对或可重定位路径.
在下面的示例中,prototype文件包含以下条目:fnone$DIRLOC/tests/genericpkginfo文件包含以下条目:DIRLOC=/myopt路径名$DIRLOC/tests/generic计算为绝对路径名/myopt/tests/generic(无论是否在pkginfo文件中设置了BASEDIR参数).
在此示例中,prototype文件与前面的示例中完全相同,而pkginfo文件包含以下条目:创建prototype文件第2章生成软件包31DIRLOC=firstcutBASEDIR=/opt路径名$DIRLOC/tests/generic将计算为可重定位的路径名/opt/firstcut/tests/generic.
有关参数化路径名的更多信息,请参见第117页中的"使用参数化基目录".
关于对象的源位置和目标位置的简要说明prototype文件中的path字段定义对象在目标系统上的位置.
如果软件包对象的目录结构不模仿目标系统上的预期结构,请在prototype文件中指定其当前位置.
有关设置软件包对象结构的更多信息,请参见第27页中的"组织软件包的内容".
如果您开发区域没有将软件包设置为所需的结构,可在path字段中使用path1=path2格式.
在此格式中,path1是对象应该在目标系统上所处的位置,而path2是对象在您系统中的位置.
还可以在path1=path2路径名格式中以path1表示可重定位对象的名称,而path2表示该对象在您系统上的完整路径名.
注–path1不能包含未定义的生成变量,但是可以包含未定义的安装变量.
path2不能包含任何未定义的变量,虽然可以使用生成变量和安装变量.
有关安装变量与生成变量之间区别的信息,请参见第22页中的"软件包环境变量".
因为链接是通过pkgadd命令创建的,因此它们必须使用path1=path2格式.
通常,链接的path2决不应是绝对的,而是应该相对于path1的目录部分.
使用path1=path2格式的一个替代方法是使用!
search命令.
有关更多信息,请参见第37页中的"为pkgmk命令提供搜索路径".
mode字段mode字段可以包含八进制数、问号()或变量规范.
八进制数指定对象安装在目标系统上时的模式.
表示在安装对象时模式不会更改,暗指在目标系统中已经存在同名对象.
$mode形式的变量规范(其中变量的首字母必须是小写字母)意味着将会在生成软件包时设置此字段.
请注意,此变量必须在生成时在prototype文件中或作为pkgmk命令的一个选项定义.
有关安装变量与生成变量之间区别的信息,请参见第22页中的"软件包环境变量".
文件类型为i(信息文件)、l(硬链接)和s(符号链接)的文件应将该字段留空.
创建prototype文件应用程序包开发者指南2009年4月32owner字段owner字段可以包含用户名、问号()或变量规范.
用户名最多可包含14个字符,并且应该是目标系统中已经存在的名称(例如bin或root).
表示在安装对象时所有者不会更改,暗指在目标系统中已经存在同名对象.
变量规范的形式可以是$Owner或$owner,其中变量的首字母是大写字母或小写字母.
如果变量首字母为一个小写字母,则必须在生成软件包时在prototype文件中或作为pkgmk命令的一个选项定义该变量.
如果变量首字母为大写字母,系统会将变量规范插入pkginfo文件中作为缺省值,并且可以在安装时通过request脚本重新定义.
有关安装变量与生成变量之间区别的信息,请参见第22页中的"软件包环境变量".
文件类型为i(信息文件)和l(硬链接)的文件应将该字段留空.
group字段group字段可以包含组名、问号()或变量规范.
组名最多可包含14个字符,并且应该是目标系统中已经存在的名称(例如bin或sys).
表示在安装对象时组不会更改,暗指在目标系统中已经存在同名对象.
变量规范的形式可以是$Group或$group,其中变量的首字母是大写字母或小写字母.
如果变量首字母为一个小写字母,则必须在生成软件包时在prototype文件中或作为pkgmk命令的一个选项定义该变量.
如果变量首字母为大写字母,系统会将变量规范插入pkginfo文件中作为缺省值,并且可以在安装时通过request脚本重新定义.
有关安装变量与生成变量之间区别的信息,请参见第22页中的"软件包环境变量".
文件类型为i(信息文件)和l(硬链接)的文件应将该字段留空.
从头创建prototype文件如果您想要从头创建prototype文件,可以使用喜爱的文本编辑器创建,为每个软件包对象添加一个条目.
有关该文件格式的更多信息,请参见第28页中的"prototype文件的格式"和prototype(4)手册页.
不过,在定义了每个软件包对象之后,您可能希望包括第36页中的"向prototype文件添加功能"中描述的某些功能.
示例-使用pkgproto命令创建prototype文件只要您按照第27页中的"组织软件包的内容"中所述组织了您的软件包目录结构,就可以使用pkgproto命令生成基本prototype文件.
例如,使用在前面各节中所述的样例目录结构和pkginfo文件时,创建prototype文件的命令如下所示:$cd/home/jane$pkgproto.
/SUNWcadap>InfoFiles/prototypeprototype文件如下所示:创建prototype文件第2章生成软件包33dnoneSUNWcadap0755janestaffdnoneSUNWcadap/demo0755janestafffnoneSUNWcadap/demo/file10555janestaffdnoneSUNWcadap/srcfiles0755janestafffnoneSUNWcadap/srcfiles/file50555janestafffnoneSUNWcadap/srcfiles/file60555janestaffdnoneSUNWcadap/lib0755janestafffnoneSUNWcadap/lib/file20644janestaffdnoneSUNWcadap/man0755janestafffnoneSUNWcadap/man/windex0644janestaffdnoneSUNWcadap/man/man10755janestafffnoneSUNWcadap/man/man1/file4.
10444janestafffnoneSUNWcadap/man/man1/file3.
10444janestaff注–生成软件包的人员的实际所有者和组由pkgproto命令记录.
一种较好的方法是使用chown-R和chgrp-R命令,在运行pkgproto命令之前根据需要设置所有者和组.
此prototype示例文件不是完整文件.
有关完成该文件的信息,请参见下一节.
优化使用pkgproto命令创建的prototype文件虽然pkgproto命令在创建初始prototype文件时很有用,但它不会为每个需要定义的软件包对象创建条目.
此命令不创建全部条目.
pkgproto命令不执行以下任一工作:为文件类型为v(可变文件)、e(可编辑的文件)、x(专用目录)或i(信息文件或安装脚本)的对象创建全部条目使用一个调用支持多个类创建文件类型为v、e、x和i的对象条目至少,您需要修改prototype文件,以添加文件类型为i的对象.
如果您将信息文件和安装脚本存储在软件包目录的第一级中(例如/home/jane/SUNWcadap/pkginfo),则prototype文件中的一个条目将如下所示:ipkginfo如果您没有将信息文件和安装脚本存储在软件包目录的第一级中,则需要指定它们的源位置.
例如:ipkginfo=/home/jane/InfoFiles/pkginfo或者,可以使用!
search命令指定位置,供pkgmk命令在生成软件包时进行查找.
有关更多信息,请参见第37页中的"为pkgmk命令提供搜索路径".
要为文件类型为v、e和x的对象添加条目,请遵循第28页中的"prototype文件的格式"中所述的格式,或参阅prototype(4)手册页.
创建prototype文件应用程序包开发者指南2009年4月34注–切记在任何时候都为文件类型为e(可编辑)的文件指定一个类,并为该类指定一个关联的类操作脚本.
否则,在删除软件包期间这类文件将被删除,即使与其他软件包共享路径名时也是如此.
使用多个类定义如果使用pkgproto命令创建基本prototype文件,可以将所有软件包对象指定给none类或一个特定类.
如第33页中的"示例-使用pkgproto命令创建prototype文件"中所示,基本pkgproto命令将所有对象指定给none类.
要将所有对象指定给一个特定类,可使用-c选项.
例如:$pkgproto-cclassname/home/jane/SUNWcadap>/home/jane/InfoFiles/prototype如果使用多个类,您可能需要手动编辑prototype文件,并修改每个对象的class字段.
如果使用类,您还需要在pkginfo文件中定义CLASSES参数并编写类操作脚本.
使用类是可选功能,将在第62页中的"编写类操作脚本"中进行详细讨论.
示例-优化使用pkgproto命令创建的prototype文件对于在第33页中的"示例-使用pkgproto命令创建prototype文件"中使用pkgproto命令创建的prototype文件,需要进行几处修改.
需要有一个pkginfo文件的条目.
需要将path字段更改为path1=path2格式,因为软件包源位置位于/home/jane.
由于软件包源位置是一个分层目录,并且!
search命令不递归搜索,因此使用path1=path2格式也许会更轻松.
owner和group字段应该包含目标系统上现有用户和组的名称.
也就是说,所有者jane将会导致错误,因为该所有者不属于SunOSTM操作系统.
修改后的prototype文件如下所示:ipkginfo=/home/jane/InfoFiles/pkginfodnoneSUNWcadap=/home/jane/SUNWcadap0755rootsysdnoneSUNWcadap/demo=/home/jane/SUNWcadap/demo0755rootbinfnoneSUNWcadap/demo/file1=/home/jane/SUNWcadap/demo/file10555rootbindnoneSUNWcadap/srcfiles=/home/jane/SUNWcadap/srcfiles0755rootbinfnoneSUNWcadap/srcfiles/file5=/home/jane/SUNWcadap/srcfiles/file50555rootbinfnoneSUNWcadap/srcfiles/file6=/home/jane/SUNWcadap/srcfiles/file60555rootbindnoneSUNWcadap/lib=/home/jane/SUNWcadap/lib0755rootbinfnoneSUNWcadap/lib/file2=/home/jane/SUNWcadap/lib/file20644rootbindnoneSUNWcadap/man=/home/jane/SUNWcadap/man0755binbinfnoneSUNWcadap/man/windex=/home/jane/SUNWcadap/man/windex0644roototherdnoneSUNWcadap/man/man1=/home/jane/SUNWcadap/man/man10755binbinfnoneSUNWcadap/man/man1/file4.
1=/home/jane/SUNWcadap/man/man1/file4.
10444binbinfnoneSUNWcadap/man/man1/file3.
1=/home/jane/SUNWcadap/man/man1/file3.
10444binbin创建prototype文件第2章生成软件包35向prototype文件添加功能除了在prototype文件中定义每个软件包对象外,您还可以执行以下操作:定义要在安装时创建的其他对象.
在安装时创建链接.
将软件包分发在多个卷上.
嵌套prototype文件.
为mode、owner和group字段设置缺省值.
为pkgmk命令提供搜索路径.
设置环境变量.
有关进行这些更改的信息,请参见以下各节.
定义要在安装时创建的其他对象可以使用prototype文件定义在安装介质上实际没有提供的对象.
在安装期间,如果这些对象尚不存在,则使用pkgadd命令创建的对象将具有所需的文件类型.
要指定将在目标系统上创建对象,请在prototype文件中使用适当文件类型为其添加一个条目.
例如,如果您要在目标系统上创建目录,但是不想在安装介质上提供该目录,请在prototype文件中为其添加以下条目:dnone/directory0644rootother如果您希望在目标系统上创建一个空文件,prototype文件中该文件的条目可能如下所示:fnonefilename=/dev/null0644binbin必须在安装介质上提供的对象只有常规文件和编辑脚本(文件类型e、v、f)以及包含这些内容所需的目录.
所有其他对象的创建都与提供的对象、目录、命名管道、设备、硬链接和符号链接无关.

在安装时创建链接要在软件包安装期间创建链接,请在链接对象的prototype文件条目中定义以下内容:其文件类型:l(链接)或s(符号链接).
链接对象的path1=path2格式的路径名,其中path1是目标文件,path2是源文件.
通常,链接的path2决不应是绝对的,而是应该相对于path1的目录部分.
例如,定义符号链接的prototype文件条目可能如下所示:snoneetc/mount=.
.
/usr/etc/mount无论软件包是安装为绝对还是可重定位软件包,都将以这种方式指定相对链接.

创建prototype文件应用程序包开发者指南2009年4月36将软件包分发到多个卷上使用pkgmk命令生成软件包时,该命令将执行组织多卷软件包所需的计算和操作.
一个多卷软件包称为分段的软件包.
不过,您可以在prototype文件中使用可选part字段定义希望对象所处的部分.
此字段中的一个数字将重写pkgmk命令,并强制将组件放置到该字段中指定的部分.
请注意,对于设置为文件系统格式的可移除介质,各部分和卷之间存在一对一的对应关系.
如果卷由开发者预先指定,当任何卷上存在空间不足情况时,pkgmk命令会引发错误.
嵌套prototype文件可以创建多个prototype文件,然后使用!
include命令将它们包括在prototype文件中.
您可能需要嵌套文件以更便于维护.
在以下示例中有三个prototype文件.
主文件(prototype)正被编辑.
另外两个文件(proto2和proto3)是要包括的文件.
!
include/source-dir/proto2!
include/source-dir/proto3为mode、owner和group字段设置缺省值要为特定软件包对象的mode、owner和group字段设置缺省值,可将!
default命令插入到prototype文件中.
例如:!
default0644rootother注–!
default命令的作用域从插入位置开始直到文件结束.
该命令的作用域不包括内含的文件.
但是,对于您知道在目标系统(例如/usr或/etc/vfstab)上存在的目录(文件类型d)和可编辑文件(文件类型e),请确保prototype文件中的mode、owner和group字段设置为问号().
这样就不会销毁站点管理员可能已修改的现有设置.
为pkgmk命令提供搜索路径如果软件包对象的源位置与其目标位置不同,并且您不希望使用第32页中的"关于对象的源位置和目标位置的简要说明"中所述的path1=path2格式,则可以在prototype文件中使用!
search命令.
例如,如果您在自己的主目录中创建了目录pkgfiles,并且该目录包含您的所有信息文件和安装脚本,可以指定在使用pkgmk命令生成软件包时搜索该目录.
在prototype文件中该命令将如下所示:创建prototype文件第2章生成软件包37!
search/home-dir/pkgfiles注–搜索请求不涉及内含的文件.
另外,搜索仅限于列出的特定目录,而且不进行递归搜索.
设置环境变量也可以向prototype文件中添加!
PARAM=value形式的命令.
此形式的命令可在当前环境中定义变量.
如果有多个prototype文件,则此命令的作用域是局部的,仅限于定义它的prototype文件.
PARAM变量的首字母可以是小写字母或大写字母.
如果PARAM变量的值在生成时未知,pkgmk命令将出错而异常中止.
有关生成变量与安装变量之间区别的更多信息,请参见第22页中的"软件包环境变量".
如何使用pkgproto命令创建prototype文件注–在创建prototype文件之前创建信息文件和安装脚本会更容易,但这种顺序并非是必需的.
您始终可在更改软件包内容之后编辑prototype文件.
有关信息文件和安装脚本的更多信息,请参见第3章,增强软件包的功能(任务).
确定哪些软件包对象将是绝对的,哪些软件包对象是可重定位的(如果尚未确定).

有关帮助您完成此步骤的信息,请参见第30页中的"path字段".
组织软件包对象,以模仿其在目标系统上的位置.
如果您已经按照第27页中的"组织软件包的内容"中所述组织了软件包,请注意,您可能需要根据步骤1中所做的决策进行一些更改.
如果您尚未组织软件包,现在应该进行组织.
如果您不组织软件包,则不能使用pkgproto命令创建基本prototype文件.
如果您的软件包有可共同重定位的对象,请编辑pkginfo文件将BASEDIR参数设置为适当的值.
例如:BASEDIR=/opt有关可共同重定位对象的信息,请参见第30页中的"可共同重定位的对象".
如果您的软件包有可单独重定位的对象,请创建request脚本,以提示安装人员输入适当的路径名.
或者,创建checkinstall脚本,以基于文件系统数据确定适当的路径.
以下列表提供了关于常见任务的参考资料页码:要创建request脚本,请参见第57页中的"如何编写request脚本".
要创建checkinstall脚本,请参见第59页中的"如何收集文件系统数据".
1234创建prototype文件应用程序包开发者指南2009年4月38有关可单独重定位对象的更多信息,请参见第31页中的"可单独重定位的对象".
将您的软件包组件的所有者和组更改为目标系统上所需的所有者和组.

对软件包目录和信息文件目录使用chown-R和chgrp-R命令.
执行pkgproto命令创建基本prototype文件.
pkgproto命令会扫描您的目录来创建基本文件.
例如:$cdpackage-directory$pkgproto.
/package-directory>prototypeprototype文件可位于您系统上的任意位置.
将信息文件和安装脚本保存在一个位置可简化访问和维护.
有关pkgproto命令的附加信息,请参见pkgproto(1)手册页.
使用您喜爱的文本编辑器编辑prototype文件,并为类型为v、e、x和i的文件添加条目.
有关您可能需要进行的特定更改的信息,请参见第34页中的"优化使用pkgproto命令创建的prototype文件".
(可选)如果您使用多个类,请编辑prototype和pkginfo文件.
使用您喜爱的文本编辑器进行必要的更改,并创建相应的类操作脚本.
有关您可能需要进行的特定更改的信息,请参见第34页中的"优化使用pkgproto命令创建的prototype文件"和第62页中的"编写类操作脚本".
使用您喜爱的文本编辑器编辑prototype文件,以便重新定义路径名和更改其他字段设置.
有关更多信息,请参见第34页中的"优化使用pkgproto命令创建的prototype文件".
(可选)使用您喜爱的文本编辑器编辑prototype文件,以便向prototype文件添加功能.
有关更多信息,请参见第36页中的"向prototype文件添加功能".
保存所做更改,然后退出编辑器.
如果您已准备好执行下一个任务,请参见第41页中的"如何生成软件包".
567891011另请参见创建prototype文件第2章生成软件包39生成软件包可使用pkgmk命令生成软件包.
pkgmk命令可执行以下任务:将prototype文件中定义的所有对象放入目录格式中.
创建pkgmap文件,该文件将替换prototype文件.
生成用作pkgadd命令的输入的可安装软件包.
使用最简单的pkgmk命令此命令最简单的形式是不带任何选项的pkgmk命令.
在使用不带选项的pkgmk命令之前,请确保您的当前工作目录包含软件包的prototype文件.
命令的输出、文件和目录都被写入/var/spool/pkg目录.
pkgmap文件当使用pkgmk命令生成软件包时,它将创建一个替换prototype文件的pkgmap文件.
来自上一个示例中的pkgmap文件包含以下内容:$morepkgmap:131701dnoneSUNWcadap0755rootsys1dnoneSUNWcadap/demo0755rootbin1fnoneSUNWcadap/demo/file10555rootbin14868456178375274961dnoneSUNWcadap/lib0755rootbin1fnoneSUNWcadap/lib/file20644rootbin1551792623728375274991dnoneSUNWcadap/man0755binbin1dnoneSUNWcadap/man/man10755binbin1fnoneSUNWcadap/man/man1/file3.
10444binbin3700429898375275001fnoneSUNWcadap/man/man1/file4.
10444binbin1338440108375274991fnoneSUNWcadap/man/windex0644rootother157132758375274991dnoneSUNWcadap/srcfiles0755rootbin1fnoneSUNWcadap/srcfiles/file50555rootbin12208202808375274971fnoneSUNWcadap/srcfiles/file60555rootbin12256632368375274971ipkginfo14010941837531104$此文件格式非常类似于prototype文件的格式.
但是,pkgmap文件包含以下信息:第一行指示了软件包所分布的卷的数量,以及软件包安装后的近似大小.

例如:13170表明软件包分布在一个卷上,在安装后占用大约3170个512字节块.
有三个额外字段定义了每个软件包对象的大小、校验和和修改时间.
软件包对象根据类和路径名按照字母顺序列出,从而减少了安装软件包所需的时间.
生成软件包应用程序包开发者指南2009年4月40如何生成软件包创建pkginfo文件,如果尚未创建.
有关逐步说明,请参见第26页中的"如何创建pkginfo文件".
创建prototype文件,如果尚未创建.
有关逐步说明,请参见第38页中的"如何使用pkgproto命令创建prototype文件".
将您的当前工作目录设置为包含软件包的prototype文件的目录.
生成软件包.
$pkgmk[-o][-aarch][-bbase-src-dir][-ddevice][-ffilename][-llimit][-ppstamp][-rrootpath][-vversion][PARAM=value][pkginst]-o覆写软件包的现有版本.
-aarch重写pkginfo文件中的体系结构信息.
-bbase-src-dir当pkgmk命令在开发系统上搜索对象时,要求将base-src-dir添加到可重定位路径名的开头.
-ddevice指定应将软件包复制到device上(可能是一个绝对目录路径名、磁盘或可移除磁盘).
-ffilename指定一个文件filename作为您的prototype文件.
缺省名称是prototype或Prototype.
-llimit以512字节块为单位指定输出设备的最大大小.
-ppstamp重写pkginfo文件中的生产标记定义.
-rrootpath请求将根目录rootpath用于在开发系统上定位对象.
-vversion重写pkginfo文件中的版本信息.
PARAM=value设置全局环境变量.
首字母为小写字母的变量在生成时被解析.
首字母为大写字母的变量被放置到pkginfo文件中供安装时使用.
pkginst按软件包缩写或特定实例(例如,SUNWcadap.
4)指定软件包.
有关更多信息,请参见pkgmk(1)手册页.
验证软件包的内容.
$pkgchk-ddevice-namepkg-abbrevCheckinguninstalleddirectoryformatpackagepkg-abbrevfromdevice-name##Checkingcontrolscripts.
##Checkingpackageobjects.
12345生成软件包第2章生成软件包41##Checkingiscomplete.
$-ddevice-name指定软件包的位置.
请注意,device-name可以是完整目录路径名或者磁带或可移除磁盘的标识符.
pkg-abbrev待检查的一个或多个软件包(由空格分隔)的名称.
如果省略,pkgchk命令将检查所有可用的软件包.
pkgchk命令会列出检查软件包的哪些方面,并根据情况显示警告或错误.
有关pkgchk命令的更多信息,请参见第80页中的"验证软件包的完整性".
注意–应该非常认真地对待错误.
错误可能意味着需要修正脚本.
如果您不认同pkgchk命令的输出,请检查所有错误,然后继续.
生成软件包此示例使用在第34页中的"优化使用pkgproto命令创建的prototype文件"中创建的prototype文件.
$cd/home/jane/InfoFiles$pkgmk##Buildingpkgmapfrompackageprototypefile.
##Processingpkginfofile.
WARNING:parametersetto"system990708093144"WARNING:parametersetto"none"##Attemptingtovolumize13entriesinpkgmap.
part1--3170blocks,17entries##Packagingonepart.
/var/spool/pkg/SUNWcadap/pkgmap/var/spool/pkg/SUNWcadap/pkginfo/var/spool/pkg/SUNWcadap/reloc/SUNWcadap/demo/file1/var/spool/pkg/SUNWcadap/reloc/SUNWcadap/lib/file2/var/spool/pkg/SUNWcadap/reloc/SUNWcadap/man/man1/file3.
1/var/spool/pkg/SUNWcadap/reloc/SUNWcadap/man/man1/file4.
1/var/spool/pkg/SUNWcadap/reloc/SUNWcadap/man/windex/var/spool/pkg/SUNWcadap/reloc/SUNWcadap/srcfiles/file5/var/spool/pkg/SUNWcadap/reloc/SUNWcadap/srcfiles/file6##Validatingcontrolscripts.
##Packagingcomplete.
$示例2–2生成软件包应用程序包开发者指南2009年4月42指定可重定位文件的源目录如果您的软件包中包含可重定位文件,可使用pkgmk命令的-bbase-src-dir选项,来指定在创建软件包期间将添加到可重定位路径名开头的路径名.
如果您没有为可重定位文件使用path1=path2格式,或没有在prototype文件中使用!
search命令指定搜索路径,该选项很有用.
以下命令将生成具有下列特征的软件包:该软件包是使用pkgproto命令创建的prototype样例文件生成的.
有关更多信息,请参见第33页中的"示例-使用pkgproto命令创建prototype文件".
生成软件包时没有修改path字段.
软件包会为pkginfo文件添加一个条目.
$cd/home/jane/InfoFiles$pkgmk-o-b/home/jane##Buildingpkgmapfrompackageprototypefile.
##Processingpkginfofile.
WARNING:parametersetto"system960716102636"WARNING:parametersetto"none"##Attemptingtovolumize13entriesinpkgmap.
part1--3170blocks,17entries##Packagingonepart.
/var/spool/pkg/SUNWcadap/pkgmap/var/spool/pkg/SUNWcadap/pkginfo/var/spool/pkg/SUNWcadap/reloc/SUNWcadap/demo/file1/var/spool/pkg/SUNWcadap/reloc/SUNWcadap/lib/file2/var/spool/pkg/SUNWcadap/reloc/SUNWcadap/man/man1/file3.
1/var/spool/pkg/SUNWcadap/reloc/SUNWcadap/man/man1/file4.
1/var/spool/pkg/SUNWcadap/reloc/SUNWcadap/man/windex/var/spool/pkg/SUNWcadap/reloc/SUNWcadap/srcfiles/file5/var/spool/pkg/SUNWcadap/reloc/SUNWcadap/srcfiles/file6##Validatingcontrolscripts.
##Packagingcomplete.
在此示例中,通过指定-o选项在缺省目录/var/spool/pkg中生成软件包.
此选项会覆写在示例2–2中创建的软件包.
为信息文件和软件包对象指定不同的源目录如果您将软件包信息文件(例如pkginfo和prototype)和软件包对象放置在两个不同的目录中,可使用pkgmk命令的-bbase-src-dir和-rrootpath选项创建软件包.
如果您的软件包对象位于名为/product/pkgbin的目录中,而其他软件包信息文件位于名为/product/pkgsrc的目录,可以使用以下命令将软件包放置在/var/spool/pkg目录下:$pkgmk-b/product/pkgbin-r/product/pkgsrc-f/product/pkgsrc/prototype示例2–3示例2–4生成软件包第2章生成软件包43可选择使用以下命令获得相同结果:$cd/product/pkgsrc$pkgmk-o-b/product/pkgbin在此示例中,pkgmk命令使用当前工作目录查找软件包的剩余部分(例如prototype和pkginfo信息文件).
如果您要为软件包添加任何可选信息文件和安装脚本,请参见第3章,增强软件包的功能(任务).
否则,在生成软件包之后,应该验证其完整性.
第4章,验证和转换软件包介绍了如何执行此任务,并提供了有关如何将经过验证的软件包转换为分发介质的逐步说明.
另请参见生成软件包应用程序包开发者指南2009年4月44增强软件包的功能(任务)本章介绍如何为软件包创建可选信息文件和安装脚本.
第2章,生成软件包中讨论了生成软件包的最低要求,而本章将讨论可以生成到软件包的附加功能.
此附加功能基于您在计划如何设计软件包时所考虑的准则.
有关更多信息,请参见第16页中的"生成软件包之前的注意事项".
以下是本章中概述信息的列表.
第45页中的"创建信息文件和安装脚本(任务图)"第46页中的"创建信息文件"第52页中的"创建安装脚本"第69页中的"创建带签名的软件包"创建信息文件和安装脚本(任务图)以下任务图描述了您可以生成到软件包的可选功能.
表3–1创建信息文件和安装脚本(任务图)任务说明参考1.
创建信息文件定义软件包相关性利用软件包相关性的定义,可以指定您的软件包是否与以前的版本兼容,是否依赖于其他软件包,或者其他软件包是否依赖于您的软件包.
第47页中的"如何定义软件包相关性"编写版权信息copyright文件为您的软件应用程序提供法律保护.
第49页中的"如何编写版权信息"3第3章45表3–1创建信息文件和安装脚本(任务图)(续)任务说明参考在目标系统上保留额外空间space文件在目标系统上留出了空间块,使您可以在安装期间创建未在pkgmap文件中定义的文件.
第51页中的"如何在目标系统上保留额外空间"2.
创建安装脚本获取来自安装人员的信息使用request脚本可以获取来自软件包安装人员的信息.
第57页中的"如何编写request脚本"收集安装所需的文件系统数据使用checkinstall脚本可以执行目标系统的分析,并为安装设置正确的环境或完全停止安装.
第59页中的"如何收集文件系统数据"编写过程脚本使用过程脚本可在安装或删除过程的特定阶段提供自定义的安装说明.
第61页中的"如何编写过程脚本"编写类操作脚本使用类操作脚本可指定在安装和删除软件包期间对特定软件包对象组执行的一组指令.
第68页中的"如何编写类操作脚本"创建信息文件此节讨论可选软件包信息文件.
使用这些文件,您可以定义软件包相关性,提供版权信息,以及在目标系统上保留额外空间.
定义软件包相关性您需要确定您的软件包是否依赖于其他软件包,以及是否有任何其他软件包依赖于您的软件包.
可使用以下两个可选软件包信息文件定义软件包相关性和不兼容性:compver和depend.
通过提供compver文件,您可以指定与正在安装的软件包兼容的以前软件包版本.
通过提供depend文件,您可以定义与您的软件包相关联的三种相关性类型.
这些相关性类型如下所示:先决软件包-您的软件包依赖于其他软件包的存在反向相关性-其他软件包依赖于您的软件包的存在创建信息文件应用程序包开发者指南2009年4月46注–只有当无法提供depend文件的软件包依赖于您的软件包时,才应使用反向相关性类型.
不兼容软件包-您的软件包与指定软件包不兼容depend文件只解析最基本的相关性.
如果您的软件包依赖于一个特定文件、其内容或者其行为,则depend文件不能提供足够的精确度.
在这种情况下,应该使用request脚本或checkinstall脚本进行详细的相关性检查.
checkinstall脚本也是唯一能够完全停止软件包安装过程的脚本.
注–请确认depend和compver文件在prototype文件中有对应条目.
文件类型应该是i(表示软件包信息文件).
有关更多信息,请参阅depend(4)和compver(4)手册页.
如何定义软件包相关性将包含信息文件的目录设置为当前工作目录.
如果存在您软件包的以前版本,并且您需要指定新软件包与其兼容,请使用您喜爱的文本编辑器创建名为compver的文件.
列出与您的软件包兼容的版本.
使用以下格式:stringstring.
.
.
对于每个兼容软件包,string值与在pkginfo文件中指定给VERSION参数的值完全相同.
保存所做更改,然后退出编辑器.
如果您的软件包依赖于其他软件包的存在、其他软件包依赖于您的软件包的存在,或者您的软件包与另一个软件包不兼容,请使用您喜爱的文本编辑器创建名为depend的文件.
为每种相关性添加一个条目.
使用以下格式:typepkg-abbrevpkg-name(arch)version(arch)version.
.
.
type定义相关性类型.
必须为以下字符之一:P(先决软件包)、I(不兼容软件包)或R(反向相关性).
pkg-abbrev指定软件包缩写,例如SUNWcadap.
1234创建信息文件第3章增强软件包的功能(任务)47pkg-name指定软件包全名,例如ChipdesignersneedCADapplicationsoftwaretodesignabcchips.
Runsonlyonxyzhardwareandisinstalledintheusrpartition.
(arch)可选.
指定运行软件包的硬件类型.
例如,sparc或x86.
如果您指定体系结构,必须使用括号作为分界符.
version可选.
指定pkginfo文件中为VERSION参数所赋的值.
有关更多信息,请参见depend(4).
保存所做更改,然后退出编辑器.
完成以下任务之一:如果您要创建其他信息文件和安装脚本,请跳至下一任务:第49页中的"如何编写版权信息".
如果您未创建prototype文件,请完成第38页中的"如何使用pkgproto命令创建prototype文件"过程.
跳至步骤7.
如果您已经创建了prototype文件,请编辑该文件,并为刚刚创建的每个文件添加一个条目.
生成您的软件包.
如果需要,请参见第41页中的"如何生成软件包".
compver文件在此示例中,有四个软件包版本:1.
0、1.
1、2.
0和新软件包3.
0.
新软件包与所有三个以前版本兼容.
最新版本的compver文件可能如下所示:release3.
0release2.
0version1.
11.
0这些条目不必按版本大小顺次排序.
但是,它们应与每个软件包的pkginfo文件中VERSION参数的定义完全匹配.
在此示例中,软件包设计人员对于前三个版本使用了不同的格式.
depend文件此示例假定样例软件包SUNWcadap要求SUNWcsr和SUNWcsu软件包已经安装在目标系统上.
SUNWcadap的depend文件如下所示:567示例3–1示例3–2创建信息文件应用程序包开发者指南2009年4月48PSUNWcsrCoreSolaris,(Root)PSUNWcsuCoreSolaris,(Usr)在生成软件包之后,请安装该软件包以确认它已正确安装并验证其完整性.
第4章,验证和转换软件包介绍了这些任务,并提供了有关如何将经过验证的软件包转换为分发介质的逐步说明.
编写版权信息您需要确定软件包是否应该在安装时显示版权信息.
如果是,请创建copyright文件.
注–应该包括copyright文件,以便为您的软件应用程序提供法律保护.
请与您公司的法律部门协商,以确定版权信息的准确措词.
要提供版权信息,必须创建名为copyright的文件.
在安装期间,信息将完全按照文件中的形式显示(无格式设置).
有关更多信息,请参见copyright(4)手册页.
注–请确认copyright文件在prototype文件中有对应条目.
文件类型应该是i(表示软件包信息文件).
如何编写版权信息将包含信息文件的目录设置为当前工作目录.
使用您喜爱的文本编辑器创建名为copyright的文件.
根据您希望在安装软件包时显示的信息键入版权信息的文本.
保存所做更改,然后退出编辑器.
完成以下任务之一:如果您要创建其他信息文件和安装脚本,请跳至下一任务:第51页中的"如何在目标系统上保留额外空间".
如果您未创建prototype文件,请完成第38页中的"如何使用pkgproto命令创建prototype文件"过程.
跳至步骤5.
如果您已经创建了prototype文件,请编辑该文件,并为刚刚创建的信息文件添加一个条目.
另请参见1234创建信息文件第3章增强软件包的功能(任务)49生成您的软件包.
如果需要,请参见第41页中的"如何生成软件包".
copyright文件例如,部分版权信息可能如下所示:Copyright(c)2003CompanyNameAllRightsReservedThisproductisprotectedbycopyrightanddistributedunderlicensesrestrictingcopying,distribution,anddecompilation.
在生成软件包之后,请安装该软件包以确认它已正确安装并验证其完整性.
第4章,验证和转换软件包介绍了这些任务,并提供了有关如何将经过验证的软件包转换为分发介质的逐步说明.
在目标系统上保留额外空间您需要确定软件包在目标系统上是否需要额外磁盘空间.
此空间是除软件包对象所需空间之外的空间.
如果是,请创建space信息文件.
此任务不同于在安装时创建空文件和目录,如第36页中的"定义要在安装时创建的其他对象"所述.
pkgadd命令可根据pkgmap文件中的对象定义确保有安装软件包所需的足够磁盘空间.
但是,除了pkgmap文件中定义的对象所需的磁盘空间之外,软件包还可能需要更多空间.
例如,软件包可能在安装后创建一个文件,该文件中可能包含数据库、日志文件,或者某个不断占用更多磁盘空间的文件.
为了保证为软件包保留了空间,您应该引入一个指定磁盘空间需求的space文件.
pkgadd命令可检查在space文件中指定的额外空间.
有关更多信息,请参阅space(4)手册页.
注–请确认space文件在prototype文件中有对应条目.
文件类型应该是i(表示软件包信息文件).
5示例3–3另请参见创建信息文件应用程序包开发者指南2009年4月50如何在目标系统上保留额外空间将包含信息文件的目录指定为当前工作目录.
使用您喜爱的文本编辑器创建名为space的文件.
指定软件包所需的所有额外磁盘空间需求.
使用以下格式:pathnameblocksinodespathname指定目录名,该目录可能是也可能不是文件系统的挂载点.
blocks指定您希望保留的512字节块的数目.
inodes指定所需的inode的数目.
有关更多信息,请参见space(4)手册页.
保存所做更改,然后退出编辑器.
完成以下任务之一.
如果您要创建安装脚本,请跳至下一任务:第57页中的"如何编写request脚本".
如果您未创建prototype文件,请完成第38页中的"如何使用pkgproto命令创建prototype文件"中的过程.
跳至步骤5.
如果您已经创建了prototype文件,请编辑该文件,并为刚刚创建的信息文件添加一个条目.
生成您的软件包.
如果需要,请参见第41页中的"如何生成软件包".
space文件以下space示例文件指定了将在目标系统的/opt目录中保留1000个512字节块和1个inode.
/opt10001在生成软件包之后,请安装该软件包以确认它已正确安装并验证其完整性.
第4章,验证和转换软件包介绍了这些任务,并提供了有关如何将经过验证的软件包转换为分发介质的逐步说明.
12345示例3–4另请参见创建信息文件第3章增强软件包的功能(任务)51创建安装脚本此节讨论可选的软件包安装脚本.
pkgadd命令可自动执行使用软件包信息文件作为输入安装软件包时所需的所有操作.
您不必提供任何软件包安装脚本.
不过,如果您要为软件包创建自定义的安装过程,可以使用安装脚本来实现.
安装脚本:必须可由Bourneshell(sh)执行必须包含Bourneshell命令和文本不必包含#!
/bin/shshell标识符不必是可执行文件可使用四种类型的安装脚本执行自定义的操作:request脚本request脚本请求来自正在安装软件包的管理员的数据,以指定或重新定义环境变量.
checkinstall脚本checkinstall脚本检查目标系统上是否有所需数据,可设置或修改软件包环境变量,以及确定安装是否继续.
注–checkinstall脚本自Solaris2.
5及兼容发行版开始可用.
过程脚本过程脚本指定在安装或删除软件包之前或之后将调用的过程.
四个过程脚本是preinstall、postinstall、preremove和postremove.
类操作脚本类操作脚本定义了应该在安装或删除期间应用于某类文件的一个操作或一组操作.
您可以定义自己的类.
或者,可以使用四个标准类(sed、awk、build和preserve)之一.
软件包安装期间的脚本处理您使用的脚本类型取决于安装过程中何时需要该脚本的操作.
软件包安装后,pkgadd命令执行以下步骤:1.
执行request脚本.
软件包只有在此步骤中才能从正在安装软件包的管理员请求输入.
2.
执行checkinstall脚本.
checkinstall脚本收集文件系统数据,并可创建或修改环境变量定义来控制后续安装.
有关软件包环境变量的更多信息,请参见第22页中的"软件包环境变量".
创建安装脚本应用程序包开发者指南2009年4月523.
执行preinstall脚本.
4.
为要安装的每个类安装软件包对象.
这些文件的安装按逐个类进行,并相应执行类操作脚本.
所处理的类列表及其安装顺序最初由pkginfo文件中的CLASSES参数定义.
不过,request脚本或checkinstall脚本可更改CLASSES参数的值.
有关安装期间如何处理类的更多信息,请参见第62页中的"软件包安装期间如何处理类".
a.
创建符号链接、设备、命名管道和所需目录.
b.
根据常规文件的类安装这些文件(文件类型e、v、f)仅针对要安装的常规文件执行类操作脚本.
所有其他软件包对象都根据pkgmap文件中的信息自动创建.
c.
创建所有硬链接.
5.
执行postinstall脚本.
软件包删除期间的脚本处理删除软件包时,pkgrm命令执行以下步骤:1.
执行preremove脚本.
2.
为每个类删除软件包对象删除也按逐个类进行.
删除脚本按照与安装时相反的顺序,根据CLASSES参数定义的序列进行处理.
有关安装期间如何处理类的更多信息,请参见第62页中的"软件包安装期间如何处理类".
a.
删除硬链接.
b.
删除常规文件.
c.
删除符号链接、设备和命名管道.
3.
执行postremove脚本.
request脚本不会在软件包删除时进行处理.
但是,该脚本的输出会保留在已安装的软件包中,供删除脚本使用.
request脚本的输出是环境变量列表.
对脚本可用的软件包环境变量以下环境变量组对所有安装脚本可用.
某些环境变量可由request脚本或checkinstall脚本修改.
除了必需的参数之外,request脚本或checkinstall脚本可设置或修改pkginfo文件中的任何标准参数.
pkginfo(4)手册页中详细介绍了标准安装参数.
创建安装脚本第3章增强软件包的功能(任务)53注–只能在Solaris2.
5发行版和兼容发行版及之后的发行版中修改BASEDIR参数.
您可定义自己的安装环境变量,方法是在pkginfo文件中为这些变量赋值.
这种环境变量只能含字母数字字符,且首字母必须大写.
这些环境变量中的任何一个都可由request脚本或checkinstall脚本更改.
request脚本和checkinstall脚本都可以定义新的环境变量,方法是为其赋值并将其放在安装环境中.
下表列出了通过环境对所有安装脚本可用的环境变量.
这些环境变量都不能由脚本修改.
环境变量说明CLIENT_BASEDIR相对于目标系统的基目录.
BASEDIR是从安装系统(一般是服务器)引用特定软件包对象时使用的变量,而CLIENT_BASEDIR是用于包括客户机系统中放置的文件的路径.
如果BASEDIR存在,则CLIENT_BASEDIR存在,而且在没有PKG_INSTALL_ROOT时与BASEDIR完全相同.
INST_DATADIR正在被读取的软件包所处的目录.
如果正从磁带读取软件包,此变量将是一个临时目录位置,其中软件包被转换为目录格式.
换句话说,假定软件包没有扩展名(例如SUNWstuff.
d),则当前软件包的request脚本将位于$INST_DATADIR/$PKG/install.
PATHsh在调用脚本时查找命令所用的搜索列表.
PATH通常设置为/sbin:/usr/sbin:/usr/bin:/usr/sadm/install/bin.
PKGINST正在安装的软件包的实例标识符.
如果尚未安装软件包的其他实例,则该值是软件包缩写(例如SUNWcadap).
否则,该值是带后缀的软件包缩写,例如SUNWcadap.
4.
PKGSAV可保存文件以供删除脚本使用的目录,或以前保存的文件所在的目录.
仅在Solaris2.
5发行版和兼容发行版中可用.
PKG_CLIENT_OS安装软件包的客户机的操作系统.
此变量的值是Solaris.
PKG_CLIENT_VERSIONx.
y格式的Solaris版本.
PKG_CLIENT_REVISIONSolaris内部版本修订版.
PKG_INSTALL_ROOT将软件包安装到的目标系统上的根文件系统.
只有当带有-R选项调用pkgadd和pkgrm命令时,此变量才存在.
这种有条件的存在有利于在过程脚本中以${PKG_INSTALL_ROOT}/somepath格式使用该变量.
PKG_NO_UNIFIED当带有-M和-R选项调用pkgadd和pkgrm命令时设置的环境变量.
此环境变量被传递给属于软件包环境的任何软件包安装脚本或软件包命令.
创建安装脚本应用程序包开发者指南2009年4月54环境变量说明UPDATE该环境变量在大多数安装环境下不存在.
如果此变量确实存在(值为yes),则表明以下两种情况之一.
一种情况是系统上已安装了名称、版本和体系结构均相同的软件包.
另一种情况是,该软件包正在根据管理员的指令覆写已安装的同名软件包.
在这些情况中,始终会使用原始基目录.
为脚本获取软件包信息在脚本中可使用两个命令请求获得关于软件包的信息:pkginfo命令可返回关于软件包的信息,例如实例标识符和软件包名称.
pkgparam命令可返回请求的环境变量的值.
有关更多信息,请参见pkginfo(1)手册页、pkgparam(1)手册页和第4章,验证和转换软件包.
脚本的退出代码每个脚本必须使用下表中所示的退出代码之一退出.
表3–2安装脚本退出代码代码含义0脚本成功完成.
1致命错误.
安装过程在此时终止.
2警告或可能的错误状态.
安装会继续.
在完成之时将显示一条警告消息.
3pkgadd命令完全停止.
只有checkinstall脚本会返回此代码.
10当完成所有选定软件包的安装时,应该重新引导系统.
(此值应该添加到一位数退出代码之一.
)20在完成当前软件包的安装时应立即重新引导系统.
(此值应该添加到一位数退出代码之一.
)有关安装脚本返回的退出代码的示例,请参见第5章,软件包创建案例研究.
注–随您的软件包一起提供的所有安装脚本均应在prototype文件中有一个条目.
文件类型应该是i(表示软件包安装脚本).
创建安装脚本第3章增强软件包的功能(任务)55编写request脚本request脚本是软件包可直接与安装该软件包的管理员进行交互的唯一途径.
例如,该脚本可用于询问管理员是否安装软件包的可选组件.
request脚本的输出必须是环境变量及其值的列表.
此列表可以包括在pkginfo文件中创建的任一参数以及CLASSES和BASEDIR参数.
该列表还可引入尚未在其他位置定义的环境变量.
不过,适用情况下,pkginfo文件应该始终提供缺省值.
有关软件包环境变量的更多信息,请参见第22页中的"软件包环境变量".
当request脚本为环境变量赋值时,它必须使这些值对pkgadd命令和其他软件包脚本可用.
request脚本行为request脚本不能修改任何文件.
该脚本仅与正在安装软件包的管理员交互,并根据这种交互创建环境变量赋值的列表.
request脚本以非特权用户install身份运行(如果存在该用户).
否则,该脚本将以root身份执行.
pkgadd命令使用一个用于命名request脚本的响应文件的参数调用该脚本.
响应文件存储管理员的响应.
在软件包删除期间,request脚本不会执行.
不过,该脚本指定的环境变量将被保存,并在软件包删除期间可用.
request脚本的设计规则对于每个软件包只能有一个request脚本.
必须将该脚本命名为request.
应该将环境变量赋值添加到安装环境(通过将其写入到响应文件),供pkgadd命令和其他打包脚本使用(对于该脚本称为$1).
request脚本不能修改除CLASSES和BASEDIR参数之外的系统环境变量和标准安装环境变量.
该脚本可以修改您创建的其他任何环境变量.
注–request脚本只能在Solaris2.
5和兼容发行版及之后的发行版中修改BASEDIR参数.
对于request脚本可以处理的每个环境变量,应该在pkginfo文件中为其指定一个缺省值.
输出列表的格式应该是PARAM=value.
例如:CLASSES=noneclass1管理员的终端被定义为request脚本的标准输入.
创建安装脚本应用程序包开发者指南2009年4月56不要在request脚本中对目标系统执行任何特殊分析.
根据该分析测试系统中是否存在特定二进制文件或特定行为以及设置环境变量都是有风险的.
无法保证request脚本在安装时实际执行.
安装软件包的管理员可能提供将插入环境变量的响应文件,而不会调用request脚本.
如果request脚本还评估目标文件系统,该评估可能不会发生.
为了进行特殊处理而对目标系统进行的分析最好留给checkinstall脚本完成.
注–如果将安装软件包的管理员可能使用JumpStartTM产品,那么不能以交互方式安装该软件包.
此时您不应该为软件包提供request脚本,或者您需要与管理员沟通,希望他们应该在安装之前使用pkgask命令.
pkgask命令存储管理员对request脚本的响应.
有关pkgask命令的更多信息,请参见pkgask(1M)手册页.
如何编写request脚本将包含信息文件的目录设置为当前工作目录.
使用您喜爱的文本编辑器创建名为request的文件.
完成时保存所做更改并退出编辑器.
完成以下任务之一.
如果您要创建其他安装脚本,请跳至下一任务:第59页中的"如何收集文件系统数据".
如果您未创建prototype文件,请完成第38页中的"如何使用pkgproto命令创建prototype文件"过程.
跳至步骤5.
如果您已经创建了prototype文件,请编辑该文件,并为刚刚创建的安装脚本添加一个条目.
生成您的软件包.
如果需要,请参见第41页中的"如何生成软件包".
编写request脚本当request脚本为环境变量赋值时,它必须使这些值对pkgadd命令可用.
此示例显示了为以下四个环境变量执行该任务的request脚本片段:CLASSES、NCMPBIN、EMACS和NCMPMAN.
假定之前已使用该脚本在与管理员的交互会话中定义了这些变量.

#makeenvironmentvariablesavailabletoinstallation#serviceandanyotherpackagingscriptwemighthavecat>$1$PKG_INSTALL_ROOT/etc/randomtableecho"1121554#firstrandomnumber">>$PKG_INSTALL_ROOT/etc/randomtablefi!
remove#randomtabledeconstructorif[-f$PKG_INSTALL_ROOT/etc/randomtable];then#thefilecanberemovedifit'sunchangedif[egrep"firstrandomnumber"$PKG_INSTALL_ROOT/etc/randomtable];thenrm$PKG_INSTALL_ROOT/etc/randomtable;fifi有关使用build类的另一个示例,请参见第5章,软件包创建案例研究.
创建安装脚本应用程序包开发者指南2009年4月66preserve类脚本preserve类通过确定在安装软件包时是否要覆写现有文件来保留软件包对象文件.
使用preserve类脚本时的两种可能情况是:如果将安装的文件在目标目录中尚不存在,通常将安装该文件.
如果将安装的文件存在于目标目录中,将显示一条消息指出该文件已存在,此时将不会安装该文件.
preserve脚本会将上述两种情况的结果都视为成功.
只有在第二种情况中当文件无法复制到目标目录时才会失败.
自Solaris7发行版开始,i.
preserve脚本以及该脚本的一个副本i.
CONFIG.
prsv以及其他类操作脚本都可在/usr/sadm/install/scripts目录中找到.
可修改该脚本以包括您希望保留的一个或多个文件名.
manifest类脚本manifest类会自动安装或卸载与SMF清单相关联的服务管理工具(ServiceManagementFacility,SMF)服务.
如果您不熟悉SMF,请参见《系统管理指南:基本管理》中的第16章"管理服务(概述)",获取有关如何使用SMF来管理服务的信息.
软件包中的的所有服务清单都应由类manifest来标识.
安装和移除服务清单的类操作脚本包含在软件包子系统中.
调用pkgadd(1M)时,会导入此服务清单.
调用pkgrm(1M)时,会删除服务清单中禁用的实例.
还会删除清单中没有保留实例的所有服务.
如果将-R选项提供给pkgadd(1M)或pkgrm(1M),在系统下一次以备用引导路径重新引导时,才会完成这些服务清单操作.
以下软件包信息文件中的部分代码显示了manifest类的用法.
#packagingfilesipkginfoicopyrightidependipreinstallipostinstallii.
manifestir.
manifest##sourcelocationsrelativetotheprototypefile#dnonevar0755rootsysdnonevar/svc0755rootsysdnonevar/svc/manifest0755rootsysdnonevar/svc/manifest/network0755rootsysdnonevar/svc/manifest/network/rpc0755rootsysfmanifestvar/svc/manifest/network/rpc/smserver.
xml0444rootsys创建安装脚本第3章增强软件包的功能(任务)67如何编写类操作脚本将包含信息文件的目录设置为当前工作目录.
在prototype文件中为软件包对象指定所需类名.
例如,将对象指定给application和manpage类将如下所示:fmanpage/usr/share/man/manl/myappl.
1lfapplication/usr/bin/myappl在pkginfo文件中修改CLASSES参数,使其包含要在软件包中使用的类名.
例如,application和manpage类的条目将如下所示:CLASSES=manpageapplicationnone注–none类始终最先安装,最后删除,无论它在CLASSES参数的定义中位置如何.
如果您要为属于sed、awk或build类的文件创建类操作脚本,请将包含软件包对象的目录设置为当前工作目录.
为属于sed、awk或build类的文件创建类操作脚本或软件包对象.
例如,名为application的类的安装脚本将命名为i.
application,而其删除脚本将命名为r.
application.
切记,当一个文件属于具有类操作脚本的类时,脚本必须安装该文件.
pkgadd命令不安装有类操作脚本的文件,虽然它确实执行安装验证.
如果您定义了一个类但是没有提供类操作脚本,则对该类执行的唯一操作是将组件从安装介质复制到目标系统(缺省pkgadd行为).
完成以下任务之一:如果您未创建prototype文件,请完成第38页中的"如何使用pkgproto命令创建prototype文件"过程,然后跳至步骤7.
如果您已经创建了prototype文件,请编辑该文件,并为刚刚创建的每个安装脚本添加一个条目.
生成您的软件包.
如果需要,请参见第41页中的"如何生成软件包".
下一步操作在生成软件包之后,请安装该软件包以确认它已正确安装并验证其完整性.
第4章,验证和转换软件包介绍了如何执行此任务,并提供了有关如何将经过验证的软件包转换为分发介质的逐步说明.
1234567更多信息创建安装脚本应用程序包开发者指南2009年4月68创建带签名的软件包创建带签名软件包的过程涉及若干步骤,您需要领会一些新概念和术语.
本节提供有关带签名的软件包、其术语以及证书管理的信息.
此外还提供了有关如何创建带签名的软件包的逐步骤过程.
带签名的软件包带签名的软件包是一种具有数字签名(下面定义的PEM编码PKCS7数字签名)的标准流格式软件包,该签名用于验证:软件包是否来自对其进行签名的实体软件包是否的确由该实体签名软件包是否在该实体对其签名之后未进行修改对软件包进行签名的实体是否为受信任实体除了签名,带签名的软件包与不带签名的软件包完全相同.
带签名的软件包与不带签名的软件包二进制兼容.
因此,带签名的软件包可用于打包工具的旧版本.
但是,在这种情况下签名会被忽略.
带签名的打包技术引入了一些新的术语和缩写,下表中介绍了这些内容.

术语定义ASN.
1抽象语法表示法1-一种表示抽象对象的方法.
例如,ASN.
1定义公钥证书、组成证书的所有对象以及对象的收集顺序.
不过,ASN.
1不指定针对存储或传输序列化对象的方式.
X.
509ITU-T推荐标准X.
509-指定广泛采用的X.
509公钥证书语法.
DER唯一编码规则-ASN.
1对象的一种二进制表示法,用于定义在计算环境中针对存储或传输序列化ASN.
1对象的方式.
PEM保密性增强消息-一种使用base64编码和某些可选标头对文件进行编码(采用DER或其他二进制格式)的方式.
PEM最初用于对MIME类型的电子邮件进行编码.
PEM还广泛用于将证书和私钥编码到文件系统或电子邮件中存在的文件中.
PKCS7公钥密码学标准#7-此标准描述可能应用了加密算法的数据的通用语法,例如数字签名和数字信封.
带签名的软件包包含一个嵌入的PKCS7签名.
此签名至少包含软件包的加密摘要,以及签名者的X.
509公钥证书.
带签名的软件包还可能包含链证书.
当形成从签名者的证书到本地存储的受信任证书的信任链时可以使用链证书.
PKCS12公钥密码学标准#12-此标准描述将加密对象存储在磁盘上的语法.
软件包密钥库会以这种格式进行维护.
创建带签名的软件包第3章增强软件包的功能(任务)69术语定义软件包密钥库可通过软件包工具查询的证书和密钥的系统信息库.
证书管理在创建带签名的软件包之前,您必须有软件包密钥库.
此软件包密钥库以对象形式包含证书.
软件包密钥库中存在两种类型的对象:受信任证书受信任证书包含属于其他实体的一个公钥证书.
之所以这样命名受信任证书,是因为密钥库属主相信证书中的公钥确实属于由证书的"主题"(所有者)指定的身份.
证书的颁发者通过对证书进行签名来确保证书的真实性.
验证签名以及启动与安全(SSL)服务器的连接时将使用受信任证书.
用户密钥用户密钥用于存放敏感的加密密钥信息.
加密密钥信息以受保护的格式存储,可防止进行未经授权的访问.
用户密钥中既包含用户的私钥又包含与私钥相对应的公钥证书.
创建带签名的软件包时将使用用户密钥.
缺省情况下,软件包密钥库存储在/var/sadm/security目录中.
缺省情况下各用户也可将自己的密钥库存储在$HOME/.
pkg/security目录中.
在磁盘上,软件包密钥库可以采用两种格式:多文件格式和单文件格式.
多文件格式将其对象存储在多个文件中.
每种类型的对象存储在单独的文件中.
必须使用相同的口令短语对所有这些文件进行加密.
单文件密钥库将其所有对象存储在文件系统上的单个文件中.
用于管理证书和软件包密钥库的主要实用程序是pkgadm命令.
以下各小节介绍了用于管理软件包密钥库的更为常见的任务.
将受信任证书添加到软件包密钥库可以使用pkgadm命令将受信任证书添加到软件包密钥库.
证书可以是PEM或DER格式.
例如:$pkgadmaddcert-t/tmp/mytrustedcert.
pem在此示例中,名为mytrustedcert.
pem的PEM格式证书会添加到软件包密钥库中.
创建带签名的软件包应用程序包开发者指南2009年4月70将用户证书和私钥添加到软件包密钥库pkgadm命令不会生成用户证书或私钥.
用户证书和私钥通常从证书颁发机构(例如Verisign)获得.
此外也可作为自行签名的证书在本地生成.
一旦获取了私钥和证书,即可使用pkgadm命令将其导入到软件包密钥库中.
例如:pkgadmaddcert-nmyname-e/tmp/myprivkey.
pem/tmp/mypubcert.
pem在此示例中,使用了以下选项:-nmyname标识软件包密钥库中您希望处理的实体(myname).
myname实体成为对象存储时所用的别名.
-e/tmp/myprivkey.
pem指定包含私钥的文件.
在本例中,文件是myprivkey.
pem,位于/tmp目录.
/tmp/mypubcert.
pem指定名为mypubcert.
pem的PEM格式证书文件.
检验软件包密钥库中的内容pkgadm命令还可用于查看软件包密钥库的内容.
例如:$pkgadmlistcert此命令显示软件包密钥库中的受信任证书和私钥.
从软件包密钥库中删除受信任证书和私钥pkgadm命令可用于从软件包密钥库中删除受信任证书和私钥.
删除用户证书时,必须指定证书/密钥对的别名.
例如:$pkgadmremovecert-nmyname证书的别名是证书的通用名称,可使用pkgadmlistcert命令标识.
例如,以下命令删除一个名为TrustedCACert1的受信任证书:$pkgadmremovecert-n"TrustedCACert1"注–如果使用同一别名存储了受信任证书和用户证书,则指定-n选项时会将其同时删除.
创建带签名的软件包第3章增强软件包的功能(任务)71创建带签名的软件包创建带签名的软件包的过程涉及三个基本步骤:1.
创建不带签名的目录格式的软件包.
2.
将签名证书、CA证书和私钥导入到软件包密钥库.
3.
使用步骤2的证书对步骤1中创建的软件包进行签名.
注–打包工具不会创建证书.
必须从证书颁发机构(例如Verisign或Thawte)获取这些证书.
以下过程介绍了创建带签名软件包的每个步骤.
如何创建不带签名的目录格式的软件包创建不带签名的目录格式的软件包过程与创建常规软件包的过程相同,如本手册前面所述.
以下过程介绍如何创建此不带签名的目录格式的软件包.
如果您需要更多信息,请参阅前面关于生成软件包的各节.
创建pkginfo文件.
pkginfo文件应该包含以下基本内容:PKG=SUNWfooBASEDIR=/NAME=MyTestPackageARCH=sparcVERSION=1.
0.
0CATEGORY=application创建prototype文件.
prototye文件应该包含以下基本内容:$catprototypeipkginfodnoneusr0755rootsysdnoneusr/bin0755rootbinfnoneusr/bin/myapp=/tmp/myroot/usr/bin/myapp0644rootbin列出对象源目录的内容.
例如:$ls-lR/tmp/myroot123创建带签名的软件包应用程序包开发者指南2009年4月72输出可能如下所示:/tmp/myroot:total16drwxr-xr-x3abcother177Jun216:19usr/tmp/myroot/usr:total16drwxr-xr-x2abcother179Jun216:19bin/tmp/myroot/usr/bin:total16-rw-------1abcother1024Jun216:19myapp创建不带签名的软件包.
pkgmk-d'pwd'输出可能如下所示:##Buildingpkgmapfrompackageprototypefile.
##Processingpkginfofile.
WARNING:parametersetto"syrinx20030605115507"WARNING:parametersetto"none"##Attemptingtovolumize3entriesinpkgmap.
part1--84blocks,7entries##Packagingonepart.
/tmp/SUNWfoo/pkgmap/tmp/SUNWfoo/pkginfo/tmp/SUNWfoo/reloc/usr/bin/myapp##Validatingcontrolscripts.
##Packagingcomplete.
软件包现在会存在于当前目录中.
如何将证书导入到软件包密钥库要导入的证书和私钥必须以PEM或DER编码的X.
509证书和私钥形式存在.
此外,必须先将任何将您的签名证书与证书颁发机构证书相关联的中间或"链"证书导入到软件包密钥库中,然后才能对软件包进行签名.
注–各证书颁发机构可能会颁发不同格式的证书.
要将证书和私钥从PKCS12文件提取到PEM编码的X.
509文件(适于导入到软件包密钥库),请使用免费软件转换实用程序,例如OpenSSL.
4创建带签名的软件包第3章增强软件包的功能(任务)73如果您的私钥进行了加密(通常应该如此),系统将提示您输入口令短语.
此外,还将提示您输入口令以保护生成的软件包密钥库.
您可以选择不提供任何口令,但是这样做会导致软件包密钥库不会加密.
以下过程介绍了证书格式正确时,如何使用pkgadm命令导入证书.
导入在PEM或DER编码的X.
509证书文件中找到的所有证书颁发机构证书.
例如,要导入在ca.
pem文件中找到的所有证书颁发机构证书,应键入以下内容:$pkgadmaddcert-k~/mykeystore-tyca.
pem输出可能如下所示:TrustingcertificateTrustingcertificatearenowtrusted为了将您的签名密钥导入到软件包密钥库,必须提供别名,供以后签名软件包时使用.
如果您要从软件包密钥库中删除密钥,也可能会使用该别名.
例如,要从sign.
pem文件中导入您的签名密钥,应键入以下内容:$pkgadmaddcert-k~/mykeystore-nmycertsign.
pem输出可能如下所示:EnterPEMpassphrase:EnterKeystorePassword:SuccessfullyaddedCertificatewithalias检验证书是否在软件包密钥库中.
例如,要在密钥库中查看在上一步骤中创建的证书,应键入以下内容:$pkgadmlistcert-k~/mykeystore如何对软件包签名一旦将证书导入到软件包密钥库,即可对软件包签名.
实际的软件包签名工作是使用pkgtrans命令完成的.
12创建带签名的软件包应用程序包开发者指南2009年4月74使用pkgtrans命令对软件包签名.
提供不带签名的软件包的位置,并提供用于签名软件包的密钥别名.
例如,使用前面过程中的示例,您应键入以下内容创建名为SUNWfoo.
signed的带签名软件包:$pkgtrans-g-k~/mykeystore-nmycert.
.
/SUNWfoo.
signedSUNWfoo此命令的输出可能如下所示:RetrievingsigningcertificatesfromkeystoreEnterkeystorepassword:GeneratingdigitalsignatureforsignerTransferringpackageinstance带签名的软件包会在SUNWfoo.
signed文件中创建且采用软件包流格式.
此带签名的软件包适合于通过pkgadd命令和URL复制到Web站点并进行安装.
创建带签名的软件包第3章增强软件包的功能(任务)7576验证和转换软件包本章介绍如何验证软件包的完整性以及将其转换为分发介质(例如软盘或CD-ROM).
以下是本章中概述信息的列表:第77页中的"验证和转换软件包(任务图)"第78页中的"安装软件包"第80页中的"验证软件包的完整性"第81页中的"显示有关已安装的软件包的附加信息"第86页中的"删除软件包"第87页中的"将软件包转换为分发介质"验证和转换软件包(任务图)下表介绍了为了验证软件包的完整性以及将其转换为分发介质所应遵循的步骤.

表4–1验证和转换软件包(任务图)任务说明参考1.
生成软件包在磁盘上生成软件包.
第2章,生成软件包2.
安装软件包通过安装软件包并确保没有安装错误来测试软件包.
第79页中的"如何在独立系统或服务器上安装软件包"3.
验证软件包的完整性使用pkgchk命令验证软件包的完整性.
第80页中的"如何验证软件包的完整性"4.
获取其他软件包信息可选.
使用pkginfo和pkgparam命令执行特定于软件包的验证.
第81页中的"显示有关已安装的软件包的附加信息"5.
删除已安装的软件包使用pkgrm命令从系统中删除已安装的软件包.
第86页中的"如何删除软件包"4第4章77表4–1验证和转换软件包(任务图)(续)任务说明参考6.
将软件包转换为分发介质使用pkgtrans命令将软件包(以软件包格式)转换为分发介质.
第87页中的"如何将软件包转换为分发介质"安装软件包软件包使用pkgadd命令进行安装.
此命令从分发介质或目录转换软件包的内容并将其安装到系统上.
本节提供有关安装软件包以便验证安装正确的基本安装说明.
安装软件数据库系统中安装的所有软件包的信息都保存在安装软件数据库中.
对于软件包中的每个对象都有一个条目,其中包含组件名、组件的驻留位置及其类型等信息.
这类条目包含以下信息:组件所属软件包的记录;可能引用该组件的其他软件包;以及路径名、组件的驻留位置和组件类型等信息.
条目由pkgadd和pkgrm命令自动添加和删除.
您可以使用pkgchk和pkginfo命令来查看数据库中的信息.
与每个软件包组件相关联的信息有两种.
属性信息描述了组件本身.
例如,组件的访问权限、所有者ID和组ID是属性信息.
内容信息描述组件的内容,例如文件大小和上次修改时间.
安装软件数据库可跟踪软件包的状态.
软件包或者是完全安装(它已经成功完成安装过程),或者是部分安装(它没有成功完成安装过程).
当软件包部分安装时,在安装终止之前可能已安装软件包的某些部分;因此,部分软件包被安装并记录在数据库中,而部分软件包则没有安装.
当您重新安装软件包时,系统将提示您从上次安装停止的位置开始安装,因为pkgadd命令可以访问数据库并检测哪些部分已经安装.
您还可以使用pkgrm命令,根据安装软件数据库中的信息删除已经安装的部分.
与pkgadd命令交互如果pkgadd命令遇到问题,它会首先检查安装管理文件中的说明.
(有关更多信息,请参见admin(4).
)如果不存在任何说明,或者如果管理文件中的相关参数被设置为ask,pkgadd将显示一条消息,描述该问题并提示用户进行答复.
该提示通常是Doyouwanttocontinuewiththisinstallation您应该回答yes、no或quit.
如果您已指定多个软件包,回答no将停止正在进行的软件包安装,但pkgadd会继续安装其他软件包.
quit指示pkgadd应该停止所有软件包的安装.
安装软件包应用程序包开发者指南2009年4月78在同构环境中的独立系统或服务器上安装软件包本节介绍如何在同构环境中的独立系统或服务器系统上安装软件包.
如何在独立系统或服务器上安装软件包生成软件包.
如果需要,请参见第40页中的"生成软件包".
以超级用户身份登录系统.
向系统中添加软件包.
#pkgadd-ddevice-name[pkg-abbrev.
.
.
]-ddevice-name指定软件包的位置.
请注意,device-name可以是完整的目录路径名或者磁带、软盘或可移除磁盘的标识符.
pkg-abbrev要添加的一个或多个软件包的名称(以空格分隔).
如果省略,pkgadd将安装所有可用的软件包.
在独立系统和服务器上安装软件包要从名为/dev/rmt/0的磁带设备安装名为pkgA的软件包,您需要输入以下命令:#pkgadd-d/dev/rmt/0pkgA您还可以同时安装多个软件包(只要您使用空格分隔软件包名称),如下所示:#pkgadd-d/dev/rmt/0pkgApkgBpkgC如果您不指定软件包所驻留的设备,该命令将检查缺省的假脱机目录(/var/spool/pkg).
如果软件包不在缺省的假脱机目录中,安装将失败.
如果您已准备好执行下一个任务,请参见第80页中的"如何验证软件包的完整性".
123示例4–1另请参见安装软件包第4章验证和转换软件包79验证软件包的完整性使用pkgchk命令可以检查软件包的完整性、它们是已经安装在系统上还是处于软件包格式(准备使用pkgadd命令安装).
它确认软件包结构或已安装的文件和目录,或者显示有关软件包对象的信息.
pkgchk命令可以列出或检查以下内容:软件包安装脚本.
系统中当前安装的对象的内容和/或属性.
假脱机的已卸载软件包的内容.
指定的pkgmap文件中描述的对象的内容和/或属性.
有关此命令的更多信息,请参阅pkgchk(1M).
pkgchk命令执行两种检查.
它检查文件属性(文件的权限和拥有权以及块或字符特殊设备的主/从设备号)和文件内容(大小、校验和及修改日期).
缺省情况下,该命令同时检查文件属性和文件内容.
pkgchk命令还将已安装的软件包的文件属性和内容与安装软件数据库进行比较.
与软件包有关的条目自安装以来可能已经更改;例如,另一个软件包可能更改了软件包组件.
数据库会反映该更改.
如何验证软件包的完整性安装软件包.
如果需要,请参见第79页中的"如何在独立系统或服务器上安装软件包".
验证软件包的完整性.
#pkgchk[-v][-Rroot-path][pkg-abbrev.
.
.
]-v在处理文件的过程中列出文件.
-Rroot-path指定客户机系统的根文件系统的位置.
pkg-abbrev要检查的一个或多个软件包的名称(以空格分隔).
如果省略,pkgchk将检查所有可用的软件包.
验证软件包的完整性本示例演示应该用于验证已安装软件包的完整性的命令.
$pkgchkpkg-abbrev$如果有错误,pkgchk命令将列出这些错误.
否则,它不会列出任何内容并且返回退出代码0.
如果您不提供软件包缩写,它将检查系统中的所有软件包.
12示例4–2验证软件包的完整性应用程序包开发者指南2009年4月80此外,您还可以使用-v选项,该选项将在没有发生错误时列出软件包中文件的列表.
例如:$pkgchk-vSUNWcadap/opt/SUNWcadap/opt/SUNWcadap/demo/opt/SUNWcadap/demo/file1/opt/SUNWcadap/lib/opt/SUNWcadap/lib/file2/opt/SUNWcadap/man/opt/SUNWcadap/man/man1/opt/SUNWcadap/man/man1/file3.
1/opt/SUNWcadap/man/man1/file4.
1/opt/SUNWcadap/man/windex/opt/SUNWcadap/srcfiles/opt/SUNWcadap/srcfiles/file5/opt/SUNWcadap/srcfiles/file6$如果您需要验证客户机系统的根文件系统上安装的软件包,请使用以下命令:$pkgchk-v-Rroot-pathpkg-abbrev如果您已准备好执行下一个任务,请参见第86页中的"如何使用pkginfo命令获取信息".
显示有关已安装的软件包的附加信息可以使用其他两个命令来显示有关已安装的软件包的信息:pkgparam命令显示参数值.
pkginfo命令显示安装软件数据库中的信息.
pkgparam命令pkgparam命令可以显示与您在命令行上指定的参数相关联的值.
这些值是从特定软件包的pkginfo文件或者从您指定的文件中获取的.
每行显示一个参数值.
您可以仅显示这些值,也可以同时显示参数及其值.
另请参见显示有关已安装的软件包的附加信息第4章验证和转换软件包81如何使用pkgparam命令获取信息安装软件包.
如果需要,请参见第79页中的"如何在独立系统或服务器上安装软件包".
显示有关软件包的附加信息.
#pkgparam[-v]pkg-abbrev[param.
.
.
]-v显示参数的名称及值.
pkg-abbrev特定软件包的名称.
param指定要显示其值的一个或多个参数.
使用pkgparam命令获取信息例如,要仅显示值,请使用以下命令.
$pkgparamSUNWcadapnone/optUS/Mountain/sbin:/usr/sbin:/usr/bin:/usr/sadm/install/bin/usr/sadm/sysadmSUNWcadapChipdesignersneedCADapplicationsoftwaretodesignabcchips.
Runsonlyonxyzhardwareandisinstalledintheusrpartition.
systemrelease1.
0SPARCvenus990706083849SUNWcadap/var/sadm/pkg/SUNWcadap/saveJul7199909:58$要显示参数及其值,请使用以下命令.
$pkgparam-vSUNWcadappkgparam-vSUNWcadapCLASSES='none'BASEDIR='/opt'TZ='US/Mountain'PATH='/sbin:/usr/sbin:/usr/bin:/usr/sadm/install/bin'OAMBASE='/usr/sadm/sysadm'12示例4–3显示有关已安装的软件包的附加信息应用程序包开发者指南2009年4月82PKG='SUNWcadap'NAME='ChipdesignersneedCADapplicationsoftwaretodesignabcchips.
Runsonlyonxyzhardwareandisinstalledintheusrpartition.
'CATEGORY='system'VERSION='release1.
0'ARCH='SPARC'PSTAMP='venus990706083849'PKGINST='SUNWcadap'PKGSAV='/var/sadm/pkg/SUNWcadap/save'INSTDATE='Jul7199909:58'$或者,如果您想要显示特定参数的值,请使用以下格式:$pkgparamSUNWcadapBASEDIR/opt$有关更多信息,请参阅pkgparam(1).
如果您已准备好执行下一个任务,请参见第86页中的"如何删除软件包".
pkginfo命令您可以使用pkginfo命令显示有关已安装的软件包的信息.
此命令具有多个选项,这些选项使您能够定制显示的格式和内容.
您可以请求有关任意数量的软件包实例的信息.
缺省pkginfo显示在不带任何选项的情况下执行pkginfo命令时,该命令将显示已经完整安装到系统中的所有软件包的类别、软件包实例和软件包名称.
显示按照类别组织,如以下示例所示.
$pkginfo.
.
.
systemSUNWinstInstallSoftwaresystemSUNWipcInterprocessCommunicationssystemSUNWisolcXSH4conversionforISOLatincharactersetsapplicationSUNWkcspfKCMSOptionalProfilesapplicationSUNWkcspgKCMSProgrammersEnvironmentapplicationSUNWkcsrtKCMSRuntimeEnvironment.
另请参见显示有关已安装的软件包的附加信息第4章验证和转换软件包83.
.
$定制pkginfo显示的格式您可以按以下三种格式之一获得pkginfo显示:短格式、简明格式和长格式.
短格式是缺省格式.
如第83页中的"缺省pkginfo显示"所示,该格式仅显示类别、软件包缩写和软件包全名.
简明格式显示软件包缩写、软件包名称、软件包体系结构(如果有)和软件包版本(如果有).
使用-x选项可以请求简明格式,如下一个示例所示.
$pkginfo-x.
.
.
SUNWipcInterprocessCommunications(sparc)11.
8.
0,REV=1999.
08.
20.
12.
37SUNWisolcXSH4conversionforISOLatincharactersets(sparc)1.
0,REV=1999.
07.
10.
10.
10SUNWkcspfKCMSOptionalProfiles(sparc)1.
1.
2,REV=1.
5SUNWkcspgKCMSProgrammersEnvironment(sparc)1.
1.
2,REV=1.
5.
.
.
$使用-l选项可生成长格式显示,其中包括有关软件包的所有可用信息,如下面的示例所示.
$pkginfo-lSUNWcadapPKGINST:SUNWcadapNAME:ChipdesignersneedCADapplicationsoftwaretodesignabcchips.
Runsonlyonxyzhardwareandisinstalledintheusrpartition.
CATEGORY:systemARCH:SPARCVERSION:release1.
0BASEDIR:/optPSTAMP:system980706083849INSTDATE:Jul7199909:58STATUS:completelyinstalledFILES:13installedpathnames6directories显示有关已安装的软件包的附加信息应用程序包开发者指南2009年4月843executables3121blocksused(approx)$pkginfo长格式的参数说明下表介绍了可以为每个软件包显示的软件包参数.
只有为参数赋值之后,才会显示参数及其值.
表4–2软件包参数参数说明ARCH此软件包支持的体系结构.
BASEDIR软件包所驻留的基目录(如果该软件包是可重定位的则显示).
CATEGORY此软件包所属的一个或多个软件类别(例如,system或application).
CLASSES为软件包定义的类的列表.
该列表的顺序确定类的安装顺序.
首先列出的类将首先安装(逐个介质进行安装).
此参数可能由request脚本修改.
DESC描述软件包的文本.
EMAIL用户查询所使用的电子邮件地址.
HOTLINE有关如何获得关于此软件包的热线帮助的信息.
INTONLY当设置为任何非NULL值时,指示仅应该以交互方式安装软件包,ISTATES允许软件包安装具有的运行状态的列表(例如,Ss1).
MAXINST一台计算机上同时应该允许存在的软件包实例的最大数目.
缺省情况下,仅允许存在一个软件包实例.
NAME软件包名称,通常是描述软件包缩写的文本.
ORDER一个类列表,定义将这些类放在介质上的顺序.
由pkgmk命令在创建软件包时使用.
此参数中未定义的类将使用标准排序过程放置在介质上.
PKGINST所安装的软件包的缩写.
PSTAMP此软件包的生产标记.
RSTATES允许软件包删除操作具有的运行状态的列表(例如,Ss1).
ULIMIT如果设置,此参数将作为参数传递给ulimit命令,该命令在安装期间设置最大文件大小.
这仅适用于过程脚本所创建的文件.
VENDOR提供软件包的供应商的名称.
VERSION此软件包的版本.
VSTOCK供应商提供的物料编号.
显示有关已安装的软件包的附加信息第4章验证和转换软件包85有关pkginfo命令的详细信息,请参阅pkginfo(1)手册页.
如何使用pkginfo命令获取信息安装软件包.
如果需要,请参见第79页中的"如何在独立系统或服务器上安装软件包".
显示有关软件包的附加信息.
#pkginfo[-x|-l][pkg-abbrev]-x以简明格式显示软件包信息.
-l以长格式显示软件包信息.
pkg-abbrev特定软件包的名称.
如果省略,pkginfo命令将以缺省格式显示有关所有已安装软件包的信息.
下一步操作如果您已准备好执行下一个任务,请参见第86页中的"如何删除软件包".
删除软件包由于pkgrm命令更新软件产品数据库中的信息,因此在删除软件包时一定要使用pkgrm命令,即使您可能倾向于使用rm命令.
例如,您可能会使用rm命令删除二进制可执行文件,但这与使用pkgrm删除包括该二进制可执行文件的软件包不同.
如果使用rm命令来删除软件包的文件,则会破坏软件产品数据库.
(如果您确实只想删除一个文件,可以使用removef命令,该命令将正确地更新软件产品数据库.
)如何删除软件包以超级用户身份登录系统.
删除已安装的软件包.
#pkgrmpkg-abbrev.
.
.
pkg-abbrev一个或多个软件包的名称(以空格分隔).
如果省略,pkgrm将删除所有可用的软件包.
12更多信息12删除软件包应用程序包开发者指南2009年4月86使用pkginfo命令验证软件包已成功删除.
$pkginfo|egreppkg-abbrev如果安装了pkg-abbrev,pkginfo命令将返回有关它的一行信息.
否则,pkginfo返回系统提示符.
将软件包转换为分发介质pkgtrans命令移动软件包并且执行软件包格式转换.
可以使用pkgtrans命令为可安装的软件包执行下列转换:文件系统格式到数据流格式数据流格式到文件系统格式一种文件系统格式到另一种文件系统格式如何将软件包转换为分发介质生成您的软件包,同时创建一个目录格式软件包(如果您尚未这样做).
有关更多信息,请参见第41页中的"如何生成软件包".
安装该软件包以验证其安装正确.
如果需要,请参见第79页中的"如何在独立系统或服务器上安装软件包".
验证软件包的完整性.
如果需要,请参见第80页中的"如何验证软件包的完整性"、第86页中的"如何使用pkginfo命令获取信息"和第82页中的"如何使用pkgparam命令获取信息".
从系统中删除已安装的软件包.
如果需要,请参见第86页中的"如何删除软件包".
将软件包(以软件包格式)转换为分发介质.
要执行基本转换,请执行以下命令:$pkgtransdevice1device2[pkg-abbrev.
.
.
]device1软件包当前驻留的设备的名称.
device2要将经过转换的软件包写入到的设备的名称.
[pkg-abbrev]一个或多个软件包缩写.
如果没有指定软件包名称,系统会将驻留在device1中的所有软件包转换并写入到device2.
312345将软件包转换为分发介质第4章验证和转换软件包87注–如果有多个软件包实例驻留在device1中,您必须对软件包使用实例标识符.
有关软件包标识符的说明,请参见第24页中的"定义软件包实例".
当要转换的软件包的实例已经存在于device2上时,pkgtrans命令不执行转换.
如果实例已经存在,您可以使用-o选项告诉pkgtrans命令覆写目标设备上现有的所有实例,并可以使用-n选项告诉该命令创建一个新实例.
请注意,当device2支持数据流格式时,此检查不适用.
下一步操作至此,您已经完成设计、生成、验证和转换软件包所需的步骤.
如果您对某些案例研究感兴趣,请参见第5章,软件包创建案例研究.
如果您对先进的软件包设计理念感兴趣,请参见第6章,创建软件包的高级技术.
更多信息将软件包转换为分发介质应用程序包开发者指南2009年4月88软件包创建案例研究本章提供了案例研究以展示打包方案,例如有条件地安装对象、在运行时确定要创建的文件数,以及在软件包安装和删除期间修改现有数据文件.
每个案例研究都以一段描述开始,然后介绍采用的打包技术的列表、使用这些技术时采取的方法,以及与案例研究相关的样例文件和脚本.
以下是本章中案例研究的列表:第89页中的"请求来自管理员的输入"第92页中的"在安装时创建文件并在删除期间保存文件"第95页中的"定义软件包兼容性和相关性"第97页中的"使用标准类和类操作脚本修改文件"第100页中的"使用sed类和postinstall脚本修改文件"第102页中的"使用build类修改文件"第103页中的"在安装期间修改crontab文件"第106页中的"使用过程脚本安装和删除驱动程序"第109页中的"使用sed类和过程脚本安装驱动程序"请求来自管理员的输入在此案例研究中,软件包有三种类型的对象.
管理员可以选择安装哪一种对象类型,并选择对象在安装计算机上的位置.
技术此案例研究展示以下技术:使用用于建立多个基目录的参数化路径名(对象路径名中有变量)有关参数化路径名的信息,请参见第31页中的"参数化路径名".
使用request脚本请求来自管理员的输入5第5章89有关request脚本的信息,请参见第56页中的"编写request脚本".
为安装参数设置条件值.
方法要在此案例研究中设置选择性安装,您必须完成以下任务:为每种可安装对象的类型定义一个类.
在此案例研究中,三种对象类型是:软件包可执行文件、手册页和emacs可执行文件.
每种类型都有其自己的类:分别是bin、man和emacs.
请注意在prototype文件中,所有对象文件均属于这三个类之一.
在pkginfo文件中将CLASSES参数初始化为null.
通常在定义类时,应该在pkginfo文件的CLASSES参数中列出该类.
否则,不会安装属于该类的任何对象.
对于此案例研究,参数最初设置为null,意味着不会安装任何对象.
CLASSES参数将由request脚本根据管理员的选择进行更改.
这样,CLASSES参数会仅设置为管理员希望安装的那些对象类型.
注–通常可取的方法是将参数设置为缺省值.
如果此软件包有对所有三种对象类型通用的组件,可以将其指定给none类,然后将CLASSES参数设置为等于none.
将参数化路径名插入到prototype文件.
request脚本会将这些环境变量设置为管理员提供的值.
然后,pkgadd命令在安装时解析这些环境变量,从而知道软件包的安装位置.
此示例中使用的三个环境变量在pkginfo文件中设置为其缺省值,作用如下:$NCMPBIN定义对象可执行文件的位置$NCMPMAN定义手册页的位置$EMACS定义emacs可执行文件的位置prototype示例文件显示了如何定义含变量的对象路径名.
创建request脚本,用于询问管理员应该安装软件包的哪些部分及其放置位置.
此软件包的request脚本会询问管理员两个问题:是否应该安装软件包的此部分当答复为是时,相应的类名被添加到CLASSES参数.
例如,当管理员选择安装与此软件包关联的手册页时,类man将会添加到CLASSES参数.
如果是,应该将软件包的此部分放置在什么位置此时将设置相应的环境变量来响应此问题.
在手册页示例中,变量$NCMPMAN设置为响应值.
对于三种对象类型的每种类型都会重复这两个问题.
请求来自管理员的输入应用程序包开发者指南2009年4月90在request脚本的末尾,参数将设置为对pkgadd命令和所有其他打包脚本的安装变量可用.
request脚本通过将这些定义写入调用实用程序提供的文件来实现这一点.
对于此案例研究,没有提供其他脚本.
当查看此案例研究的request脚本时,请注意,上述问题由数据验证工具ckyorn和ckpath生成.
有关这些工具的更多信息,请参见ckyorn(1)和ckpath(1).
案例研究文件pkginfo文件PKG=ncmpNAME=NCMPUtilitiesCATEGORY=application,toolsBASEDIR=/ARCH=SPARCVERSION=RELEASE1.
0,Issue1.
0CLASSES=""NCMPBIN=/binNCMPMAN=/usr/manEMACS=/usr/emacsprototype文件ipkginfoirequestxbin$NCMPBIN0755roototherfbin$NCMPBIN/dired=/usr/ncmp/bin/dired0755roototherfbin$NCMPBIN/less=/usr/ncmp/bin/less0755roototherfbin$NCMPBIN/ttype=/usr/ncmp/bin/ttype0755roototherfemacs$NCMPBIN/emacs=/usr/ncmp/bin/emacs0755roototherxemacs$EMACS0755roototherfemacs$EMACS/ansii=/usr/ncmp/lib/emacs/macros/ansii0644roototherfemacs$EMACS/box=/usr/ncmp/lib/emacs/macros/box0644roototherfemacs$EMACS/crypt=/usr/ncmp/lib/emacs/macros/crypt0644roototherfemacs$EMACS/draw=/usr/ncmp/lib/emacs/macros/draw0644roototherfemacs$EMACS/mail=/usr/ncmp/lib/emacs/macros/mail0644roototherfemacs$NCMPMAN/man1/emacs.
1=/usr/ncmp/man/man1/emacs.
10644roototherdman$NCMPMAN0755roototherdman$NCMPMAN/man10755roototherfman$NCMPMAN/man1/dired.
1=/usr/ncmp/man/man1/dired.
10644roototherfman$NCMPMAN/man1/ttype.
1=/usr/ncmp/man/man1/ttype.
10644roototherfman$NCMPMAN/man1/less.
1=/usr/ncmp/man/man1/less.
10644inixmrother请求来自管理员的输入第5章软件包创建案例研究91request脚本trap'exit3'15#determineifandwheregeneralexecutablesshouldbeplacedans='ckyorn-dy\-p"Shouldexecutablesincludedinthispackagebeinstalled"'||exit$if["$ans"=y]thenCLASSES="$CLASSESbin"NCMPBIN='ckpath-d/usr/ncmp/bin-aoy\-p"Whereshouldexecutablesbeinstalled"'||exit$fi#determineifemacseditorshouldbeinstalled,andifitshould#whereshouldtheassociatedmacrosbeplacedans='ckyorn-dy\-p"Shouldemacseditorincludedinthispackagebeinstalled"'||exit$if["$ans"=y]thenCLASSES="$CLASSESemacs"EMACS='ckpath-d/usr/ncmp/lib/emacs-aoy\-p"Whereshouldemacsmacrosbeinstalled"'||exit$fi请注意,request脚本可以在不在文件系统上留下任何文件的情况下退出.
对于2.
5和兼容版本之前的Solaris版本上的安装(其中没有checkinstall脚本可用),request脚本是以确保安装成功所需的任何方式测试文件系统的正确位置.
当request脚本以代码1退出时,安装将完全退出.
这些示例文件显示了使用参数化路径建立多个基目录.
然而,首选的方法涉及使用由pkgadd命令管理并验证的BASEDIR参数.
每当使用多个基目录时,在同一个平台上安装多个版本和体系结构时应格外小心.
在安装时创建文件并在删除期间保存文件在此案例研究中,将在安装时创建一个数据库文件,并在删除软件包时保存数据库副本.
技术此案例研究展示以下技术:使用类和类操作脚本对不同的对象集执行特殊操作在安装时创建文件并在删除期间保存文件应用程序包开发者指南2009年4月92有关更多信息,请参见第62页中的"编写类操作脚本".
使用space文件通知pkgadd命令要正确安装此软件包需要额外空间有关space文件的更多信息,请参见第50页中的"在目标系统上保留额外空间".
使用installf命令安装没有在prototype和pkgmap文件中定义的文件.
方法要为此案例研究在安装时创建一个数据库文件,并在删除时保存副本,您必须完成以下任务:定义三个类.
在此案例研究中,软件包要求在CLASSES参数中定义以下三个类:标准类none,该类包含一组属于子目录bin的进程.
admin类,该类包含可执行文件config和一个包含数据文件的目录.
cfgdata类,该类包含一个目录.
使软件包可共同重定位.
请注意在prototype文件中,没有路径名以斜线或环境变量开头,这表明它们是可共同重定位的.
计算数据库文件需要的空间量,并创建一个要随软件包一起提供的space文件.
此文件通知pkgadd命令软件包需要额外空间并指定空间量.
为admin类创建类操作脚本(i.
admin).
该样例脚本使用属于admin类的数据文件初始化数据库.
要执行此任务,该脚本执行以下操作:将源数据文件复制到相应目标位置创建一个名为config.
data的空文件,并将其指定给cfgdata类执行bin/config命令(与软件包一起提供并已安装)以使用属于admin类的数据文件填充config.
data数据库文件执行installf-f命令完成config.
data的安装由于在删除时admin类不需要特殊操作,因此不会创建删除类操作脚本.
这意味着admin类中的所有文件和目录都会从系统中删除.
为cfgdata类创建删除类操作脚本(r.
cfgdata).
删除脚本会在删除数据库文件之前创建该文件的副本.
由于在安装时此类不需要特殊操作,因此不需要安装类操作脚本.
切记删除脚本的输入是要删除的路径名的列表.
路径名始终按反向字母顺序显示.
此删除脚本将文件复制到名为$PKGSAV的目录.
当所有路径名都被处理后,脚本会返回并删除与cfgdata类关联的所有目录和文件.
在安装时创建文件并在删除期间保存文件第5章软件包创建案例研究93此删除脚本的结果是将config.
data复制到$PKGSAV,然后删除config.
data文件和数据目录.
案例研究文件pkginfo文件PKG=krazyNAME=KrAzYApplicationsCATEGORY=applicationsBASEDIR=/optARCH=SPARCVERSION=Version1CLASSES=nonecfgdataadminprototype文件ipkginfoirequestii.
adminir.
cfgdatadnonebin555rootsysfnonebin/process1555roototherfnonebin/process2555roototherfnonebin/process3555roototherfadminbin/config500rootsysdadmincfg555rootsysfadmincfg/datafile1444rootsysfadmincfg/datafile2444rootsysfadmincfg/datafile3444rootsysfadmincfg/datafile4444rootsysdcfgdatadata555rootsysspace文件#extraspacerequiredbyconfigdatawhichis#dynamicallyloadedontothesystemdata5001i.
admin类操作脚本#PKGINSTparameterprovidedbyinstallationservice#BASEDIRparameterprovidedbyinstallationservicewhilereadsrcdestdocp$src$dest||exit2在安装时创建文件并在删除期间保存文件应用程序包开发者指南2009年4月94done#ifthisisthelasttimethisscriptwillbeexecuted#duringtheinstallation,doadditionalprocessinghere.
if["$1"=ENDOFCLASS]then#ourconfigprocesswillcreateadatafilebasedonanychanges#madebyinstallingfilesinthisclass;makesurethedatafile#isinclass'cfgdata'sospecialrulescanapplytoitduring#packageremoval.
installf-ccfgdata$PKGINST$BASEDIR/data/config.
dataf444rootsys||exit2$BASEDIR/bin/config>$BASEDIR/data/config.
data||exit2installf-f-ccfgdata$PKGINST||exit2fiexit0这里举例说明了一个很少见的实例,其中installf适用于类操作脚本.
由于space文件用于在特定文件系统上保留空间,因此即使该新文件没有包括在pkgmap文件中也可以被安全地添加.
r.
cfgdata删除脚本#theproductmanagerforthispackagehassuggestedthat#theconfigurationdataissovaluablethatitshouldbe#backedupto$PKGSAVbeforeitisremoved!
whilereadpathdo#pathnamesappearinreverselexicalorder.
mv$path$PKGSAV||exit2rm-f$path||exit2doneexit0定义软件包兼容性和相关性在此案例研究中,软件包使用可选信息文件来定义软件包兼容性和相关性,以及在安装期间呈现版权新息.
技术此案例研究展示以下技术:使用copyright文件使用compver文件使用depend文件定义软件包兼容性和相关性第5章软件包创建案例研究95有关这些文件的更多信息,请参见第46页中的"创建信息文件".
方法要符合描述中的要求,您必须:创建copyright文件.
copyright文件包含版权信息的ASCII文本.
样例文件中所示的信息将在软件包安装期间显示在屏幕上.
创建compver文件.
下图中显示的pkginfo文件将此软件包版本定义为3.
0版.
compver文件将3.
0版定义为与2.
3、2.
2、2.
1、2.
1.
1、2.
1.
3和1.
7版兼容.
创建depend文件.
安装软件包时depend文件中列出的文件必须已经安装在系统上.
示例文件有11个软件包,安装时这些软件包必须已安装在系统上.
案例研究文件pkginfo文件PKG=case3NAME=CaseStudy#3CATEGORY=applicationBASEDIR=/optARCH=SPARCVERSION=Version3.
0CLASSES=nonecopyright文件Copyright(c)1999company_nameAllRightsReserved.
THISPACKAGECONTAINSUNPUBLISHEDPROPRIETARYSOURCECODEOFcompany_name.
Thecopyrightnoticeabovedoesnotevidenceanyactualorintendedpublicationofsuchsourcecodecompver文件Version3.
0Version2.
3Version2.
2定义软件包兼容性和相关性应用程序包开发者指南2009年4月96Version2.
1Version2.
1.
1Version2.
1.
3Version1.
7depend文件PacuAdvancedCUtilitiesIssue4Version1PccCProgrammingLanguageIssue4Version1PdfmDirectoryandFileManagementUtilitiesPedEditingUtilitiesPesgExtendedSoftwareGenerationUtilitiesIssue4Version1PgraphGraphicsUtilitiesPrfsRemoteFileSharingUtilitiesIssue1Version1PrxRemoteExecutionUtilitiesPsgsSoftwareGenerationUtilitiesIssue4Version1PshellShellProgrammingUtilitiesPsysSystemHeaderFilesRelease3.
1使用标准类和类操作脚本修改文件在此案例研究中,使用标准类和类操作脚本在软件包安装期间修改现有文件.
它使用三种修改方法之一.
另外两种方法将在第100页中的"使用sed类和postinstall脚本修改文件"和第102页中的"使用build类修改文件"中进行介绍.
修改的文件是/etc/inittab.
技术此案例研究展示如何使用安装类操作脚本和删除类操作脚本.
有关更多信息,请参见第62页中的"编写类操作脚本".
方法要使用类和类操作脚本在安装期间修改/etc/inittab,您必须完成以下任务:创建一个类.
创建名为inittab的类.
必须为该类提供安装和删除类操作脚本.
在pkginfo文件的CLASSES参数中定义inittab类.
使用标准类和类操作脚本修改文件第5章软件包创建案例研究97创建一个inittab文件.
此文件包含将添加到/etc/inittab的条目的信息.
请注意在prototype文件图中,inittab是inittab类的成员并且文件类型为e(表示可编辑).
创建安装类操作脚本(i.
inittab).
切记类操作脚本每次执行时都必须产生相同结果.
类操作脚本执行以下过程:检查以前是否已添加该条目如果是,删除该条目的所有以前版本编辑inittab文件并添加注释行,以便您知道该条目的来源将临时文件移回/etc/inittab当收到ENDOFCLASS指示符时,执行initq命令请注意,此安装脚本可执行initq命令.
此方法不需要使用只有一行的postinstall脚本.
创建删除类操作脚本(r.
inittab).
删除脚本与安装脚本非常类似.
安装脚本添加的信息会被删除,而且会执行initq命令.
此案例研究比下一个更为复杂;请参见第100页中的"使用sed类和postinstall脚本修改文件".
在此案例研究中,不是提供两个文件而是需要三个文件,而且提供的/etc/inittab文件实际上只是包含要插入的条目片段的占位符.
此占位符可能已被放置到i.
inittab文件中,除非pkgadd命令必须将一个文件传递到i.
inittab文件.
此外,必须将删除过程放置到一个单独的文件(r.
inittab)中.
虽然此方法效果很好,但最好将其保留为在涉及多个文件的非常复杂的安装情况下使用.
请参见第103页中的"在安装期间修改crontab文件".
由于inittab条目末尾的注释基于软件包实例,因此第100页中的"使用sed类和postinstall脚本修改文件"中使用的sed程序支持多个软件包实例.
第102页中的"使用build类修改文件"中的案例研究给出了一种在安装期间编辑/etc/inittab的更简化的方法.
案例研究文件pkginfo文件PKG=case5NAME=CaseStudy#5CATEGORY=applicationsBASEDIR=/optARCH=SPARCVERSION=Version1d05CLASSES=inittab使用标准类和类操作脚本修改文件应用程序包开发者指南2009年4月98prototype文件ipkginfoii.
inittabir.
inittabeinittab/etc/inittabi.
inittab安装类操作脚本#PKGINSTparameterprovidedbyinstallationservicewhilereadsrcdestdo#removeallentriesfromthetablethat#associatedwiththisPKGINSTsed-ePKGINST$/d"$dest>/tmp/$$itab||exit2sed-e"s/$/#$PKGINST"$src>>/tmp/$$itab||exit2mv/tmp/$$itab$dest||exit2doneif["$1"=ENDOFCLASS]then/sbin/initq||exit2fiexit0r.
inittab删除类操作脚本#PKGINSTparameterprovidedbyinstallationservicewhilereadsrcdestdo#removeallentriesfromthetablethat#areassociatedwiththisPKGINSTsed-ePKGINST$/d"$dest>/tmp/$$itab||exit2mv/tmp/$$itab$dest||exit2done/sbin/initq||exit2exit0inittab文件rb:023456:wait:/usr/robot/bin/setup使用标准类和类操作脚本修改文件第5章软件包创建案例研究99使用sed类和postinstall脚本修改文件此案例研究在软件包安装期间修改安装计算机上存在的一个文件.
它使用三种修改方法之一.
另外两种方法将在第97页中的"使用标准类和类操作脚本修改文件"和第102页中的"使用build类修改文件"中进行介绍.
修改的文件是/etc/inittab.
技术此案例研究展示以下技术:使用sed类有关sed类的更多信息,请参见第65页中的"sed类脚本".
使用postinstall脚本有关此脚本的更多信息,请参见第60页中的"编写过程脚本".
方法要使用sed类在安装时修改/etc/inittab,您必须完成以下任务:将sed类脚本添加到prototype文件.
脚本的名称必须是将编辑文件的名称.
在本例中,将编辑的文件是/etc/inittab,因此sed脚本被命名为/etc/inittab.
对于sed脚本的模式、所有者和组没有要求(在样例prototype中由问号表示).
sed脚本的文件类型必须是e(表示可编辑).
设置CLASSES参数以包括sed类.
如示例文件所示,sed是待安装的唯一类.
不过,类的数目可以是任意的.
创建sed类操作脚本.
您的软件包不能提供您希望的形式的/etc/inittab副本,因为/etc/inittab是一个动态文件,您无法知道它在软件包安装时的外观形式.
不过,可使用sed脚本在软件包安装期间修改/etc/inittab文件.
创建postinstall脚本.
您需要执行initq命令通知系统/etc/inittab已被修改.
在此示例中,您可以执行该操作的唯一位置是在postinstall脚本中.
查看postinstall示例脚本,您会发现它的唯一作用是执行initq命令.
这种在安装期间编辑/etc/inittab的方法有一个缺点:虽然只是为了执行initq命令也必须提供一个完整的脚本(postinstall脚本).
使用sed类和postinstall脚本修改文件应用程序包开发者指南2009年4月100案例研究文件pkginfo文件PKG=case4NAME=CaseStudy#4CATEGORY=applicationsBASEDIR=/optARCH=SPARCVERSION=Version1d05CLASSES=sedprototype文件ipkginfoipostinstallesed/etc/inittabsed类操作脚本(/etc/inittab)!
remove#removeallentriesfromthetablethatareassociated#withthispackage,thoughnotnecessarilyjust#withthispackageinstanceROBOT$/d!
install#removeanypreviousentryaddedtothetable#forthisparticularchangeROBOT$/d#addtheneededentryattheendofthetable;#sed(1)doesnotproperlyinterpretthe'$a'#constructifyoupreviouslydeletedthelast#line,sothecommand#$a\#rb:023456:wait:/usr/robot/bin/setup#ROBOT#willnotworkhereifthefilealreadycontained#themodification.
Instead,youwillsettlefor#insertingtheentrybeforethelastline!
$i\rb:023456:wait:/usr/robot/bin/setup#ROBOTpostinstall脚本#makeinitre-readinittab/sbin/initq||exit2exit0使用sed类和postinstall脚本修改文件第5章软件包创建案例研究101使用build类修改文件此案例研究在软件包安装期间修改安装计算机上存在的一个文件.
它使用三种修改方法之一.
另外两种方法将在第97页中的"使用标准类和类操作脚本修改文件"和第100页中的"使用sed类和postinstall脚本修改文件"中进行介绍.
修改的文件是/etc/inittab.
技术此案例研究展示如何使用build类.
有关build类的更多信息,请参见第66页中的"build类脚本".
方法这种修改/etc/inittab的方法使用build类.
build类脚本作为shell脚本执行,其输出成为正在执行的文件的新版本.
换句话说,与该软件包一起提供的/etc/inittab数据文件将会执行,执行后的输出将成为/etc/inittab.
build类脚本在软件包安装和删除期间执行.
如果该文件在安装时执行,参数install会传递给该文件.
请注意在build样例类脚本中,安装操作通过测试此参数来定义.
要使用build类编辑/etc/inittab,您必须完成以下任务:在prototype文件中定义生成文件.
prototype文件中的生成文件条目应将该文件放置在build类中,并将其文件类型定义为e.
请确保将pkginfo文件中的CLASSES参数定义为build.
创建build类脚本.
build样例类脚本执行以下过程:编辑/etc/inittab文件以删除对该软件包的任何现有更改.
请注意,文件名/etc/inittab已被硬编码到sed命令中.
如果正在安装软件包,将新行添加到/etc/inittab的末尾.
一个注释标记会包括在该新条目中,用于描述该条目的来源.
执行initq命令.
该解决方案解决了在第97页中的"使用标准类和类操作脚本修改文件"和第100页中的"使用sed类和postinstall脚本修改文件"的案例研究中描述的缺点.
只需要一个很短的文件(除pkginfo和prototype文件之外).
因为使用了PKGINST参数,所以该文件适用于软件包的多个实例,而且由于initq命令可从build类脚本中执行,因此不需要postinstall脚本.
使用build类修改文件应用程序包开发者指南2009年4月102案例研究文件pkginfo文件PKG=case6NAME=CaseStudy#6CATEGORY=applicationsBASEDIR=/optARCH=SPARCVERSION=Version1d05CLASSES=buildprototype文件ipkginfoebuild/etc/inittab生成文件#PKGINSTparameterprovidedbyinstallationservice#removeallentriesfromtheexistingtablethat#areassociatedwiththisPKGINSTsed-ePKGINST$/d"/etc/inittab||exit2if["$1"=install]then#addthefollowingentrytothetableecho"rb:023456:wait:/usr/robot/bin/setup#$PKGINST"||exit2fi/sbin/initq||exit2exit0在安装期间修改crontab文件此案例研究在软件包安装期间修改crontab文件.
技术此案例研究展示以下技术:使用类和类操作脚本有关更多信息,请参见第62页中的"编写类操作脚本".
在安装期间修改crontab文件第5章软件包创建案例研究103在类操作脚本中使用crontab命令.
方法在安装期间编辑多个文件的最高效方式是定义一个类,然后提供类操作脚本.
如果您使用了build类方法,您将需要为每个编辑的crontab文件提供一个build类脚本.
定义cron类是一种更通用的方法.
要使用这种方法编辑crontab文件,您必须:在prototype文件中定义将编辑的crontab文件.
在prototype文件中为每个将编辑的crontab文件创建一个条目.
对于每个文件,将类定义为cron并将文件类型定义为e.
使用将编辑的文件的实际名称.
为软件包创建crontab文件.
这些文件包含您希望添加到同名的现有crontab文件的信息.
为cron类创建安装类操作脚本.
i.
cron样例脚本执行以下过程:确定用户ID(userID,UID).
i.
cron脚本将user变量设置为正在处理的cron类脚本的基名.
该名称是UID.
例如,/var/spool/cron/crontabs/root的基名是root,该基名也是UID.
使用UID和-l选项执行crontab.
使用-l选项会告诉crontab为定义的用户将crontab文件内容发送到标准输出.
将crontab命令的输出通过管道输出到sed脚本,该脚本用于删除以前使用该安装技术添加的所有条目.
将编辑的输出放置到临时文件中.
将rootUID对应的数据文件(随软件包提供)添加到临时文件,并添加一个标记,以便您知道这些条目的来源.
使用同一UID执行crontab,并使用临时文件作为其输入.
为cron类创建删除类操作脚本.
r.
cron脚本与安装脚本基本相同,只不过前者没有用于向crontab文件添加信息的过程.
这些过程针对cron类中的每个文件执行.
案例研究文件下述i.
cron和r.
cron脚本由超级用户执行.
以超级用户身份编辑其他用户的crontab文件可能导致无法预测的结果.
如果需要,请在每个脚本中将以下条目:crontab$user/tmp/$$crontab)||exit2sed-e"s/$/#$PKGINST/"$src>>/tmp/$$crontab||exit2crontab$user/tmp/$$crontab)||exit2crontab$user/dev/null4523***ulimit5000;/usr/bin/suuucp-c"/usr/lib/uucp/uudemon.
cleanup">/dev/null2>&111,31,51usr/lib/uucp/uudemon.
poll>/dev/nullcrontab文件#20***0-6/usr/lib/sa/sa120,408-17**1-5/usr/lib/sa/sa1518**1-5/usr/lib/sa/sa2-s8:00-e18:01-i1200-A注–如果对一组文件的编辑将导致文件总大小增加超过10K,请提供一个space文件,以便pkgadd命令可以允许这种增加.
有关space文件的更多信息,请参见第50页中的"在目标系统上保留额外空间".
使用过程脚本安装和删除驱动程序此软件包可安装驱动程序.
技术此案例研究展示以下技术:使用postinstall脚本安装和装入驱动程序使用preremove脚本卸载驱动程序有关这些脚本的更多信息,请参见第60页中的"编写过程脚本".
方法创建request脚本.
使用过程脚本安装和删除驱动程序应用程序包开发者指南2009年4月106request脚本通过询问管理员并将答复指定给$KERNDIR参数,确定管理员希望将驱动程序对象安装到的位置.
该脚本以一个例程结束,以使两个参数(即,CLASSES和KERNDIR)对于安装环境和postinstall脚本可用.
创建postinstall脚本.
postinstall脚本实际上执行驱动程序安装.
该脚本在buffer和buffer.
conf两个文件安装后执行.
在此示例中显示的postinstall文件执行以下操作:使用add_drv命令将驱动程序装入到系统.
使用installf命令为设备创建链接.
使用installf-f命令完成安装.
创建preremove脚本.
preremove脚本使用rem_drv命令从系统卸载驱动程序,然后删除链接/dev/buffer0.
案例研究文件pkginfo文件PKG=bufdevNAME=BufferDeviceCATEGORY=systemBASEDIR=/ARCH=INTELVERSION=SoftwareIssue#19CLASSES=noneprototype文件要在安装时安装驱动程序,您必须在prototype文件中包括驱动程序的对象和配置文件.
在此示例中,驱动程序的可执行模块被命名为buffer;add_drv命令处理该文件.
内核使用配置文件buffer.
conf帮助配置驱动程序.
ipkginfoirequestipostinstallipreremovefnone$KERNDIR/buffer444rootrootfnone$KERNDIR/buffer.
conf444rootroot查看此示例中的prototype文件,请注意以下事项:使用过程脚本安装和删除驱动程序第5章软件包创建案例研究107因为不需要对软件包对象进行特殊处理,所以您可以将其放置在none标准类中.
在pkginfo文件中CLASSES参数被设置为none.
buffer和buffer.
conf的路径名以变量$KERNDIR开头.
此变量在request脚本中设置,允许管理员决定驱动程序文件的安装位置.
缺省目录是/kernel/drv.
postinstall脚本(将执行驱动程序安装的脚本)有一个对应条目.
request脚本trap'exit3'15#determinewheredriverobjectshouldbeplaced;location#mustbeanabsolutepathnamethatisanexistingdirectoryKERNDIR='ckpath-aoy-d/kernel/drv-p\"Wheredoyouwantthedriverobjectinstalled"'||exit$#makeparametersavailabletoinstallationservice,and#sotoanyotherpackagingscriptscat>$1prototype上述命令的输出如下所示:dnoneusr0775pmsmtsdnoneusr/include0775pmsmtsdnoneusr/include/sys0775pmsmtsdnoneusr/include/sys/scsi0775pmsmtsdnoneusr/include/sys/scsi/targets0775pmsmtsfnoneusr/include/sys/scsi/targets/sst_def.
h0444pmsmtsdnoneusr/kernel0775pmsmtsdnoneusr/kernel/drv0775pmsmtsfnoneusr/kernel/drv/sst0664pmsmtsfnoneusr/kernel/drv/sst.
conf0444pmsmtsdnoneSUNWsst0775pmsmtsfnoneSUNWsst/sstest.
c0664pmsmts此prototype文件并不是完整文件.
要完成此文件,您需要进行以下修改:插入控制文件(文件类型i)条目,因为它们与其他软件包对象的格式不同.
删除目标系统上已存在的目录的条目.
更改每个条目的访问权限和拥有权.
在绝对软件包对象之前添加一个斜线.
以下是最终的prototype文件:ipkginfoipostinstallipreremoveicopyrightesed/etc/devlink.
tabfnone/usr/include/sys/scsi/targets/sst_def.
h0644binbinfnone/usr/kernel/drv/sst0755rootsysfnone/usr/kernel/drv/sst.
conf0644rootsysdnoneSUNWsst0775rootsysfnoneSUNWsst/sstest.
c0664rootsyssed脚本条目中的问号表明不应更改安装计算机上现有文件的访问权限和拥有权.

使用sed类和过程脚本安装驱动程序第5章软件包创建案例研究111sed类操作脚本(/etc/devlink.
tab)在驱动程序示例中,sed类脚本用于向/etc/devlink.
tab文件中添加一个驱动程序条目.
devlinks命令使用此文件创建从/dev到/devices的符号链接.
以下是sed脚本:#sedclassscripttomodify/etc/devlink.
tab!
install/name=sst;/d$i\type=ddi_pseudo;name=sst;minor=characterrsst\\A1!
remove/name=sst;/dpkgrm命令不运行该脚本的删除部分.
您可能需要向preremove脚本中添加一行,以便直接运行sed从/etc/devlink.
tab文件删除条目.
postinstall安装脚本在此示例中,该脚本所需要做的只是运行add_drv命令.
#PostinstallationscriptforSUNWsst#Thisdoesnotapplytoaclient.
if[$PKG_INSTALL_ROOT="/"-o-z$PKG_INSTALL_ROOT];thenSAVEBASE=$BASEDIRBASEDIR="";exportBASEDIR/usr/sbin/add_drvsstSTATUS=$BASEDIR=$SAVEBASE;exportBASEDIRif[$STATUS-eq0]thenexit20elseexit2fielseecho"Thiscannotbeinstalledontoaclient.
"exit2fiadd_drv命令使用BASEDIR参数,因此该脚本必须在运行此命令之前取消设置BASEDIR,并在以后恢复它.
add_drv命令的操作之一是运行devlinks,它使用由sed类脚本放置在/etc/devlink.
tab中的条目为驱动程序创建/dev条目.
postinstall脚本的退出代码作用很重要.
退出代码20告诉pkgadd命令告知用户重新引导系统(安装驱动程序后必须这样做),而退出代码2则告诉pkgadd命令告知用户安装部分失败.
使用sed类和过程脚本安装驱动程序应用程序包开发者指南2009年4月112preremove删除脚本在此驱动程序示例中,该脚本删除/dev中的链接并对驱动程序运行rem_drv命令.
#Preremovalscriptforthesstdriverecho"Removing/deventries"/usr/bin/rm-f/dev/rsst*echo"Deinstallingdriverfromthekernel"SAVEBASE=$BASEDIRBASEDIR="";exportBASEDIR/usr/sbin/rem_drvsstBASEDIR=$SAVEBASE;exportBASEDIRexit该脚本删除/dev条目本身;/devices条目由rem_drv命令删除.
copyright文件以下是一个包含版权声明文本的简单ASCII文件.
该声明在软件包安装开始时显示,显示时与此文件中的形式完全相同.
Copyright(c)1999Drivers-R-Us,Inc.
10DeviceDrive,Thebus,IO80586Allrightsreserved.
Thisproductandrelateddocumentationisprotectedbycopyrightanddistributedunderlicensesrestrictingitsuse,copying,distributionanddecompilation.
NopartofthisproductorrelateddocumentationmaybereproducedinanyformbyanymeanswithoutpriorwrittenauthorizationofDrivers-R-Usanditslicensors,ifany.
使用sed类和过程脚本安装驱动程序第5章软件包创建案例研究113114创建软件包的高级技术SolarisOS中实现的SystemV打包的完整功能提供了一个用于安装软件产品的强大工具.
作为软件包设计者,您可以利用这些功能.
不属于SolarisOS的软件包(非随附软件包)可以使用类机制来定制服务器/客户机安装.
可针对管理员的需要设计可重定位的软件包.
复杂产品可以通过能够自动解决软件包相关性问题的复合软件包集合形式提供.
升级和修补可由软件包设计者定制.
修补的软件包可以按照与未修补的软件包相同的方式提供,并且产品中还可以包括回退归档.
以下是本章中概述信息的列表.
第115页中的"指定基目录"第119页中的"适应重定位"第127页中的"在异构环境中支持重定位"第136页中的"使软件包可远程安装"第138页中的"修补软件包"第161页中的"升级软件包"第163页中的"创建类归档软件包"指定基目录您可以使用多种方法指定软件包的安装位置,而且很重要的一点是能够在安装时动态更改安装基本位置.
如果正确实现了此功能,管理员便可以轻松安装多个版本和多个体系结构.
本节首先讨论常用方法,然后讨论能够改进异构系统上的安装的途径.
缺省管理文件负责安装软件包的管理员可以使用管理文件来控制软件包安装.
然而,作为软件包设计者,您需要了解有关管理文件的信息,并了解管理员如何能够改变您计划的软件包安装.
6第6章115管理文件告诉pkgadd命令是否执行它通常执行的任何检查或提示.
因此,管理员在使用管理文件之前应该充分了解软件包的安装过程和涉及的脚本.
缺省基本管理文件随SunOS操作系统一起提供,位于/var/sadm/install/admin/default中.
该文件建立了与软件产品安装有关的最基本级别的管理策略.
随操作系统一起提供的该文件如下所示:#ident"@(#)default1.
492/12/23SMI"/*SVr4.
01.
5.
2.
1*/mail=instance=uniquepartial=askrunlevel=askidepend=askrdepend=askspace=asksetuid=askconflict=askaction=askbasedir=default管理员可以编辑此文件以建立新的缺省行为,或者创建一个不同的管理文件并使用pkgadd命令的-a选项指定其存在.
在一个管理文件中可以定义11个参数,但并非所有参数都必须定义.
有关更多信息,请参见admin(4).
basedir参数指定在安装软件包时如何派生基目录.
大多数管理员都将此参数保留为default,但可以将basedir设置为以下值之一:ask,表示始终要求管理员提供基目录绝对路径名包含$PKGINST构造的绝对路径名,表示始终安装到派生于软件包实例的基目录注–如果带有参数-anone调用了pkgadd命令,则该命令始终要求管理员提供基目录.
遗憾的是,这还会将文件中的所有参数设置为缺省值quit,而这可能会导致其他问题.
适应不确定性管理员可使用管理文件来控制系统上正安装的所有软件包.
遗憾的是,软件包设计者经常提供一个替代的缺省管理文件,而没有考虑管理员的愿望.
软件包设计者有时会提供一个替代管理文件,以便他们自己(而不是管理员)能够控制软件包的安装.
由于缺省管理文件中的basedir条目会覆盖所有其他基目录,因此它提供了一种在安装时选择适当基目录的简单方法.
在早于Solaris2.
5发行版的所有SolarisOS版本中,这种方法被认为是控制基目录的最简单方法.
指定基目录应用程序包开发者指南2009年4月116然而,您必须接受管理员的有关产品安装的希望.
提供一个临时的缺省管理文件以便控制安装会导致管理员觉得不受信任.
您应该使用request脚本和checkinstall脚本在管理员的监督下控制这些安装.
如果request脚本如实地使管理员参与安装过程,SystemV打包过程将同时满足管理员和软件包设计者的需求.
使用BASEDIR参数pkginfo文件都必须以如下所示的条目形式包括一个缺省基目录:BASEDIR=absolute_path这只是缺省基目录,可由管理员在安装期间更改.
尽管某些软件包需要多个基目录,但使用此参数定位软件包的好处是,当安装开始的时候,能够保证基目录作为一个有效的目录就位并可写.
服务器和客户机的基目录的正确路径以保留环境变量的形式供所有过程脚本使用,并且pkginfo-rSUNWstuf命令显示软件包的当前安装基本位置.
在checkinstall脚本中,BASEDIR即是pkginfo文件中定义的该参数(该参数尚未根据条件赋值).
为了检查目标基目录,需要使用${PKG_INSTALL_ROOT}$BASEDIR构造.
这意味着request或checkinstall脚本可以在安装环境下更改BASEDIR的值,并且可以获得可预测的结果.
当调用preinstall脚本时,BASEDIR参数是指向目标系统上实际基目录的完全根据条件设置的指针,即使该系统是客户机也是如此.
注–对于不同的SunOS操作系统发行版,request脚本以不同方式利用BASEDIR参数.
为了在request脚本中测试BASEDIR参数,应该使用下面的代码来确定正在使用的实际基目录.
#requestscriptconstructsbasedirectoryif[${CLIENT_BASEDIR}];thenLOCAL_BASE=$BASEDIRelseLOCAL_BASE=${PKG_INSTALL_ROOT}$BASEDIRfi使用参数化基目录如果一个软件包需要多个基目录,您可以使用参数化路径名建立这些目录.
此方法已经相当流行,尽管它具有以下缺点.
具有参数化路径名的软件包的行为方式通常类似于绝对软件包,但pkgadd命令会像处理可重定位的软件包一样处理该软件包.
必须定义BASEDIR参数(即使没有使用).
指定基目录第6章创建软件包的高级技术117管理员无法使用SystemV实用程序确定软件包的安装基本位置(pkginfo-r命令不起作用).
管理员无法使用既定的方法重定位软件包(它称为可重定位的软件包,但是其行为方式与绝对软件包相同).
多体系结构或多版本的安装要求对每个目标基目录进行意外事件计划,这通常意味着使用多个复杂的类操作脚本.
尽管确定基目录的参数是在pkginfo文件中定义的,但可以被request脚本修改.
这是此方法广受欢迎的主要原因之一.
然而,此方法的缺点会长期存在,您应该在迫不得已的情况下才考虑使用此配置.
示例-使用参数化基目录pkginfo文件#pkginfofilePKG=SUNWstufNAME=softwarestuffARCH=sparcVERSION=1.
0.
0,REV=1.
0.
5CATEGORY=applicationDESC=asetofutilitiesthatdostuffBASEDIR=/EZDIR=/usr/stuf/EZstufHRDDIR=/opt/SUNWstuf/HRDstufVENDOR=SunMicrosystems,Inc.
HOTLINE=PleasecontactyourlocalserviceproviderEMAIL=MAXINST=1000CLASSES=nonePSTAMP=hubert980707141632pkgmap文件:117581dnone$EZDIR0775rootbin1fnone$EZDIR/dirdel0555binbin407737513102291fnone$EZDIR/usrdel0555binbin407737513102291fnone$EZDIR/filedel0555binbin407737513102291dnone$HRDDIR0775rootbin1fnone$HRDDIR/mksmart0555binbin407737513102291fnone$HRDDIR/mktall0555binbin407737513102291fnone$HRDDIR/mkcute0555binbin407737513102291fnone$HRDDIR/mkeasy0555binbin407737513102291dnone/etc1dnone/etc/rc2.
d指定基目录应用程序包开发者指南2009年4月1181fnone/etc/rc2.
d/S70dostuf0744rootsys4502234431ipkginfo348284117607401631ipostinstall323264757513099081ipostremove402331797513099451ipreinstall321262547513100191ipreremove32026114751309865管理基目录如有必要,任何具有多个版本或多种体系结构的软件包都应该设计为遍历基目录.
遍历基目录意味着如果基目录中已经存在要安装的软件包的以前版本或不同体系结构,则要安装的软件包会解决此问题,方法可能是使用稍微不同的名称创建一个新的基目录.
Solaris2.
5和兼容发行版中的request和checkinstall脚本能够修改BASEDIR环境变量.
对于SolarisOS的任何更早版本,情况则不是这样的.
即使在SolarisOS的较早版本中,request脚本也有权在安装基本位置中重新定义目录.
request脚本可以采用仍然支持多数管理首选项的方法完成此操作.
适应重定位尽管您可以为各种软件包选择能够保证对某个体系结构和版本唯一的基目录,但这会导致目录分层结构中存在多余的级别.
例如,对于为基于SPARC和x86的处理器设计的产品,您可能会根据处理器和版本组织基目录,如下所示.
基目录版本和处理器/opt/SUNWstuf/sparc/1.
01.
0版,SPARC/opt/SUNWstuf/sparc/1.
21.
2版,SPARC/opt/SUNWstuf/x86/1.
01.
0版,x86这样做完全可以而且有效,但是您处理名称和编号的方式就好像它们对管理员有意义一样.
一种更好的方法是在向管理员进行解释并获取权限之后自动完成此工作.

这意味着您可以在软件包中完成全部工作,而无需要求管理员手动完成.
您可以在postinstall脚本中任意指定基目录,然后透明地建立适当的客户机链接.
您还可以在postinstall脚本中使用pkgadd命令在客户机上安装软件包的全部或一部分.
您甚至可以咨询管理员哪些用户或客户机需要了解此软件包,并自动更新PATH环境变量和/etc文件.
只要软件包在安装时执行的所有操作能够在删除时撤消,那么该方法是完全可以接受的.
适应重定位第6章创建软件包的高级技术119遍历基目录您可以利用两种方法在安装时控制基目录.
第一种方法最适合于仅能安装在Solaris2.
5和兼容发行版上的新软件包;它为管理员提供非常有用的数据,支持多个已安装的版本和体系结构,而只需要完成最少的特殊工作.
第二种方法可由任何软件包使用,并且利用request脚本所固有的对于生成参数的控制来确保安装成功.
使用BASEDIR参数checkinstall脚本可以在安装时选择适当的基目录,这意味着可以将基目录放置在目录树中非常低的位置.
此示例按顺序递增基目录,从而得到如下形式的目录:/opt/SUNWstuf、/opt/SUNWstuf.
1和/opt/SUNWstuf.
2.
管理员可以使用pkginfo命令确定在每个基目录中所安装的体系结构和版本.
如果SUNWstuf软件包(包含一组执行具体工作的实用程序)使用此方法,则它的pkginfo和pkgmap文件将如下所示.
pkginfo文件#pkginfofilePKG=SUNWstufNAME=softwarestuffARCH=sparcVERSION=1.
0.
0,REV=1.
0.
5CATEGORY=applicationDESC=asetofutilitiesthatdostuffBASEDIR=/opt/SUNWstufVENDOR=SunMicrosystems,Inc.
HOTLINE=PleasecontactyourlocalserviceproviderEMAIL=MAXINST=1000CLASSES=nonedaemonPSTAMP=hubert990707141632pkgmap文件:117581dnoneEZstuf0775rootbin1fnoneEZstuf/dirdel0555binbin407737513102291fnoneEZstuf/usrdel0555binbin407737513102291fnoneEZstuf/filedel0555binbin407737513102291dnoneHRDstuf0775rootbin1fnoneHRDstuf/mksmart0555binbin407737513102291fnoneHRDstuf/mktall0555binbin407737513102291fnoneHRDstuf/mkcute0555binbin407737513102291fnoneHRDstuf/mkeasy0555binbin407737513102291dnone/etc适应重定位应用程序包开发者指南2009年4月1201dnone/etc/rc2.
d1fdaemon/etc/rc2.
d/S70dostuf0744rootsys4502234431ipkginfo348284117607401631ipostinstall323264757513099081ipostremove402331797513099451ipreinstall321262547513100191ipreremove320261147513098651ii.
daemon509395607529781031ir.
daemon32024573742152591示例-遍历BASEDIR的分析脚本假定SUNWstuf的x86版本已经安装在服务器上的/opt/SUNWstuf中.
当管理员使用pkgadd命令安装SPARC版本时,request脚本需要检测是否存在x86版本并且与管理员就安装问题进行交互.
注–可在checkinstall脚本中遍历基目录而无需管理员交互,但是,如果此类任意操作的发生过于频繁,管理员会在此过程中失去信心.
软件包的用于处理此情形的request脚本和checkinstall脚本可能如下所示.
request脚本#requestscriptforSUNWstuftowalktheBASEDIRparameter.
PATH=/usr/sadm/bin:${PATH}#useadminutilitiesGENMSG="Thebasedirectory$LOCAL_BASEalreadycontainsa\differentarchitectureorversionof$PKG.
"OLDMSG="Iftheoption\"-anone\"wasused,pressthe\keyandenteranunusedbasedirectorywhenitisrequested.
"OLDPROMPT="Doyouwanttooverwritethisversion"OLDHELP="\"y\"willreplacetheinstalledpackage,\"n\"will\stoptheinstallation.
"SUSPEND="Suspendinginstallationatuserrequestusingerror\code1.
"MSG="Thispackagecouldbeinstalledattheunusedbasedirectory$WRKNG_BASE.
"PROMPT="Doyouwanttousetotheproposedbasedirectory"适应重定位第6章创建软件包的高级技术121HELP="Aresponseof\"y\"willinstalltotheproposeddirectoryandcontinue,\"n\"willrequestadifferentdirectory.
Iftheoption\"-anone\"wasused,pressthekeyandenteranunusedbasedirectorywhenitisrequested.
"DIRPROMPT="Selectapreferredbasedirectory($WRKNG_BASE)"DIRHELP="Thepackage$PKGwillbeinstalledatthelocationentered.
"NUBD_MSG="Thebasedirectoryhaschanged.
Besuretoupdate\anyapplicablesearchpathswiththeactuallocationofthe\binarieswhichareat$WRKNG_BASE/EZstufand$WRKNG_BASE/HRDstuf.
"OldSolaris=""Changed=""Suffix="0"##Determineifthisproductisactuallyinstalledintheworking#basedirectory.
#Product_is_present(){if[-d$WRKNG_BASE/EZstuf-o-d$WRKNG_BASE/HRDstuf];thenreturn1elsereturn0fi}if[${BASEDIR}];then#ThismaybeanoldversionofSolaris.
InthelatestSolaris#CLIENT_BASEDIRwon'tbedefinedyet.
Inolderversionitis.
if[${CLIENT_BASEDIR}];thenLOCAL_BASE=$BASEDIROldSolaris="true"else#Thebasedirectoryhasn'tbeenprocessedyetLOCAL_BASE=${PKG_INSTALL_ROOT}$BASEDIRfiWRKNG_BASE=$LOCAL_BASE#Seeifthebasedirectoryisalreadyinplaceandwalkitif#possiblewhile[-d${WRKNG_BASE}-aProduct_is_present];do#Thereisaconflict#Isthisanupdateofthesamearch&versionif[${UPDATE}];thenexit0#It'soutofourhands.
else适应重定位应用程序包开发者指南2009年4月122#Sothisisadifferentarchitectureor#versionthanwhatisalreadythere.
#WalkthebasedirectorySuffix='expr$Suffix+1'WRKNG_BASE=$LOCAL_BASE.
$SuffixChanged="true"fidone#Sonowwecanproposeabasedirectorythatisn'tclaimedby#anyofourotherversions.
if[$Changed];thenputtext"$GENMSG"if[$OldSolaris];thenputtext"$OLDMSG"result='ckyorn-Q-d"a"-h"$OLDHELP"-p"$OLDPROMPT"'if[$result="n"];thenputtext"$SUSPEND"exit1#suspendinstallationelseexit0fielse#Thelatestfunctionalityisavailableputtext"$MSG"result='ckyorn-Q-d"a"-h"$HELP"-p"$PROMPT"'if[$-eq3];thenechoquitinstall>>$1exit0fiif[$result="n"];thenWRKNG_BASE='ckpath-ayw-d"$WRKNG_BASE"\-h"$DIRHELP"-p"$DIRPROMPT"'elseif[$result="a"]exit0fifiecho"BASEDIR=$WRKNG_BASE">>$1puttext"$NUBD_MSG"fifiexit0checkinstall脚本#checkinstallscriptforSUNWstuftopolitelysuspend适应重定位第6章创建软件包的高级技术123grepquitinstall$1if[$-eq0];thenexit3#politelysuspendinstallationfiexit0如果基目录仅仅是/opt,则此方法不会非常有效.
因为/opt难以遍历,所以此软件包必须更加准确地调用BASEDIR.
实际上,根据挂载方案的不同,可能无法实现这一点.
此示例通过在/opt下创建一个新目录来遍历基目录,这种方法不会导致任何问题.
此示例使用request脚本和checkinstall脚本,即使Solaris2.
5发行版以前的版本无法运行checkinstall脚本.
此示例中的checkinstall脚本用于正常停止安装,以响应一个采用quitinstall字符串形式的专用消息.
如果此脚本在Solaris2.
3发行版中执行,checkinstall脚本将被忽略,而request脚本将停止安装并显示错误消息.
请记住,在Solaris2.
5和兼容发行版之前,BASEDIR参数是一个只读参数,不能通过request脚本更改.
因此,如果检测到SunOS操作系统的早期版本(通过测试CLIENT_BASEDIR条件环境变量),request脚本只有两种选择-继续或退出.
使用相对参数化路径如果您的软件产品可能安装在SunOS操作系统的早期版本上,则request脚本需要完成所有必要的工作.
还可以使用此方法处理多个目录.
如果需要使用额外的目录,仍然需要将这些包括在单个基目录下,以便提供易于管理的产品.
尽管BASEDIR参数没有提供最新Solaris发行版中的粒度级别,您的软件包仍然可以使用request脚本来处理参数化路径,从而遍历基目录.
pkginfo和pkgmap文件可能如下所示.
pkginfo文件#pkginfofilePKG=SUNWstufNAME=softwarestuffARCH=sparcVERSION=1.
0.
0,REV=1.
0.
5CATEGORY=applicationDESC=asetofutilitiesthatdostuffBASEDIR=/optSUBBASE=SUNWstufVENDOR=SunMicrosystems,Inc.
HOTLINE=PleasecontactyourlocalserviceproviderEMAIL=MAXINST=1000CLASSES=nonedaemonPSTAMP=hubert990707141632适应重定位应用程序包开发者指南2009年4月124pkgmap文件:117581dnone$SUBBASE/EZstuf0775rootbin1fnone$SUBBASE/EZstuf/dirdel0555binbin407737513102291fnone$SUBBASE/EZstuf/usrdel0555binbin407737513102291fnone$SUBBASE/EZstuf/filedel0555binbin407737513102291dnone$SUBBASE/HRDstuf0775rootbin1fnone$SUBBASE/HRDstuf/mksmart0555binbin407737513102291fnone$SUBBASE/HRDstuf/mktall0555binbin407737513102291fnone$SUBBASE/HRDstuf/mkcute0555binbin407737513102291fnone$SUBBASE/HRDstuf/mkeasy0555binbin407737513102291dnone/etc1dnone/etc/rc2.
d1fdaemon/etc/rc2.
d/S70dostuf0744rootsys4502234431ipkginfo348284117607401631ipostinstall323264757513099081ipostremove402331797513099451ipreinstall321262547513100191ipreremove320261147513098651ii.
daemon509395607529781031ir.
daemon32024573742152591此示例并不完善.
pkginfo-r命令为安装基本位置返回/opt,其含义相当模糊.
许多软件包位于/opt中,但起码它是一个有意义的目录.
就像上一个示例一样,接下来的这个示例完全支持多个体系结构和版本.
request脚本可根据特定软件包的需要进行调整,并可解析任何适用的相关性.
示例-遍历相对参数化路径的request脚本#requestscriptforSUNWstuftowalkaparametricpathPATH=/usr/sadm/bin:${PATH}#useadminutilitiesMSG="Thetargetdirectory$LOCAL_BASEalreadycontains\differentarchitectureorversionof$PKG.
Thispackage\couldbeinstalledattheunusedtargetdirectory$WRKNG_BASE.
"PROMPT="Doyouwanttousetotheproposeddirectory"HELP="Aresponseof\"y\"willinstalltotheproposeddirectory\andcontinue,\"n\"willrequestadifferentdirectory.
If\theoption\"-anone\"wasused,pressthekeyand\enteranunusedbasedirectorywhenitisrequested.
"DIRPROMPT="Selectarelativetargetdirectoryunder$BASEDIR/"适应重定位第6章创建软件包的高级技术125DIRHELP="Thepackage$PKGwillbeinstalledatthelocationentered.
"SUSPEND="Suspendinginstallationatuserrequestusingerror\code1.
"NUBD_MSG="Thelocationofthispackageisnotthedefault.
Be\suretoupdateanyapplicablesearchpathswiththeactual\locationofthebinarieswhichareat$WRKNG_BASE/EZstuf\and$WRKNG_BASE/HRDstuf.
"Changed=""Suffix="0"##Determineifthisproductisactuallyinstalledintheworking#basedirectory.
#Product_is_present(){if[-d$WRKNG_BASE/EZstuf-o-d$WRKNG_BASE/HRDstuf];thenreturn1elsereturn0fi}if[${BASEDIR}];then#ThismaybeanoldversionofSolaris.
InthelatestSolaris#CLIENT_BASEDIRwon'tbedefinedyet.
Inolderversionsitis.
if[${CLIENT_BASEDIR}];thenLOCAL_BASE=$BASEDIR/$SUBBASEelse#Thebasedirectoryhasn'tbeenprocessedyetLOCAL_BASE=${PKG_INSTALL_ROOT}$BASEDIR/$SUBBASEfiWRKNG_BASE=$LOCAL_BASE#Seeifthebasedirectoryisalreadyinplaceandwalkitif#possiblewhile[-d${WRKNG_BASE}-aProduct_is_present];do#Thereisaconflict#Isthisanupdateofthesamearch&versionif[${UPDATE}];thenexit0#It'soutofourhands.
else#Sothisisadifferentarchitectureor#versionthanwhatisalreadythere.
#Walkthebasedirectory适应重定位应用程序包开发者指南2009年4月126Suffix='expr$Suffix+1'WRKNG_BASE=$LOCAL_BASE.
$SuffixChanged="true"fidone#Sonowwecanproposeabasedirectorythatisn'tclaimedby#anyofourotherversions.
if[$Changed];thenputtext"$MSG"result='ckyorn-Q-d"a"-h"$HELP"-p"$PROMPT"'if[$-eq3];thenputtext"$SUSPEND"exit1fiif[$result="n"];thenWRKNG_BASE='ckpath-lyw-d"$WRKNG_BASE"-h"$DIRHELP"\-p"$DIRPROMPT"'elif[$result="a"];thenexit0elseexit1fiechoSUBBASE=$SUBBASE.
$Suffix>>$1puttext"$NUBD_MSG"fifiexit0在异构环境中支持重定位SystemV打包背后的原始概念假定每个系统有一个体系结构.
服务器的概念在设计中没有发挥作用.
当然,现在一台服务器可以支持多个体系结构,这意味着在一台服务器上可能存在同一个软件的多个副本,每个副本适用于不同的体系结构.
尽管Solaris软件包被隔离在建议的文件系统边界(例如,/和/usr)内,但由于在服务器以及每个客户机上都有产品数据库,因此并非所有安装都一定支持这种划分.
某些实现支持完全不同的结构,并且隐含一个公共产品数据库.
尽管将客户机指向不同的版本是一项非常简单的工作,但将SystemV软件包实际安装到不同的基目录可能给管理员带来困难.
当您设计软件包时,还应该考虑管理员用来引入新的软件版本的常用方法.
管理员通常寻求并行安装和测试最新版本与当前安装的版本.
该过程涉及到将新版本安装到与当前版本不同的基目录,以及将一些非关键性客户机定向到新版本以便进行测试.
随着信心不断增加,管理员将越来越多的客户机重定向到新版本.
最终,管理员仅仅为了应对紧急情况而保留旧版本,并最终将其删除.
在异构环境中支持重定位第6章创建软件包的高级技术127这意味着以现代异构系统为目标的软件包必须支持真正的重定位:即管理员可以将这些软件包放置到文件系统中的任意合理位置,而仍然可以使用其完整的功能.
Solaris2.
5和兼容发行版提供了许多有用的工具,允许将多个体系结构和版本完全安装到同一个系统中.
Solaris2.
4和兼容发行版也支持真正的重定位,但完成该任务的方法不是很明显.
传统方法可重定位软件包SystemVABI表明,可重定位软件包背后的原始意图是使安装软件包对于管理员而言更加便利.
现在,对可重定位软件包的需求更进了一大步.
便利与否不是唯一的问题,更有可能发生的问题是在安装期间,一个活动的软件产品已经安装在缺省目录中.
不能处理这种情况的软件包会覆写现有产品,或者安装失败.
然而,可处理多个体系结构和多个版本的软件包可以顺利安装,并且为管理员提供与现有管理传统完全兼容的大量选项.
在某些方面,多个体系结构的问题和多个版本的问题是同一问题.
必须可以并行安装现有软件包的变体与其他变体,并且能够在不影响功能的情况下将客户机或导出的文件系统的独立使用者定向到其中任一变体.
尽管Sun已经制定了在服务器上处理多个体系结构的方法,但管理员可以不遵守这些推荐方法.
所有软件包都必须能够符合管理员的合理安装期望.
示例-传统的可重定位软件包此示例演示一个传统的可重定位软件包内容.
该软件包将位于/opt/SUNWstuf中,其pkginfo文件和pkgmap文件可能如下所示.
pkginfo文件#pkginfofilePKG=SUNWstufNAME=softwarestuffARCH=sparcVERSION=1.
0.
0,REV=1.
0.
5CATEGORY=applicationDESC=asetofutilitiesthatdostuffBASEDIR=/optVENDOR=SunMicrosystems,Inc.
HOTLINE=PleasecontactyourlocalserviceproviderEMAIL=MAXINST=1000CLASSES=nonePSTAMP=hubert990707141632在异构环境中支持重定位应用程序包开发者指南2009年4月128pkgmap文件:117581dnoneSUNWstuf0775rootbin1dnoneSUNWstuf/EZstuf0775rootbin1fnoneSUNWstuf/EZstuf/dirdel0555binbin407737513102291fnoneSUNWstuf/EZstuf/usrdel0555binbin407737513102291fnoneSUNWstuf/EZstuf/filedel0555binbin407737513102291dnoneSUNWstuf/HRDstuf0775rootbin1fnoneSUNWstuf/HRDstuf/mksmart0555binbin407737513102291fnoneSUNWstuf/HRDstuf/mktall0555binbin407737513102291fnoneSUNWstuf/HRDstuf/mkcute0555binbin407737513102291fnoneSUNWstuf/HRDstuf/mkeasy0555binbin407737513102291ipkginfo348284117607401631ipostinstall323264757513099081ipostremove402331797513099451ipreinstall321262547513100191ipreremove32026114751309865因为每个软件包对象都会安装到pkginfo文件中的BASEDIR参数所定义的基目录,所以这称为传统方法.
例如,pkgmap文件中的第一个对象被安装到目录/opt/SUNWstuf.
绝对软件包绝对软件包是安装到特定根(/)文件系统的软件包.
这些软件包难以从多个版本和体系结构的角度进行处理.
通常,所有软件包都应该是可重定位的.
然而,有非常充足的理由在可重定位软件包中包括绝对元素.
示例-传统绝对软件包如果SUNWstuf软件包是绝对软件包,则不应该在pkginfo文件中定义BASEDIR参数,而pkgmap文件将如下所示.
pkgmap文件:117581dnone/opt1dnone/opt/SUNWstuf0775rootbin1dnone/opt/SUNWstuf/EZstuf0775rootbin1fnone/opt/SUNWstuf/EZstuf/dirdel0555binbin407737513102291fnone/opt/SUNWstuf/EZstuf/usrdel0555binbin407737513102291fnone/opt/SUNWstuf/EZstuf/filedel0555binbin407737513102291dnone/opt/SUNWstuf/HRDstuf0775rootbin1fnone/opt/SUNWstuf/HRDstuf/mksmart0555binbin407737513102291fnone/opt/SUNWstuf/HRDstuf/mktall0555binbin407737513102291fnone/opt/SUNWstuf/HRDstuf/mkcute0555binbin407737513102291fnone/opt/SUNWstuf/HRDstuf/mkeasy0555binbin407737513102291ipkginfo34828411760740163在异构环境中支持重定位第6章创建软件包的高级技术1291ipostinstall323264757513099081ipostremove402331797513099451ipreinstall321262547513100191ipreremove32026114751309865在此示例中,如果管理员在安装期间指定了一个备用基目录,pkgadd命令将忽略该目录.
此软件包总是安装到目标系统的/opt/SUNWstuf.
pkgadd命令的-R参数按预期方式工作.
例如,pkgadd-d.
-R/export/opt/client3SUNWstuf将对象安装在/export/opt/client3/opt/SUNWstuf中;但这是此软件包最接近可重定位软件包之处.
请注意,在pkgmap文件中,对/opt目录使用了问号().
这表明不应该更改现有属性.
这并不意味着"使用缺省属性创建目录",尽管在某些情况下可能发生这种情况.
特定于新软件包的任何目录都必须明确指定所有属性.
复合软件包任何包含可重定位对象的软件包称为可重定位软件包.
这可能令人产生误解,因为可重定位软件包可能在其pkgmap文件中包含绝对路径.
在pkgmap文件中使用根(/)条目可以增强软件包的可重定位特性.
同时具有可重定位条目和根条目的软件包称为复合软件包.
示例-传统解决方案假定SUNWstuf软件包中的一个对象是在运行级别2执行的启动脚本.
文件/etc/rc2.
d/S70dostuf需要作为该软件包的一部分安装,但不能将其放置到基目录中.
假定可重定位软件包是唯一的解决方案,pkginfo和pkgmap可能如下所示.
pkginfo文件#pkginfofilePKG=SUNWstufNAME=softwarestuffARCH=sparcVERSION=1.
0.
0,REV=1.
0.
5CATEGORY=applicationDESC=asetofutilitiesthatdostuffBASEDIR=/VENDOR=SunMicrosystems,Inc.
HOTLINE=PleasecontactyourlocalserviceproviderEMAIL=MAXINST=1000CLASSES=nonePSTAMP=hubert990707141632在异构环境中支持重定位应用程序包开发者指南2009年4月130pkgmap文件:117581dnoneopt/SUNWstuf/EZstuf0775rootbin1fnoneopt/SUNWstuf/EZstuf/dirdel0555binbin407737513102291fnoneopt/SUNWstuf/EZstuf/usrdel0555binbin407737513102291fnoneopt/SUNWstuf/EZstuf/filedel0555binbin407737513102291dnoneopt/SUNWstuf/HRDstuf0775rootbin1fnoneopt/SUNWstuf/HRDstuf/mksmart0555binbin407737513102291fnoneopt/SUNWstuf/HRDstuf/mktall0555binbin407737513102291fnoneopt/SUNWstuf/HRDstuf/mkcute0555binbin407737513102291fnoneopt/SUNWstuf/HRDstuf/mkeasy0555binbin407737513102291dnoneetc1dnoneetc/rc2.
d1fnoneetc/rc2.
d/S70dostuf0744rootsys4502234431ipkginfo348284117607401631ipostinstall323264757513099081ipostremove402331797513099451ipreinstall321262547513100191ipreremove32026114751309865此方法和绝对软件包方法之间没有太大差异.
实际上,作为绝对软件包使用会更好,因为如果管理员为此软件包提供备用基目录,它将无法正常工作!
实际上,此软件包中只有一个文件需要相对于根保持固定,其余文件都可以任意移动.
本节其余部分将讨论如何使用复合软件包解决此问题.
超越传统本节描述的方法不适用于所有软件包,但是,在将软件包安装到异构环境期间该方法确实能够改善性能.
该方法很少适用于作为SolarisOS的一部分提供的软件包(随附的软件包);然而,非随附软件包可以实行非传统打包.
鼓励采用可重定位软件包的原因是支持以下需求:在添加或删除软件包时,已安装的软件产品的现有理想行为将保持不变.

非随附软件包应该驻留在/opt下,以便保证新软件包不会干扰现有产品.
复合软件包另一特性在构建功能复合软件包时,需要遵循两个规则:根据软件包对象的绝大部分的安装位置来建立基目录.
如果某个软件包对象安装到基目录以外的其他公共目录(例如/etc),请在prototype文件中将其指定为绝对路径名.
在异构环境中支持重定位第6章创建软件包的高级技术131换句话说,因为"可重定位"意味着该对象可以安装到任何位置而仍然能够正常工作,所以不能将init在引导时运行的任何启动脚本视为可重定位的!
尽管在提供的软件包中将/etc/passwd指定为相对路径没有任何问题,但它只有一个安装位置.
使绝对路径名看起来像可重定位对象如果您要构建一个复合软件包,绝对路径必须以不干扰已安装的现有软件的方式工作.
可以完全包含在/opt中的软件包可避免此问题,因为不存在形成阻碍的现有文件.
当/etc中的一个文件包括在软件包中时,您必须确保绝对路径名的行为方式与相对路径名的预期行为方式相同.
请考虑下面两个示例.
示例-修改文件说明将一个条目添加到表中,或者对象是可能要由其他程序或软件包修改的一个新表.

实现将该对象定义为文件类型e并定义为属于build、awk或sed类.
执行此任务的脚本必须可与添加自身一样高效地删除自身.
示例需要将一个条目添加到/etc/vfstab中,以便支持新的固态硬盘.
pkgmap文件中的条目可能是1esed/etc/vfstabrequest脚本询问操作员/etc/vfstab是否应该由软件包修改.
如果操作员回答"否",那么request脚本将列出有关如何手动完成该工作的说明,并将执行:echo"CLASSES=none">>$1如果操作员回答"是",那么它将执行:echo"CLASSES=nonesed">>$1该命令将激活将要执行必要修改的类操作脚本.
sed类意味着软件包文件/etc/vfstab是一个sed程序,该程序包含目标系统上同名文件的安装和删除操作.
在异构环境中支持重定位应用程序包开发者指南2009年4月132示例-创建新文件说明对象是一个不太可能在以后进行编辑的全新文件,或者它将替换另一个软件包拥有的某个文件.
实现将软件包对象定义为文件类型f,并使用能够撤消更改的类操作脚本来安装该对象.
示例/etc中需要一个全新的文件来提供必要的信息,以便支持名为/etc/shdisk.
conf的固态硬盘.
pkgmap文件中的条目可能如下所示:.
.
.
1fnewetc/etc/shdisk.
conf.
.
.
类操作脚本i.
newetc负责安装此文件以及需要安装到/etc的所有其他文件.
该脚本将执行检查以确保该位置不存在其他文件.
如果不存在其他文件,它只是将新文件复制到该位置.
如果该位置已经有文件,该脚本将在安装新文件之前备份该文件.
脚本r.
newetc可根据需要删除这些文件并恢复原始文件.
以下是安装脚本的关键片段.

#i.
newetcwhilereadsrcdst;doif[-f$dst];thendstfile='basename$dst'cp$dst$PKGSAV/$dstfileficp$src$dstdoneif["${1}"="ENDOFCLASS"];thencd$PKGSAVtarcfSAVE.
newetc.
$INST_DATADIR/$PKG/install/squishSAVE.
newetcfi在异构环境中支持重定位第6章创建软件包的高级技术133请注意,此脚本使用PKGSAV环境变量存储将被替换的文件的备份.
当参数ENDOFCLASS传递给该脚本时,即pkgadd命令通知该脚本这些条目是此类中的最后一批条目,此时,该脚本将归档并压缩使用专用压缩程序(存储在软件包的安装目录中)保存的文件.
尽管在软件包更新期间使用PKGSAV环境变量不可靠,但如果软件包未更新(例如,未通过修补程序更新),则备份文件将是安全的.
下面的删除脚本包含的代码用于处理另一个问题:pkgrm命令的旧版本不向脚本传递PKGSAV环境变量的正确路径.
删除脚本可能如下所示.
#r.
newetc#makesurewehavethecorrectPKGSAVif[-d$PKG_INSTALL_ROOT$PKGSAV];thenPKGSAV="$PKG_INSTALL_ROOT$PKGSAV"fi#findtheunsquishprogramUNSQUISH_CMD='dirname$0'/unsquishwhilereadfile;dorm$filedoneif["${1}"=ENDOFCLASS];thenif[-f$PKGSAV/SAVE.
newetc.
sq];then$UNSQUISH_CMD$PKGSAV/SAVE.
newetcfiif[-f$PKGSAV/SAVE.
newetc];thentargetdir=dirname$file#gettherightdirectorycd$targetdirtarxf$PKGSAV/SAVE.
newetcrm$PKGSAV/SAVE.
newetcfifi此脚本使用软件包数据库的安装目录中的专用卸载算法(unsquish).
这由pkgadd命令在安装时自动完成.
所有未被pkgadd命令特别识别为仅限于安装的脚本都将保留在此目录中,供pkgrm命令使用.
您无法肯定该目录位于何处,但您可以确定该目录是无层次的,并且包含该软件包的所有适当信息文件和安装脚本.
此脚本根据以下事实查找该目录:即类操作脚本肯定从包含unsquish程序的目录中执行.
另外请注意,此脚本并不只是假定目标目录是/etc.
该目录实际上可能是/export/root/client2/etc.
可以用以下两种方式之一构建正确的目录.
使用${PKG_INSTALL_ROOT}/etc构造,或者.
在异构环境中支持重定位应用程序包开发者指南2009年4月134获取由pkgadd命令传递的文件目录名(就是此脚本的作用).
通过对软件包中的每个绝对对象使用此方法,您可以确信当前的理想行为保持不变或者至少是可恢复的.
示例-复合软件包以下是复合软件包的pkginfo和pkgmap文件的示例.
pkginfo文件PKG=SUNWstufNAME=softwarestuffARCH=sparcVERSION=1.
0.
0,REV=1.
0.
5CATEGORY=applicationDESC=asetofutilitiesthatdostuffBASEDIR=/optVENDOR=SunMicrosystems,Inc.
HOTLINE=PleasecontactyourlocalserviceproviderEMAIL=MAXINST=1000CLASSES=nonedaemonPSTAMP=hubert990707141632pkgmap文件:117581dnoneSUNWstuf/EZstuf0775rootbin1fnoneSUNWstuf/EZstuf/dirdel0555binbin407737513102291fnoneSUNWstuf/EZstuf/usrdel0555binbin407737513102291fnoneSUNWstuf/EZstuf/filedel0555binbin407737513102291dnoneSUNWstuf/HRDstuf0775rootbin1fnoneSUNWstuf/HRDstuf/mksmart0555binbin407737513102291fnoneSUNWstuf/HRDstuf/mktall0555binbin407737513102291fnoneSUNWstuf/HRDstuf/mkcute0555binbin407737513102291fnoneSUNWstuf/HRDstuf/mkeasy0555binbin407737513102291dnone/etc1dnone/etc/rc2.
d1edaemon/etc/rc2.
d/S70dostuf0744rootsys4502234431ii.
daemon509395607529781031ipkginfo348284117607401631ipostinstall323264757513099081ipostremove402331797513099451ipreinstall321262547513100191ipreremove320261147513098651ir.
daemon32024573742152591在异构环境中支持重定位第6章创建软件包的高级技术135尽管S70dostuf属于daemon类,但指向它的目录(这些目录在安装时已经就位)属于none类.
即使这些目录对于此软件包是唯一的,您也应该将它们保留在none类中.
这样做的原因是,这些目录需要首先被创建而且最后删除,而对于none类而言始终如此.
pkgadd命令创建这些目录;它们不是从软件包复制的,而且不会传递给将创建的类操作脚本.
相反,这些目录由pkgadd命令在调用安装类操作脚本之前创建,而pkgrm命令会在删除类操作脚本完成之后删除这些目录.
这意味着,如果一个特殊类中的目录包含none类中的对象,pkgrm命令在尝试删除该目录时会失败,因为该目录无法及时变成空目录.
如果类none的一个对象将插入到某个特殊类的目录中,该目录不会及时出现以便接受该对象.
pkgadd命令将在对象安装期间动态创建该目录,并且可能无法在最终看到pkgmap定义时同步该目录的属性.
注–在将目录指定给类时,请一定记住创建和删除顺序.
使软件包可远程安装所有软件包都必须可远程安装.
可远程安装意味着您不假定安装软件包的管理员正在向运行pkgadd命令的系统的根(/)文件系统进行安装.
如果在某个过程脚本中,需要到达目标系统的/etc/vfstab文件,则需要使用PKG_INSTALL_ROOT环境变量.
换句话说,路径名/etc/vfstab会将您引导至运行pkgadd命令的系统的/etc/vfstab文件,但管理员可能正在向位于/export/root/client3的客户机进行安装.
路径${PKG_INSTALL_ROOT}/etc/vfstab肯定能够将您引导至目标文件系统.
示例-安装到客户机系统在此示例中,SUNWstuf软件包被安装到client3,该客户机在其根(/)文件系统中配置有/opt.
此软件包的另一个版本已经安装在client3上,并且基目录从管理文件thisadmin中设置为basedir=/opt/$PKGINST.
(有关管理文件的更多信息,请参见第115页中的"缺省管理文件".
)服务器上执行的pkgadd命令是:#pkgadd-athisadmin-R/export/root/client3SUNWstuf下表列出传递给过程脚本的环境变量及其值.
表6–1传递给过程脚本的值环境变量值PKGINSTSUNWstuf.
2PKG_INSTALL_ROOT/export/root/client3使软件包可远程安装应用程序包开发者指南2009年4月136表6–1传递给过程脚本的值(续)环境变量值CLIENT_BASEDIR/opt/SUNWstuf.
2BASEDIR/export/root/client3/opt/SUNWstuf.
2示例-安装到服务器或独立系统要在与上一个示例相同的环境下安装到服务器或独立系统,所使用的命令是:#pkgadd-athisadminSUNWstuf下表列出传递给过程脚本的环境变量及其值.
表6–2传递给过程脚本的值环境变量值PKGINSTSUNWstuf.
2PKG_INSTALL_ROOT未定义.
CLIENT_BASEDIR/opt/SUNWstuf.
2BASEDIR/opt/SUNWstuf.
2示例-挂载共享文件系统假定SUNWstuf软件包在服务器上的/export/SUNWstuf/share创建并共享了一个文件系统.
在将软件包安装到客户机系统时,需要更新客户机系统的/etc/vfstab文件以挂载这一共享文件系统.
在这种情况下可以使用CLIENT_BASEDIR变量.
客户机上的条目需要根据客户机的文件系统呈现挂载点.
无论安装是从服务器进行还是从客户机进行,都应该正确构建该行.
假定服务器的系统名是$SERVER.
您可以转至$PKG_INSTALL_ROOT/etc/vfstab,并使用sed或awk命令为客户机的/etc/vfstab文件构建以下行.
$SERVER:/export/SUNWstuf/share-$CLIENT_BASEDIR/usrnfs-yesro例如,对于服务器universe和客户机系统client9,客户机系统的/etc/vfstab文件中的该行可能如下所示:universe:/export/SUNWstuf/share-/opt/SUNWstuf.
2/usrnfs-yesro正确使用这些参数时,该条目始终挂载客户机的文件系统,而无论它是在本地构建还是从服务器构建.
使软件包可远程安装第6章创建软件包的高级技术137修补软件包软件包的修补程序只是一个专门用于覆写原始软件包中某些文件的稀疏软件包.
除了在交付介质上节省空间以外,发布稀疏软件包没有其他真正原因.
您还可以发布更改了几个文件的完整原始软件包,或者提供通过网络访问经过修改的软件包的权限.
只要只有这些新文件实际上是不同的(其他文件未重新编译),pkgadd命令就会安装这些区别.
请查看以下有关修补软件包的准则.
如果系统足够复杂,那么明智的做法是建立一种修补程序标识系统,以便确保任意两个修补程序在试图更正不同的异常行为时不会替换同一个文件.
例如,Sun修补程序基本号被指定它们所负责的文件互斥集.
能够回退修补程序是必要的.
至关重要的一点是,修补程序软件包的版本号必须与原始软件包的版本号相同.
您应该使用如下形式的单独pkginfo文件条目来跟踪软件包的修补程序状态:PATCH=patch_number如果软件包版本在进行修补后发生改变,则相当于您创建了该软件包的另一个实例,这样,管理修补后的产品将变得极为困难.
这种渐进式实例修补方法可以将早期SolarisOS发行版的某些优势传递下去,但却使更复杂系统的管理变得繁琐.
修补程序中的所有区域参数都必须与软件包中的区域参数相匹配.
对于组成SolarisOS的软件包而言,虽然可能有多个修补后的实例,但在软件包数据库中应该只有该软件包的一个副本.
为了使用removef命令从已安装的软件包中删除某个对象,您需要判断哪些实例拥有该文件.
然而,如果您的软件包(该软件包不属于SolarisOS)需要确定属于SolarisOS的特定软件包的修补级别,那么这就成为一个需要在此处解决的问题.
安装脚本可能非常大但不会产生重大影向,因为它们不存储在目标文件系统中.
通过类操作脚本和其他各种过程脚本,您可以使用PKGSAV环境变量保存经过更改的文件(或者保存到其他某个更加持久的目录),以便能够回退已安装的修补程序.
您还可以通过request脚本设置适当的环境变量,以监视修补程序历史记录.
以下各节中的脚本假定可能存在多个修补程序,其编号方案在应用于单个软件包时具有某种含义.
在这种情况下,各个修补程序编号表示软件包内的功能相关文件的一个子集.
两个编号不同的修补程序不能更改同一个文件.
为了将一个常规的稀疏软件包转换成修补程序软件包,可将以下各节描述的脚本简单地封装到该软件包中.
这些脚本都是公认的标准软件包组件,只有最后两个名为patch_checkinstall和patch_postinstall的脚本除外.
如果您要包括回退修补程序功能,可以将这两个脚本合并到回退软件包中.
这些脚本十分简单,它们的各种任务也容易完成.
修补软件包应用程序包开发者指南2009年4月138注–此修补方法可用于修补客户机系统,但服务器上的客户机根目录必须拥有正确的权限,以允许用户install或nobody读取.
checkinstall脚本checkinstall脚本验证修补程序是否适合于此特定软件包.
一旦确认这一点,该脚本将构建修补程序列表和修补程序信息列表,然后将它们插入到响应文件中,以便合并到软件包数据库中.
修补程序列表是已经影响当前软件包的修补程序的列表.
这一修补程序列表记录在已安装的软件包的pkginfo文件中,记录该列表的行可能如下所示:PATCHLIST=patch_idpatch_id.
.
.
修补程序信息列表是当前修补程序所依赖的修补程序的列表.
这一修补程序列表也记录在pkginfo文件中,记录该列表的行可能如下所示.
PATCH_INFO_103203-01=Installed.
.
.
Obsoletes:103201-01Requires:\Incompatibles:120134-01注–这些行(及其格式)被声明为公共接口.
任何为Solaris软件包发行修补程序的公司都应该相应地更新此列表.
当修补程序交付时,修补程序内的每个软件包都包含一个执行此任务的checkinstall脚本.
该同一个checkinstall脚本还会更新其他一些特定于修补程序的参数.
这是新的修补程序体系结构,称为"直接实例修补".

在此示例中,原始软件包及其修补程序都存在于同一个目录中.
两个原始软件包命名为SUNWstuf.
v1和SUNWstuf.
v2,而它们的修补程序分别命名为SUNWstuf.
p1和SUNWstuf.
p2.
这意味着,过程脚本可能很难判断这些文件来自哪个目录,因为对于PKG参数除去了软件包名称中的点(".
")之后的所有内容,并且PKGINST环境变量是指已安装的实例,而不是源实例.
因此,过程脚本可以找到源目录,checkinstall脚本(始终从源目录执行)执行查询并且将位置作为变量SCRIPTS_DIR传递.
如果源目录中只有一个名为SUNWstuf的软件包,则过程脚本可能已经使用$INSTDIR/$PKG找到它.
#checkinstallscripttocontrolapatchinstallation.
#directoryformatoptions.
##@(#)checkinstall1.
696/09/27SMI##Copyright(c)1995bySunMicrosystems,Inc.
#Allrightsreserved#修补软件包第6章创建软件包的高级技术139PATH=/usr/sadm/bin:$PATHINFO_DIR='dirname$0'INFO_DIR='dirname$INFO_DIR'#onelevelupNOVERS_MSG="PaTcH_MsG8Version$VERSIONof$PKGisnotinstalledonthissystem.
"ALRDY_MSG="PaTcH_MsG2Patchnumber$Patch_labelisalreadyapplied.
"TEMP_MSG="PaTcH_MsG23Patchnumber$Patch_labelcannotbeapplieduntilall\restrictedpatchesarebackedout.
"#Readtheprovidedenvironmentfromwhatmayhavebeenarequestscript.
$1#Oldsystemscan'tdealwithcheckinstallscriptsanywayif["$PATCH_PROGRESSIVE"="true"];thenexit0fi##Confirmthattheintendedversionisinstalledonthesystem.
#if["${UPDATE}"!
="yes"];thenecho"$NOVERS_MSG"exit3fi##Confirmthatthispatchhasn'talreadybeenappliedand#thatnoothermix-upshaveoccurredinvolvingpatchversionsand#thelike.
#Skip=0active_base='echo$Patch_label|nawk'{printsubstr($0,1,match($0,"Patchvers_pfx")-1)}''active_inst='echo$Patch_label|nawk'{printsubstr($0,match($0,"Patchvers_pfx")+Patchvers_pfx_lnth)}''#Isthisarestrictedpatchifecho$active_base|egrep-s"Patchstrict_str";thenis_restricted="true"#Allrestrictedpatchesarebackoutableecho"PATCH_NO_UNDO=">>$1elseis_restricted="false"fiforpatchapplin${PATCHLIST};do#Isthisanordinarypatchapplyingoverarestrictedpatch修补软件包应用程序包开发者指南2009年4月140if[$is_restricted="false"];thenifecho$patchappl|egrep-s"Patchstrict_str";thenecho"$TEMP_MSG"exit3;fifi#Isthereanewerversionofthispatchappl_base='echo$patchappl|nawk'{printsubstr($0,1,match($0,"Patchvers_pfx")-1)}''if[$appl_base=$active_base];thenappl_inst='echo$patchappl|nawk'{printsubstr($0,match($0,"Patchvers_pfx")\+Patchvers_pfx_lnth)}''result='expr$appl_inst\>$active_inst'if[$result-eq1];thenecho"PaTcH_MsG1Patchnumber$Patch_labelis\supercededbythealreadyapplied$patchappl.
"exit3elif[$appl_inst=$active_inst];then#Notnewer,it'sthesameif["$PATCH_UNCONDITIONAL"="true"];thenif[-d$PKGSAV/$Patch_label];thenecho"PATCH_NO_UNDO=true">>$1fielseecho"$ALRDY_MSG"exit3;fififidone#Constructalistofappliedpatchesinorderecho"PATCHLIST=${PATCHLIST}$Patch_label">>$1##Constructthecompletelistofpatchesthisoneobsoletes#ACTIVE_OBSOLETES=$Obsoletes_labelif[-n"$Obsoletes_label"];then#Mergethetwolistsecho$Obsoletes_label|sed'y/\/\n/'|\nawk-vPatchObsList="$PATCH_OBSOLETES"'BEGIN{printf("PATCH_OBSOLETES=");PatchCount=split(PatchObsList,PatchObsComp,"");修补软件包第6章创建软件包的高级技术141for(PatchIndexinPatchObsComp){Atisat=match(PatchObsComp[PatchIndex],"@");PatchObs[PatchIndex]=substr(PatchObsComp[PatchIndex],\0,Atisat-1);PatchObsCnt[PatchIndex]=substr(PatchObsComp\[PatchIndex],Atisat+1);}}{Inserted=0;for(PatchIndexinPatchObs){if(PatchObs[PatchIndex]==$0){if(Inserted==0){PatchObsCnt[PatchIndex]=PatchObsCnt\[PatchIndex]+1;Inserted=1;}else{PatchObsCnt[PatchIndex]=0;}}}if(Inserted==0){printf("%s@1",$0);}next;}END{for(PatchIndexinPatchObs){if(PatchObsCnt[PatchIndex]!
=0){printf("%s@%d",PatchObs[PatchIndex],\PatchObsCnt[PatchIndex]);}}printf("\n");}'>>$1#Cleartheparametersinceithasalreadybeenused.
echo"Obsoletes_label=">>$1#Passit'svalueontothepreinstallunderanothernameecho"ACTIVE_OBSOLETES=$ACTIVE_OBSOLETES">>$1fi##ConstructPATCH_INFOlineforthispackage.
#tmpRequire='nawk-F='$1~/REQUIR/{print$2}'$INFO_DIR/pkginfo'修补软件包应用程序包开发者指南2009年4月142tmpIncompat='nawk-F='$1~/INCOMPAT/{print$2}'$INFO_DIR/pkginfo'if[-n"$tmpRequire"n"$tmpIncompat"]thenecho"PATCH_INFO_$Patch_label=Installed:'date'From:'uname-n'\Obsoletes:$ACTIVE_OBSOLETESRequires:$tmpRequire\Incompatibles:$tmpIncompat">>$1elif[-n"$tmpRequire"]thenecho"PATCH_INFO_$Patch_label=Installed:'date'From:'uname-n'\Obsoletes:$ACTIVE_OBSOLETESRequires:$tmpRequire\Incompatibles:">>$1elif[-n"$tmpIncompat"]thenecho"PATCH_INFO_$Patch_label=Installed:'date'From:'uname-n'\Obsoletes:$ACTIVE_OBSOLETESRequires:Incompatibles:\$tmpIncompat">>$1elseecho"PATCH_INFO_$Patch_label=Installed:'date'From:'uname-n'\Obsoletes:$ACTIVE_OBSOLETESRequires:Incompatibles:">>$1fi##Sincethisscriptiscalledfromthedeliverymediumandwemaybeusing#dotextensionstodistinguishthedifferentpatchpackages,thisisthe#onlyplacewecan,withcertainty,tracethatsourceforourbackout#scripts.
(Usually$INST_DATADIRwouldgetusthere).
#echo"SCRIPTS_DIR='dirname$0'">>$1#Ifadditionaloperationsarerequiredforthispackage,place#thosepackage-specificcommandshere.
#XXXSpecial_CommandsXXX#exit0preinstall脚本preinstall脚本可初始化prototype文件、信息文件和安装脚本,以便构建回退软件包.
此脚本非常简单,并且此示例中的其余脚本只允许回退软件包描述常规文件.

如果您要在回退软件包中恢复符号链接、硬链接、设备和命名管道,可以修改preinstall脚本,以便使用pkgproto命令将交付的pkgmap文件与安装的文件进行比较,然后为要在回退软件包中更改的每个非文件创建一个prototype文件条目.
应该使用的方法类似于类操作脚本中的方法.
修补软件包第6章创建软件包的高级技术143脚本patch_checkinstall和patch_postinstall会从preinstall脚本插入到软件包源树中.
这两个脚本撤消了修补程序执行的操作.
#Thisscriptinitializesthebackoutdataforapatchpackage#directoryformatoptions.
##@(#)preinstall1.
596/05/10SMI##Copyright(c)1995bySunMicrosystems,Inc.
#Allrightsreserved#PATH=/usr/sadm/bin:$PATHrecovery="no"if["$PKG_INSTALL_ROOT"thenPKG_INSTALL_ROOT=""fi#Checktoseeifthisisapatchinstallationretry.
if["$INTERRUPTION"="yes"];thenif[-d"$PKG_INSTALL_ROOT/var/tmp/$Patch_label.
$PKGINST"d\"$PATCH_BUILD_DIR/$Patch_label.
$PKGINST"];thenrecovery="yes"fifiif[-n"$PATCH_BUILD_DIR"-a-d"$PATCH_BUILD_DIR"];thenBUILD_DIR="$PATCH_BUILD_DIR/$Patch_label.
$PKGINST"elseBUILD_DIR="$PKG_INSTALL_ROOT/var/tmp/$Patch_label.
$PKGINST"fiFILE_DIR=$BUILD_DIR/filesRELOC_DIR=$BUILD_DIR/files/relocROOT_DIR=$BUILD_DIR/files/rootPROTO_FILE=$BUILD_DIR/prototypePKGINFO_FILE=$BUILD_DIR/pkginfoTHIS_DIR='dirname$0'if["$PATCH_PROGRESSIVE"="true"];then#Ifthisisbeingusedinanold-stylepatch,insert#theold-stylescriptcommandshere.
#XXXOld_CommandsXXX#exit0fi修补软件包应用程序包开发者指南2009年4月144##Unlessspecificallydenied,initializethebackoutpatchdataby#creatingthebuilddirectoryandcopyingovertheoriginalpkginfo#whichpkgaddsavedincaseithadtoberestored.
#if["$PATCH_NO_UNDO"!
="true"recovery"="no"];thenif[-d$BUILD_DIR];thenrm-r$BUILD_DIRfi#Ifthisisaretryofthesamepatchthenrecoveryissetto#yes.
Whichmeansthereisabuilddirectoryalreadyin#placewiththecorrectbackoutdata.
if["$recovery"="no"];thenmkdir$BUILD_DIRmkdir-p$RELOC_DIRmkdir$ROOT_DIRfi##Hereweinitializethebackoutpkginfofilebyfirst#copyingovertheoldpkginfofileandthemnaddingthe#ACTIVE_PATCHparametersothebackoutwillknowwhatpatch#it'sbackingout.
##NOTE:Withintheinstallation,pkgparamreturnsthe#originaldata.
#pkgparam-v$PKGINST|nawk'$1~/PATCHLIST/{next;}$1~/PATCH_OBSOLETES/{next;}$1~/ACTIVE_OBSOLETES/{next;}$1~/Obsoletes_label/{next;}$1~/ACTIVE_PATCH/{next;}$1~/Patch_label/{next;}$1~/UPDATE/{next;}$1~/SCRIPTS_DIR/{next;}$1~/PATCH_NO_UNDO/{next;}$1~/INSTDATE/{next;}$1~/PKGINST/{next;}$1~/OAMBASE/{next;}$1~/PATH/{next;}{print;PKGINFO_FILEecho"ACTIVE_PATCH=$Patch_label">>$PKGINFO_FILEecho"ACTIVE_OBSOLETES=$ACTIVE_OBSOLETES">>$PKGINFO_FILE修补软件包第6章创建软件包的高级技术145#Andnowinitializethebackoutprototypefilewiththe#pkginfofilejustformulated.
echo"ipkginfo">$PROTO_FILE#Copyoverthebackoutscriptsincludingtheundoclass#actionscriptsforscriptin$SCRIPTS_DIR/*;dosrcscript='basename$script'targscript='echo$srcscript|nawk'{script=$0;}/u\.
/{sub("u.
","i.
",script);printscript;next;}/patch_/{sub("patch_","",script);printscript;next;}{print"dont_use"}''if["$targscript"="dont_use"];thencontinuefiecho"i$targscript=$FILE_DIR/$targscript">>$PROTO_FILEcp$SCRIPTS_DIR/$srcscript$FILE_DIR/$targscriptdone##Nowaddentriestotheprototypefilethatwon'tbepassedto#classactionscripts.
Iftheentryisbrandnew,addittothe#deletesfileforthebackoutpackage.
#Our_Pkgmap='dirname$SCRIPTS_DIR'/pkgmapBO_Deletes=$FILE_DIR/deletesnawk-vbasedir=${BASEDIR:-/}'BEGIN{count=0;}{token=$2;ftype=$1;}$1next;}$1~/[0123456789]/{if(NF>=3){token=$3;ftype=$2;}else{修补软件包应用程序包开发者指南2009年4月146next;}}{if(ftype=="i"||ftype=="e"||ftype=="f"||ftype==\"v"||ftype=="d"){next;}}{equals=match($4,"=")-1;if(equals==-1){print$3,$4;}else{print$3,substr($4,0,equals);}}'>\$PROTO_FILE2>/dev/nullcd$THIS_DIRelif[-h"$Chk_Path"-o\-c"$Chk_Path"-o\-b"$Chk_Path"-o\-p"$Chk_Path"];thenpkgproto-c$class"$Chk_Path=$path"1>>\修补软件包第6章创建软件包的高级技术147$PROTO_FILE2>/dev/nullelseecho$path>>$BO_Deletesfidonefi#Ifadditionaloperationsarerequiredforthispackage,place#thosepackage-specificcommandshere.
#XXXSpecial_CommandsXXX#exit0类操作脚本类操作脚本创建每个替换现有文件的文件的副本,并为回退软件包向prototype文件中添加一个相应的行.
这一切都由十分简单的nawk脚本完成.
类操作脚本接收一个源/目标对列表,其中包括不与相应的已安装文件匹配的普通文件.
必须在preinstall脚本中处理符号链接和其他非文件.
#Thisclassactionscriptcopiesthefilesbeingreplaced#intoapackagebeingconstructedin$BUILD_DIR.
Thisclass#actionscriptisonlyappropriateforregularfilesthat#areinstalledbysimplycopyingthemintoplace.
##Forspecialpackageobjectssuchaseditablefiles,thepatch#producermustsupplyappropriateclassactionscripts.
##directoryformatoptions.
##@(#)i.
script1.
696/05/10SMI##Copyright(c)1995bySunMicrosystems,Inc.
#Allrightsreserved#PATH=/usr/sadm/bin:$PATHECHO="/usr/bin/echo"SED="/usr/bin/sed"PKGPROTO="/usr/bin/pkgproto"EXPR="/usr/bin/expr"#usedbydirnameMKDIR="/usr/bin/mkdir"CP="/usr/bin/cp"RM="/usr/bin/rm"修补软件包应用程序包开发者指南2009年4月148MV="/usr/bin/mv"recovery="no"Pn=$$procIdCtr=0CMDS_USED="$ECHO$SED$PKGPROTO$EXPR$MKDIR$CP$RM$MV"LIBS_USED=""if["$PKG_INSTALL_ROOT"thenPKG_INSTALL_ROOT=""fi#Checktoseeifthisisapatchinstallationretry.
if["$INTERRUPTION"="yes"];thenif[-d"$PKG_INSTALL_ROOT/var/tmp/$Patch_label.
$PKGINST"]||\[-d"$PATCH_BUILD_DIR/$Patch_label.
$PKGINST"];thenrecovery="yes"fifiif[-n"$PATCH_BUILD_DIR"-a-d"$PATCH_BUILD_DIR"];thenBUILD_DIR="$PATCH_BUILD_DIR/$Patch_label.
$PKGINST"elseBUILD_DIR="$PKG_INSTALL_ROOT/var/tmp/$Patch_label.
$PKGINST"fiFILE_DIR=$BUILD_DIR/filesRELOC_DIR=$FILE_DIR/relocROOT_DIR=$FILE_DIR/rootBO_Deletes=$FILE_DIR/deletesPROGNAME='basename$0'if["$PATCH_PROGRESSIVE"="true"];thenPATCH_NO_UNDO="true"fi#Sincethisisgeneric,figureouttheclass.
Class='echo$PROGNAME|nawk'{printsubstr($0,3)}''#Sincethisisanupdate,$BASEDIRisguaranteedtobecorrectBD=${BASEDIR:-/}cd$BD##First,figureoutthedynamiclibrariesthatcantripusup.
修补软件包第6章创建软件包的高级技术149#if[-z"$PKG_INSTALL_ROOT"];thenif[-x/usr/bin/ldd];thenLIB_LIST='/usr/bin/ldd$CMDS_USED|sort-u|nawk'$1continue;}{printf"%s",$3}''elseLIB_LIST="/usr/lib/libc.
so.
1/usr/lib/libdl.
so.
1\/usr/lib/libw.
so.
1/usr/lib/libintl.
so.
1/usr/lib/libadm.
so.
1\/usr/lib/libelf.
so.
1"fifi##Nowreadthelistoffilesinthisclasstobereplaced.
Ifthefile#isalreadyinplace,thenthisisachangeandweneedtocopyit#overtothebuilddirectoryifundoisallowed.
Ifit'sanewentry#(No$dst),thenitgoesinthedeletesfileforthebackoutpackage.
#procIdCtr=0whilereadsrcdst;doif[-z"$PKG_INSTALL_ROOT"];thenChk_Path=$dstforlibraryin$LIB_LIST;doif[$Chk_Path=$library];then$CP$dst$dst.
$PnLIBS_USED="$LIBS_USED$dst.
$Pn"LD_PRELOAD="$LIBS_USED"exportLD_PRELOADfidonefiif["$PATCH_PROGRESSIVE"="true"];then#Ifthisisbeingusedinanold-stylepatch,insert#theold-stylescriptcommandshere.
#XXXOld_CommandsXXX#echo>/dev/null#dummyfiif["${PATCH_NO_UNDO}"!
="true"];then##Hereweconstructthepathtotheappropriatesource#treeforthebuild.
FirstwetrytostripBASEDIR.
If#there'snoBASEDIRinthepath,wepresumethatitis#absoluteandconstructthetargetasanabsolutepath修补软件包应用程序包开发者指南2009年4月150#bystrippingPKG_INSTALL_ROOT.
FS_Pathisthepathto#thefileonthefilesystem(fordeletionpurposes).
#Build_Pathisthepathtotheobjectinthebuild#environment.
#if["$BD"thenFS_Path='$ECHO$dst|$SEDs@"$BD"@@'elseFS_Path='$ECHO$dst|$SEDs@"$BD/"@@'fi#Ifit'sanabsolutepaththeattempttostripthe#BASEDIRwillhavefailed.
if[$dst=$FS_Path];thenif[-z"$PKG_INSTALL_ROOT"];thenFS_Path=$dstBuild_Path="$ROOT_DIR$dst"elseBuild_Path="$ROOT_DIR'echo$dst|\seds@"$PKG_INSTALL_ROOT"@@'"FS_Path='echo$dst|\seds@"$PKG_INSTALL_ROOT"@@'fielseBuild_Path="$RELOC_DIR/$FS_Path"fiif[-f$dst];then#Ifthisisreplacingsomethingcd$FILE_DIR##Constructtheprototypefileentry.
Wereplace#thepointertothefilesystemobjectwiththe#builddirectoryobject.
#$PKGPROTO-c$Class$dst=$FS_Path|\$SED-es@=$dst@=$Build_Path@>>\$BUILD_DIR/prototype#Nowcopyoverthefileif["$recovery"="no"];thenDirName='dirname$Build_Path'$MKDIR-p$DirName$CP-p$dst$Build_Pathelse#Ifthisfileisalreadyinthebuildareaskipitif[-f"$Build_Path"];thencd$BDcontinue修补软件包第6章创建软件包的高级技术151elseDirName='dirname$Build_Path'if[!
-d"$DirName"];then$MKDIR-p$DirNamefi$CP-p$dst$Build_Pathfificd$BDelse#It'sbrandnew$ECHO$FS_Path>>$BO_Deletesfifi#Ifspecialprocessingisrequiredforeachsrc/dstpair,#addthathere.
##XXXSpecial_CommandsXXX##$CP$src$dst.
$$$procIdCtrif[$-ne0];then$RM$dst.
$$$procIdCtr1>/dev/null2>&1else$MV-f$dst.
$$$procIdCtr$dstforlibraryin$LIB_LIST;doif["$library"="$dst"];thenLD_PRELOAD="$dst"exportLD_PRELOADfidonefiprocIdCtr='expr$procIdCtr+1'done#Ifadditionaloperationsarerequiredforthispackage,place#thosepackage-specificcommandshere.
#XXXSpecial_CommandsXXX###Releasethedynamiclibraries#forlibraryin$LIBS_USED;do$RM-f$librarydoneexit0修补软件包应用程序包开发者指南2009年4月152postinstall脚本postinstall脚本使用其他脚本提供的信息创建回退软件包.
因为pkgmk和pkgtrans命令不需要软件包数据库,所以可以在软件包安装时执行这些命令.
在此示例中,通过在保存目录中(使用PKGSAV环境变量)构建一个流格式软件包来允许撤消修补程序.
这并不显而易见,但此软件包必须采用流格式,因为在pkgadd操作期间,保存目录会发生移动.
如果pkgadd命令应用于自己的保存目录中的一个软件包,那么有关软件包源在任何指定时刻所在位置的假设将变得非常不可靠.
流格式软件包被解压缩到一个临时目录中并在此处安装.
(目录格式软件包将从保存目录开始安装,并且发现自己在pkgadd失败安全操作期间突然被重定位.
)要确定应用于软件包的修补程序,请使用以下命令:$pkgparamSUNWstufPATCHLIST除PATCHLIST(一个Sun公共接口)之外,此示例中的参数名称中没有什么重要内容.
您可以取代PATCH使用传统SUNW_PATCHID,而其他各种列表(例如PATCH_EXCL和PATCH_REQD)可以相应地重命名.
如果某些修补程序软件包依赖于可从同一个介质中获得的其他修补程序软件包,那么checkinstall脚本可以确定这一点,并且按照与升级示例(请参见第161页中的"升级软件包")相同的方式创建一个将由postinstall脚本执行的脚本.
#Thisscriptcreatesthebackoutpackageforapatchpackage##directoryformatoptions.
##@(#)postinstall1.
696/01/29SMI##Copyright(c)1995bySunMicrosystems,Inc.
#Allrightsreserved##Description:#SettheTYPEparameterfortheremotefile##Parameters:#none##Globalsset:#TYPEset_TYPE_parameter(){if[${PATCH_UNDO_ARCHIVE:dev"];then#handledevicespecificstuffTYPE="removable"修补软件包第6章创建软件包的高级技术153elseTYPE="filesystem"fi}##Description:#Buildtheremotefilethatpointstothebackoutdata##Parameters:#$1:theun/compressedundoarchive##Globalsset:#UNDO,STATEbuild_remote_file(){remote_path=$PKGSAV/$Patch_label/remoteset_TYPE_parameterSTATE="active"if[$1="undo"];thenUNDO="undo"elseUNDO="undo.
Z"ficat>$remote_path>$BUILD_DIR/prototypefi##Nowdeleteeverythinginthedeleteslistaftertransferring#thefiletothebackoutpackageandtheentrytotheprototype#file.
RememberthatthepkgmapwillgettheCLIENT_BASEDIRpath#butwehavetoactuallygetatitusingtheBASEDIRpath.
Also#rememberthatremovefwillimportourPKG_INSTALL_ROOT#Our_Deletes=$THIS_DIR/deletesif[-f$Our_Deletes];thencd$BASEDIRcat$Our_Deletes|whilereadpath;doReg_File=0ifvalpath-l$path;thenClient_Path="$CLIENT_BASEDIR/$path"Build_Path="$RELOC_DIR/$path"修补软件包第6章创建软件包的高级技术155Proto_Path=$BASEDIR/$pathelse#It'sanabsolutepathClient_Path=$pathBuild_Path="$ROOT_DIR$path"Proto_Path=$PKG_INSTALL_ROOT$pathfi#Note:Ifthefileisn'treallythere,pkgproto#doesn'twriteanything.
LINE='pkgproto$Proto_Path=$path'ftype='echo$LINE|nawk'{print$1}''if[$ftype="f"];thenReg_File=1fiif[$Reg_File=1];then#Addsourcefiletotheprototypeentryif["$Proto_Path"="$path"];thenLINE='echo$LINE|sed-es@$Proto_Path@$Build_Path@2'elseLINE='echo$LINE|sed-es@$Proto_Path@$Build_Path@'fiDirName='dirname$Build_Path'#makeroominthebuildtreemkdir-p$DirNamecp-p$Proto_Path$Build_Pathfi#Insertitintotheprototypefileecho$LINE1>>$PROTO_FILE2>/dev/null#Removethefileonlyifit'sOK'dbyremovefrm'removef$PKGINST$Client_Path'1>/dev/null2>&1doneremovef-f$PKGINSTrm$Our_Deletesfi##Unlessspecificallydenied,makethebackoutpackage.
#if["$PATCH_NO_UNDO"!
="true"];thencd$BUILD_DIR#Wehavetobuildfromhere.
if["$PATCH_UNDO_ARCHIVE"!
="none"];thenSTAGE_DIR="$PATCH_UNDO_ARCHIVE"修补软件包应用程序包开发者指南2009年4月156ARCHIVE_DIR="$PATCH_UNDO_ARCHIVE/$Patch_label/$PKGINST"mkdir-p$ARCHIVE_DIRmkdir-p$PKGSAV/$Patch_labelelseif[-d$PKGSAV/$Patch_label];thenrm-r$PKGSAV/$Patch_labelfiSTAGE_DIR=$PKGSAVARCHIVE_DIR=$PKGSAV/$Patch_labelmkdir$ARCHIVE_DIRfipkgmk-o-d$STAGE_DIR1>/dev/null2>&1pkgtrans-s$STAGE_DIR$ARCHIVE_DIR/undo$PKG1>/dev/null2>&1compress$ARCHIVE_DIR/undoretcode=$if["$PATCH_UNDO_ARCHIVE"!
="none"];thenif[$retcode!
=0];thenbuild_remote_file"undo"elsebuild_remote_file"undo.
Z"fifirm-r$STAGE_DIR/$PKGcd.
.
rm-r$BUILD_DIR#removethescriptsthatareleftbehindinstall_scripts='dirname$0'rm$install_scripts/checkinstall$install_scripts/patch_\checkinstall$install_scripts/patch_postinstallfi##Sincethisapparentlyworked,we'llmarkasobsoletedtheprior#versionsofthispatch-installpatchdealswithexplicitobsoletions.
#cd${PKG_INSTALL_ROOT:-/}cdvar/sadm/pkgactive_base='echo$Patch_label|nawk'{printsubstr($0,1,match($0,"Patchvers_pfx")-1)}''List='ls-d$PKGINST/save/${active_base}*'if[$-ne0];thenList=""fi修补软件包第6章创建软件包的高级技术157forsavedirin$List;dopatch='basename$savedir'if[$patch=$Patch_label];thenbreakfi#Ifwegetherethenthepreviouspatchgetsdeletedif[-f$savedir/undo];thenmv$savedir/undo$savedir/obsoleteecho$Patch_label>>$savedir/obsoleted_byelif[-f$savedir/undo.
Z];thenmv$savedir/undo.
Z$savedir/obsolete.
Zecho$Patch_label>>$savedir/obsoleted_byelif[-f$savedir/remote];then'grep.
$PKGSAV/$patch/remote|sed's/STATE=.
*/STATE=obsolete/'>$TEMP_REMOTE'rm-f$PKGSAV/$patch/remotemv$TEMP_REMOTE$PKGSAV/$patch/remoterm-f$TEMP_REMOTEecho$Patch_label>>$savedir/obsoleted_byelif[-f$savedir/obsolete-o-f$savedir/obsolete.
Z];thenecho$Patch_label>>$savedir/obsoleted_byfidone#Ifadditionaloperationsarerequiredforthispackage,place#thosepackage-specificcommandshere.
#XXXSpecial_CommandsXXX#exit0patch_checkinstall脚本#checkinstallscripttovalidatebackingoutapatch.
#directoryformatoption.
##@(#)patch_checkinstall1.
295/10/10SMI##Copyright(c)1995bySunMicrosystems,Inc.
#Allrightsreserved#PATH=/usr/sadm/bin:$PATHLATER_MSG="PaTcH_MsG6ERROR:Alaterversionofthispatchisapplied.
"NOPATCH_MSG="PaTcH_MsG2ERROR:Patchnumber$ACTIVE_PATCHisnotinstalled"修补软件包应用程序包开发者指南2009年4月158NEW_LIST=""#GetOLDLIST.
$1##Confirmthatthepatchthatgotushereisthelatestoneinstalledon#thesystemandremoveitfromPATCHLIST.
#Is_Inst=0Skip=0active_base='echo$ACTIVE_PATCH|nawk'{printsubstr($0,1,match($0,"Patchvers_pfx")-1)}''active_inst='echo$ACTIVE_PATCH|nawk'{printsubstr($0,match($0,"Patchvers_pfx")+1)}''forpatchapplin${OLDLIST};doappl_base='echo$patchappl|nawk'{printsubstr($0,1,match($0,"Patchvers_pfx")-1)}''if[$appl_base=$active_base];thenappl_inst='echo$patchappl|nawk'{printsubstr($0,match($0,"Patchvers_pfx")+1)}''result='expr$appl_inst\>$active_inst'if[$result-eq1];thenputtext"$LATER_MSG"exit3elif[$appl_inst=$active_inst];thenIs_Inst=1Skip=1fifiif[$Skip=1];thenSkip=0elseNEW_LIST="${NEW_LIST}$patchappl"fidoneif[$Is_Inst=0];thenputtext"$NOPATCH_MSG"exit3fi##OK,all'swell.
Nowconditionthekeyvariables.
#echo"PATCHLIST=${NEW_LIST}">>$1echo"Patch_label=">>$1echo"PATCH_INFO_$ACTIVE_PATCH=backedout">>$1修补软件包第6章创建软件包的高级技术159#GetthecurrentPATCH_OBSOLETESandconditionitOld_Obsoletes=$PATCH_OBSOLETESecho$ACTIVE_OBSOLETES|sed'y/\/\n/'|\nawk-vPatchObsList="$Old_Obsoletes"'BEGIN{printf("PATCH_OBSOLETES=");PatchCount=split(PatchObsList,PatchObsComp,"");for(PatchIndexinPatchObsComp){Atisat=match(PatchObsComp[PatchIndex],"@");PatchObs[PatchIndex]=substr(PatchObsComp[PatchIndex],\0,Atisat-1);PatchObsCnt[PatchIndex]=substr(PatchObsComp\[PatchIndex],Atisat+1);}}{for(PatchIndexinPatchObs){if(PatchObs[PatchIndex]==$0){PatchObsCnt[PatchIndex]=PatchObsCnt[PatchIndex]-1;}}next;}END{for(PatchIndexinPatchObs){if(PatchObsCnt[PatchIndex]>0){printf("%s@%d",PatchObs[PatchIndex],PatchObsCnt\[PatchIndex]);}}printf("\n");}'>>$1#removetheusedparametersecho"ACTIVE_OBSOLETES=">>$1echo"Obsoletes_label=">>$1exit0patch_postinstall脚本#Thisscriptdeletestheusedbackoutdataforapatchpackage#andremovesthedeletesfileentries.
#修补软件包应用程序包开发者指南2009年4月160#directoryformatoptions.
##@(#)patch_postinstall1.
296/01/29SMI##Copyright(c)1995bySunMicrosystems,Inc.
#Allrightsreserved#PATH=/usr/sadm/bin:$PATHTHIS_DIR='dirname$0'Our_Deletes=$THIS_DIR/deletes##Deletetheusedbackoutdata#if[-f$Our_Deletes];thencat$Our_Deletes|whilereadpath;doifvalpath-l$path;thenClient_Path='echo"$CLIENT_BASEDIR/$path"|seds@//@/@'else#It'sanabsolutepathClient_Path=$pathfirm'removef$PKGINST$Client_Path'doneremovef-f$PKGINSTrm$Our_Deletesfi##Removethedeletesfile,checkinstallandthepostinstall#rm-r$PKGSAV/$ACTIVE_PATCHrm-f$THIS_DIR/checkinstall$THIS_DIR/postinstallexit0升级软件包升级软件包的过程与覆写软件包的过程极为不同.
尽管有一些特殊工具支持对作为SolarisOS的一部分交付的标准软件包进行升级,但可以设计一个非随附软件包来支持它自己的升级-前面的多个示例描述了一些可在管理员指导下具有前瞻性并且控制精确安装方法的软件包.
您还可以设计request脚本以支持软件包的直接升级.
如果管理员选择安装一个软件包以便完全替换另一个软件包,并且不留下残余的过时文件,软件包脚本可以执行此任务.
升级软件包第6章创建软件包的高级技术161此示例中的request脚本和postinstall脚本提供了一个简单的可升级软件包.
request脚本与管理员通信,然后在/tmp目录中设置一个简单的文件以删除旧的软件包实例.
(虽然request脚本创建了一个被禁止的文件,但这不会有什么问题,因为每个人都有权访问/tmp.
)然后,postinstall脚本执行/tmp中的shell脚本,该脚本对旧软件包执行必要的pkgrm命令,然后删除它自身.
此示例演示基本升级.
该示例少于50行代码,其中包括一些相当长的消息.
可以对其进行扩展以回退升级,或者根据设计者的要求对软件包进行其他重要转换.

升级选项的用户界面设计必须完全确保管理员充分了解升级过程,并且已经主动请求升级而不是并行安装.
只要用户界面能够清楚地说明操作,执行诸如升级这样的复杂操作就不会出现什么错误.
request脚本#requestscriptcontrolanupgradeinstallationPATH=/usr/sadm/bin:$PATHUPGR_SCRIPT=/tmp/upgr.
$PKGINSTUPGRADE_MSG="Doyouwanttoupgradetheinstalledversion"UPGRADE_HLP="Ifupgradeisdesired,theexistingversionofthe\packagewillbereplacedbythisversion.
Ifitisnot\desired,thisnewversionwillbeinstalledintoadifferent\basedirectoryandbothversionswillbeusable.
"UPGRADE_NOTICE="Conflictapprovalquestionsmaybedisplayed.
The\listedfilesaretheonesthatwillbeupgraded.
Please\answer\"y\"tothesequestionsiftheyarepresented.
"pkginfo-v1.
0-qSUNWstuf.
\*if[$-eq0];then#Seeifupgradeisdesiredhereresponse='ckyorn-p"$UPGRADE_MSG"-h"$UPGRADE_HLP"'if[$response="y"];thenOldPkg='pkginfo-v1.
0-xSUNWstuf.
\*|nawk'\/SUNW/{print$1}''#Initiateupgradeecho"PATH=/usr/sadm/bin:$PATH">$UPGR_SCRIPTecho"sleep3">>$UPGR_SCRIPTecho"echoNowremovingoldinstanceof$PKG">>\升级软件包应用程序包开发者指南2009年4月162$UPGR_SCRIPTif[${PKG_INSTALL_ROOT}];thenecho"pkgrm-n-R$PKG_INSTALL_ROOT$OldPkg">>\$UPGR_SCRIPTelseecho"pkgrm-n$OldPkg">>$UPGR_SCRIPTfiecho"rm$UPGR_SCRIPT">>$UPGR_SCRIPTecho"exit$">>$UPGR_SCRIPT#Gettheoriginalpackage'sbasedirectoryOldBD='pkgparam$OldPkgBASEDIR'echo"BASEDIR=$OldBD">$1puttext-l5"$UPGRADE_NOTICE"elseif[-f$UPGR_SCRIPT];thenrm-r$UPGR_SCRIPTfififiexit0postinstall脚本#postinstalltoexecuteasimpleupgradePATH=/usr/sadm/bin:$PATHUPGR_SCRIPT=/tmp/upgr.
$PKGINSTif[-f$UPGR_SCRIPT];thensh$UPGR_SCRIPT&fiexit0创建类归档软件包类归档软件包是对应用称序二进制接口(ApplicationBinaryInterface,ABI)的增强,其中,某些文件集已经组合为单个文件(即归档文件),并且可能已选择性地压缩或加密.
类归档格式最多可使初始安装速度提高30%,并且在将软件包和修补程序安装到可能活动的文件系统上的过程中提高可靠性.
以下各节提供有关归档软件包目录结构、关键字和faspac实用程序的信息.
创建类归档软件包第6章创建软件包的高级技术163归档软件包目录的结构下图中显示的软件包条目表示包含软件包文件的目录.
此目录必须与软件包同名.

下面列出了软件包目录内包含的文件和目录的功能.
项说明pkginfo文件,对软件包进行总体描述,包括特殊环境变量和安装指令pkgmap描述每个要安装对象的文件,如文件、目录或管道reloc可选目录,包含要相对于基目录安装的文件(可重定位的对象)root可选目录,包含要相对于root目录安装的文件(根对象)install可选目录,包含脚本和其他辅助文件(除了pkginfo和pkgmap,所有ftypei文件都位于此处)使用类归档格式,软件包生成器可以将reloc和root目录中的文件组合到归档文件中,然后对其进行压缩、加密或以所需的任何方式进行其他处理,以便提高安装速度,减小软件包大小,或者增加软件包的安全性.
ABI允许将软件包内的任何文件指定给某个类.
特定类中的所有文件都可以使用类操作脚本定义的自定义方法安装到磁盘中.
此自定义方法可以利用目标系统中提供的程序或随软件包一起提供的程序.
得到的格式很像标准ABI格式.
如下图所示,另一个目录被添加.
将要归档的任何文件类只是组合为单个文件,并且放置到archive目录中.
系统将从reloc和root目录中删除所有归档文件,并且将一个安装类操作脚本放置到install目录中.
Packagepkgmaprelocpkginfopath2path1.
.
.
rootpath2path1.
.
.
installscriptscopyrightdependencies图6–1软件包目录结构创建类归档软件包应用程序包开发者指南2009年4月164支持类归档软件包的关键字为了支持这一新的类归档格式,三个采用关键字形式的新接口在pkginfo文件内具有特殊含义.
这些关键字用于指定需要特殊处理的类.
每个关键字语句的格式为:keyword=class1[class2.
.
.
].
下表定义了每个关键字值.
关键字说明PKG_SRC_NOVERIFY如果所交付的软件包的reloc或root目录中的文件属于指定类,则该关键字告诉pkgadd不要验证这些文件是否存在以及文件属性.
所有归档类都需要此关键字,因为这些文件不再位于reloc或root目录中.
它们是archive目录中的专用格式文件.
Packagepkgmaparchivepkginfoclass2class1.
.
.
relocpath2path1.
.
.
rootpath2path1.
.
.
installscriptscopyrightdependencies图6–2归档软件包目录结构创建类归档软件包第6章创建软件包的高级技术165关键字说明PKG_DST_QKVERIFY这些类中的文件在安装后使用一个快速算法进行验证,只有少量或者没有任何文本输出.
快速验证首先正确设置每个文件的属性,然后检查以了解该操作是否成功.
然后,将根据pkgmap测试文件大小和修改时间.
不会执行checksum验证,该验证与标准验证机制相比错误恢复功能较差.
如果在安装期间发生断电或磁盘故障,则目录文件可能与已安装的文件不一致.
总能使用pkgrm解决这种不一致问题.
PKG_CAS_PASSRELATIVE通常,安装类操作脚本从stdin接收告诉它安装哪些文件的源和目标对列表.
指定给PKG_CAS_PASSRELATIVE的类不会获得这些源和目标对.
相反,这些类会收到单个列表,其中第一个条目是源软件包的位置,其余条目是目标路径.
这专门用于简化从归档文件中进行提取的操作.
根据源软件包的位置,您可以在archive目录中找到归档文件.
然后,目标路径被传递给负责提取归档文件内容的函数.
所提供的每个目标路径对于基目录而言是绝对的或相对的,具体取决于该路径原来位于root还是位于reloc.
如果选择此选项,可能难以将相对路径和绝对路径都组合到单个类中.
对于每个归档类,都需要一个类操作脚本.
这是一个包含Bourneshell命令的文件,该文件由pkgadd执行以便从归档中实际安装文件.
如果在软件包的install目录中找到一个类操作脚本,pkgadd会将所有安装职责移交给该脚本.
该类操作脚本以超级用户权限运行,并且可以将其文件放置在目标系统中的任何位置.
注–实现类归档软件包绝对必须的唯一关键字是PKG_SRC_NOVERIFY.
其他关键字可用于提高安装速度或保存代码.
faspac实用程序faspac实用程序将标准ABI软件包转换为随附软件包所使用的类归档格式.
此实用程序使用cpio进行归档,使用compress进行压缩.
生成的软件包在顶层目录中有一个名为archive的附加目录.
在此目录中,将包含按类命名的所有归档文件.
install目录将包含解压缩每个归档文件所需的类操作脚本.
绝对路径将不进行归档.

faspac实用程序具有以下格式:faspac[-mArchiveMethod]-a-s-q[-dBaseDirectory]/[-xExcludeList][ListofPackages]下表描述了每个faspac命令选项.
创建类归档软件包应用程序包开发者指南2009年4月166选项说明-mArchiveMethod指示一种归档或压缩方法.
bzip2是所使用的缺省压缩实用程序.
要切换到zip压缩或unzip解压缩方法,请使用-mzip,或者,对于cpio或compress,请使用-mcpio.
-a修复属性(只有超级用户才能执行此操作).
-s指示标准ABI类型软件包转换.
此选项将经过cpio或压缩处理的软件包进行打包,并使其具有符合标准ABI的软件包格式.
-q指示静默模式.
-dBaseDirectory指示所有软件包所在的目录将由命令行根据需要进行操作.
这与ListofPackages条目互斥.
-xExcludeList指示要从处理范围中排除的软件包的逗号分隔列表或用引号括起来的空格分隔列表.
ListofPackages指示要处理的软件包的列表.
创建类归档软件包第6章创建软件包的高级技术167168词汇表ABI请参见应用程序二进制接口(applicationbinaryinterface,ABI).
abstractsyntaxnotation1(抽象语法表示法1)一种表示抽象对象的方法.
例如,ASN.
1定义公钥证书、组成证书的所有对象以及对象的收集顺序.
不过,ASN.
1不指定针对存储或传输序列化对象的方式.
applicationbinaryinterface(应用程序二进制接口)对编译的应用程序和运行这些应用程序的操作系统之间的二进制系统接口的定义.

ASN.
1请参见抽象语法表示法1(abstractsyntaxnotation1,ASN.
1).
basedirectory(基目录)可重定位对象的安装位置.
在pkginfo文件中使用BASEDIR参数对基目录进行定义.
buildtime(生成时)使用pkgmk命令生成软件包的时间.
buildvariable(生成变量)以小写字母开头并在生成时被计算的变量.
certificateauthority(证书颁发机构)一种颁发证书的机构(例如Verisign),对软件包进行签名时将使用该证书.
classactionscript(类操作脚本)一种文件,用于定义要对一组软件包对象执行的一组操作.
class(类)用于对软件包对象进行分组的名称.
另请参见classactionscript(类操作脚本).
collectivelyrelocatableobject(可共同重定位的对象)相对于通用安装基目录进行定位的软件包对象.
另请参见basedirectory(基目录).
commonname(通用名称)带签名的软件包的软件包密钥库中列出的别名.
compositepackage(复合软件包)包含可重定位路径名和绝对路径名的软件包.
compverfile(compver文件)指定软件包向下兼容性的一种方法.
controlfile(控制文件)控制是否安装软件包以及软件包安装方式和位置的文件.
请参见informationfile(信息文件)和installationscript(安装脚本).
169copyright(版权)拥有和销售知识产权(例如,软件、源代码或文档)的权利.
必须在CD-ROM和插入文本上声明拥有权,无论该版权归SunSoft还是另一方所有.
在SunSoft文档中,也对版权拥有权进行了确认.
dependfile(depend文件)解析基本软件包相关性的一种方法.
另请参见compverfile(compver文件).
DER请参见distinguishedencodingrules(唯一编码规则).
digitalsignature(数字签名)用于验证软件包完整性和安全性的一种编码消息.
distinguishedencodingrules(唯一编码规则)ASN.
1对象的一种二进制表示法,用于定义在计算环境中针对存储或传输序列化ASN.
1对象的方式.
与带签名的软件包一起使用.
incompatiblepackage(不兼容软件包)与指定软件包不兼容的软件包.
另请参见dependfile(depend文件).
individuallyrelocatableobject(可单独重定位的对象)不限于定位到可共同重定位的对象所在的目录位置的软件包对象.
使用prototype文件中path字段中的安装变量对其进行定义,安装位置通过request脚本或checkinstall脚本确定.
informationfile(信息文件)一种文件,可以定义软件包相关性、提供版权信息或在目标系统上保留空间.

installtime(安装时)使用pkgadd命令安装软件包的时间.
installvariable(安装变量)以大写字母开头并在安装时被计算的变量.
installationscript(安装脚本)使您能够提供软件包自定义安装过程的脚本.
ITU-TRecommendationX.
509(ITU-T推荐标准X.
509)一种指定广泛采用的X.
509公钥证书语法的协议.
packageabbreviation(软件包缩写)通过pkginfo文件中的PKG参数定义的软件包的简短名称.
packageidentifier(软件包标识符)通过pkgadd命令添加到软件包缩写的数字后缀.
packageinstance(软件包实例)软件包的变体,通过组合软件包的pkginfo文件中的PKG、ARCH和VERSION参数的定义确定.
packagekeystore(软件包密钥库)可通过软件包工具查询的证书和密钥的系统信息库.
copyright(版权)应用程序包开发者指南2009年4月170packageobject(软件包对象)包含在要安装到目标系统的软件包中的应用程序文件的另一种称呼.
package(软件包)软件应用程序所需文件和目录的集合.
parametricpathname(参数化路径名)包含变量规范的路径名.
patchlist(修补程序列表)影响当前软件包的修补程序的列表.
该修补程序列表记录在pkginfo文件中的已安装软件包中.
PEM请参见privacyenhancedmessage(保密性增强消息).
PKCS12请参见publickeycryptographystandard#12(公钥密码学标准#12).
PKCS7请参见publickeycryptographystandard#7(公钥密码学标准#7).
prerequisitepackage(先决软件包)依赖于其他软件包是否存在的软件包.
另请参见dependfile(depend文件).
privacyenhancedmessage(保密性增强消息)一种使用base64编码和某些可选标头对文件进行编码的方式.
广泛用于将证书和私钥编码到文件系统或电子邮件中存在的文件中.
privatekey(私钥)仅为交换秘密消息的一方或多方所知的加密/解密密钥.
该私钥与公钥结合使用以创建带签名的软件包.
procedurescript(过程脚本)定义软件包安装和删除过程中的特定时刻发生的操作的脚本.
publickeycryptographystandard#12(公钥密码学标准#12)此标准描述将加密对象存储在磁盘上的语法.
软件包密钥库会以这种格式进行维护.

星梦云:四川100G高防4H4G10M月付仅60元

星梦云怎么样?星梦云资质齐全,IDC/ISP均有,从星梦云这边租的服务器均可以备案,属于一手资源,高防机柜、大带宽、高防IP业务,一手整C IP段,四川电信,星梦云专注四川高防服务器,成都服务器,雅安服务器。星梦云目前夏日云服务器促销,四川100G高防4H4G10M月付仅60元;西南高防月付特价活动,续费同价,买到就是赚到!点击进入:星梦云官方网站地址1、成都电信年中活动机(成都电信优化线路,封锁...

hostkvm:美国VPS,三网强制CU-VIP线路,$5/月,1G内存/1核/15gSSD/500g流量

hostkvm在2021年3月新上线洛杉矶新VPS业务,强制三网接入中国联通优化线路,是当前中美之间性价比最高、最火热的线路之一,性价比高、速度非常好,接近联通AS9929和电信AS4809的效果,带宽充裕,晚高峰也不爆炸。 官方网站:https://hostkvm.com 全场优惠码:2021(全场通用八折,终身码,长期) 美国 US-Plan0【三网联通优化线路】 内存:1G CPU:...

FBICDN,0.1元解决伪墙/假墙攻击,超500 Gbps DDos 防御,每天免费流量高达100G,免费高防网站加速服务

最近很多网站都遭受到了伪墙/假墙攻击,导致网站流量大跌,间歇性打不开网站。这是一种新型的攻击方式,攻击者利用GWF规则漏洞,使用国内服务器绑定host的方式来触发GWF的自动过滤机制,造成GWF暂时性屏蔽你的网站和服务器IP(大概15分钟左右),使你的网站在国内无法打开,如果攻击请求不断,那么你的网站就会是一个一直无法正常访问的状态。常规解决办法:1,快速备案后使用国内服务器,2,使用国内免备案服...

crontab用法为你推荐
美国虚拟空间国内虚拟空间与美国虚拟主机有什么不一样域名注册公司国内正规的国别域名注册商是哪家?虚拟主机服务器虚拟主机与独立服务器区别me域名注册请问 .me 域名在哪里注册或查看,至少万网查不到全能虚拟主机旗舰型全能主机500m(x500.特惠虚拟主机)要什么数据库免费虚拟主机空间免费的虚拟主机空间有没有asp主机ASP环境是不是所有的主机都默认支持?虚拟主机申请域名申请以及虚拟主机免费网站空间哪里有永久免费的网站空间?香港虚拟主机推荐一下香港的虚拟主机公司!
韩国服务器租用 vps代购 60g硬盘 英文简历模板word 服务器日志分析 xfce 线路工具 ibox官网 泉州电信 免费防火墙 可外链网盘 paypal注册教程 linux使用教程 安徽双线服务器 移动服务器托管 新加坡空间 独立主机 免费个人网页 深圳主机托管 netvigator 更多