应用程序包开发者指南

创建安装脚本

此节讨论可选的软件包安装脚本。pkgadd 命令可自动执行使用软件包信息文件作为输入安装软件包时所需的所有操作。您不必提供任何软件包安装脚本。不过,如果您要为软件包创建自定义的安装过程,可以使用安装脚本来实现。安装脚本:

可使用四种类型的安装脚本执行自定义的操作:

软件包安装期间的脚本处理

您使用的脚本类型取决于安装过程中何时需要该脚本的操作。软件包安装后,pkgadd 命令执行以下步骤:

  1. 执行 request 脚本。

    软件包只有在此步骤中才能从正在安装软件包的管理员请求输入。

  2. 执行 checkinstall 脚本。

    checkinstall 脚本收集文件系统数据,并可创建或修改环境变量定义来控制后续安装。有关软件包环境变量的更多信息,请参见软件包环境变量

  3. 执行 preinstall 脚本。

  4. 为要安装的每个类安装软件包对象。

    这些文件的安装按逐个类进行,并相应执行类操作脚本。所处理的类列表及其安装顺序最初由 pkginfo 文件中的 CLASSES 参数定义。不过,request 脚本或 checkinstall 脚本可更改 CLASSES 参数的值。有关安装期间如何处理类的更多信息,请参见软件包安装期间如何处理类

    1. 创建符号链接、设备、命名管道和所需目录。

    2. 根据常规文件的类安装这些文件(文件类型 evf

      仅针对要安装的常规文件执行类操作脚本。所有其他软件包对象都根据 pkgmap 文件中的信息自动创建。

    3. 创建所有硬链接。

  5. 执行 postinstall 脚本。

软件包删除期间的脚本处理

删除软件包时,pkgrm 命令执行以下步骤:

  1. 执行 preremove 脚本。

  2. 为每个类删除软件包对象

    删除也按逐个类进行。删除脚本按照与安装时相反的顺序,根据 CLASSES 参数定义的序列进行处理。有关安装期间如何处理类的更多信息,请参见软件包安装期间如何处理类

    1. 删除硬链接。

    2. 删除常规文件。

    3. 删除符号链接、设备和命名管道。

  3. 执行 postremove 脚本。

request 脚本不会在软件包删除时进行处理。但是,该脚本的输出会保留在已安装的软件包中,供删除脚本使用。request 脚本的输出是环境变量列表。

对脚本可用的软件包环境变量

以下环境变量组对所有安装脚本可用。某些环境变量可由 request 脚本或 checkinstall 脚本修改。

为脚本获取软件包信息

在脚本中可使用两个命令请求获得关于软件包的信息:

脚本的退出代码

每个脚本必须使用下表中所示的退出代码之一退出。

表 3–2 安装脚本退出代码

代码 

含义 

脚本成功完成。  

致命错误。安装过程在此时终止。  

2  

警告或可能的错误状态。安装会继续。在完成之时将显示一条警告消息。  

3  

pkgadd 命令完全停止。只有 checkinstall 脚本会返回此代码。

10  

当完成所有选定软件包的安装时,应该重新引导系统。(此值应该添加到一位数退出代码之一。)  

20  

在完成当前软件包的安装时应立即重新引导系统。(此值应该添加到一位数退出代码之一。)  

有关安装脚本返回的退出代码的示例,请参见第 5 章


注 –

随您的软件包一起提供的所有安装脚本均应在 prototype 文件中有一个条目。文件类型应该是 i(表示软件包安装脚本)。


编写 request 脚本

request 脚本是软件包可直接与安装该软件包的管理员进行交互的唯一途径。例如,该脚本可用于询问管理员是否安装软件包的可选组件。

request 脚本的输出必须是环境变量及其值的列表。此列表可以包括在 pkginfo 文件中创建的任一参数以及 CLASSES BASEDIR 参数。该列表还可引入尚未在其他位置定义的环境变量。不过,适用情况下,pkginfo 文件应该始终提供缺省值。有关软件包环境变量的更多信息,请参见软件包环境变量

request 脚本为环境变量赋值时,它必须使这些值对 pkgadd 命令和其他软件包脚本可用。

request 脚本行为

request 脚本的设计规则


注 –

如果将安装软件包的管理员可能使用 JumpStartTM 产品,那么不能以交互方式安装该软件包。此时您不应该为软件包提供 request 脚本,或者您需要与管理员沟通,希望他们应该在安装之前使用 pkgask 命令。pkgask 命令存储管理员对 request 脚本的响应。有关 pkgask 命令的更多信息,请参见 pkgask(1M) 手册页。


Procedure如何编写 request 脚本

  1. 将包含信息文件的目录设置为当前工作目录。

  2. 使用您喜爱的文本编辑器创建名为 request 的文件。

  3. 完成时保存所做更改并退出编辑器。

  4. 完成以下任务之一。

  5. 生成您的软件包。

    如果需要,请参见如何生成软件包


示例 3–5 编写 request 脚本

request 脚本为环境变量赋值时,它必须使这些值对 pkgadd 命令可用。此示例显示了为以下四个环境变量执行该任务的 request 脚本片段: CLASSESNCMPBIN EMACSNCMPMAN。假定之前已使用该脚本在与管理员的交互会话中定义了这些变量。


# make environment variables available to installation
# service and any other packaging script we might have
 
cat >$1 <<!
CLASSES=$CLASSES
NCMPBIN=$NCMPBIN
EMACS=$EMACS
NCMPMAN=$NCMPMAN
!

另请参见

在生成软件包之后,请安装该软件包以确认它已正确安装并验证其完整性。第 4 章介绍了这些任务,并提供了有关如何将经过验证的软件包转换为分发介质的逐步说明。

使用 checkinstall 脚本收集文件系统数据

checkinstall 脚本在可选的 request 脚本执行之后不久执行。checkinstall 脚本以 install 用户身份运行(如果存在这样的用户),或者以 nobody 用户身份运行。checkinstall 脚本没有更改文件系统数据的权限。不过,它可以根据所收集的信息创建或修改环境变量,以控制所发生的安装的过程。该脚本还能够完全停止安装过程。

checkinstall 脚本旨在对文件系统执行基本检查,这些检查无法使用 pkgadd 命令正常执行。例如,此脚本可用于提前检查以确定当前软件包中是否有任何文件将覆写现有文件,或者将管理常规软件相关性。depend 文件只管理软件包级别的相关性。

request 脚本不同,无论是否提供了响应文件,checkinstall 脚本都会执行。存在该脚本并不表明软件包是交互式软件包。可使用 checkinstall 脚本的情形包括 request 脚本被禁用或管理交互无法实现。


注 –

checkinstall 脚本自 Solaris 2.5 及兼容发行版开始可用。


checkinstall 脚本行为

checkinstall 脚本的设计规则

Procedure如何收集文件系统数据

  1. 将包含信息文件的目录设置为当前工作目录。

  2. 使用您喜爱的文本编辑器创建名为 checkinstall 的文件。

  3. 完成时保存所做更改并退出编辑器。

  4. 完成以下任务之一。

  5. 生成您的软件包。

    如果需要,请参见如何生成软件包


示例 3–6 编写 checkinstall 脚本

checkinstall 示例脚本将检查是否安装了 SUNWcadap 软件包所需的数据库软件。


# checkinstall script for SUNWcadap
#
# This confirms the existence of the required specU database
 
# First find which database package has been installed.
pkginfo -q SUNWspcdA	# try the older one
 
if [ $? -ne 0 ]; then
   pkginfo -q SUNWspcdB	# now the latest
 
	  if [ $? -ne 0 ]; then	# oops
		    echo "No database package can be found. Please install the"
		    echo "SpecU database package and try this installation again."
		    exit 3		# Suspend
	  else
		    DBBASE="`pkgparam SUNWsbcdB BASEDIR`/db"	# new DB software
	  fi
else
	  DBBASE="`pkgparam SUNWspcdA BASEDIR`/db"	# old DB software
fi
 
# Now look for the database file we will need for this installation
if [ $DBBASE/specUlatte ]; then
	  exit 0		# all OK
else
	  echo "No database file can be found. Please create the database"
	  echo "using your installed specU software and try this"
	  echo "installation again."
	  exit 3		# Suspend
fi
 

另请参见

在生成软件包之后,请安装该软件包以确认它已正确安装并验证其完整性。第 4 章介绍了这些任务,并提供了有关如何将经过验证的软件包转换为分发介质的逐步说明。

编写过程脚本

过程脚本提供了将在软件包安装或删除期间的特定点执行的一组指令。根据这些指令将执行的时间,必须将四个过程脚本命名为预定义的名称之一。这些脚本不带参数执行。

过程脚本行为

过程脚本以 uid=rootgid=other 执行。

过程脚本的设计规则

Procedure如何编写过程脚本

  1. 将包含信息文件的目录设置为当前工作目录。

  2. 使用您喜爱的文本编辑器创建一个或多个过程脚本。

    必须将过程脚本命名为预定义的名称之一: preinstallpostinstall preremovepostremove

  3. 保存所做更改,然后退出编辑器。

  4. 完成以下任务之一。

  5. 生成您的软件包。

    如果需要,请参见如何生成软件包

另请参见

在生成软件包之后,请安装该软件包以确认它已正确安装并验证其完整性。第 4 章介绍了这些任务,并提供了有关如何将经过验证的软件包转换为分发介质的逐步说明。

编写类操作脚本

定义对象类

对象类允许在安装或删除时对一组软件包对象执行一系列操作。您需要在 prototype 文件中将对象指定给一个类。必须为所有软件包对象指定类,但是缺省情况下将为无需特殊操作的对象指定 none 类。

pkginfo 文件中定义的安装参数 CLASSES 是将安装的类的列表(包括 none 类)。


注 –

pkgmap 文件中定义的、属于未在 pkginfo 文件的此参数中列出的类的对象将不会被安装。


CLASSES 列表确定安装顺序。类 none 总是首先安装(如果有)而且最后删除。因为目录是所有其他文件系统对象的基础支持结构,因此应将所有目录指定给 none 类。通常使用 none 类是最安全的,虽然也可能有例外情况。此策略可确保在创建目录包含的对象之前创建目录。此外,不会在一个目录清空之前尝试删除该目录。

软件包安装期间如何处理类

下面描述了安装类时发生的系统操作。操作针对软件包的每个卷都会重复执行一次(在该卷进行安装时)。

  1. pkgadd 命令创建路径名列表。

    pkgadd 命令创建操作脚本处理的路径名列表。此列表的每一行都包含源路径名和目标路径名,由空格分隔。源路径名指明要安装的对象在安装卷上所处的位置。目标路径名指明应将该对象安装到的目标系统上的位置。列表的内容受以下条件限制:

    • 列表只包含属于关联类的路径名。

    • 如果尝试创建软件包对象失败,那么目录、命名管道、字符设备、块设备和符号链接将会包括在列表中,且源路径名设置为 /dev/null。通常,这些项目由 pkgadd 命令自动创建(如果尚不存在),并根据 pkgmap 文件中的定义被赋予适当的属性(模式、所有者、组)。

    • 文件类型为 l 的链接文件在任何情况下都不会包括在列表中。指定类中的硬链接在项目 4 中创建。

  2. 如果没有针对某个特定类的安装提供类操作脚本,则生成的列表中的路径名将会从卷复制到相应的目标位置。

  3. 执行类操作脚本(如果存在)。

    将会使用包含项目 1 中生成的列表的标准输入调用类操作脚本。如果该卷是软件包的最后一个卷,或者该类中不再有对象存在,则将使用单个参数 ENDOFCLASS 执行该脚本。


    注 –

    即使软件包中不存在该类的常规文件,也会使用一个空列表和 ENDOFCLASS 参数至少调用类操作脚本一次。


  4. pkgadd 命令执行内容和属性审计,并创建硬链接。

    成功执行项目 2 或 3 之后,pkgadd 命令将审计路径名列表的内容和属性信息。pkgadd 命令会自动创建与类关联的链接。将为生成的列表中的所有路径名更正检测到的属性不一致性。

软件包删除期间如何处理类

对象是按逐个类删除的。对于软件包存在但未在 CLASSES 参数中列出的类将首先被删除(例如,使用 installf 命令安装的对象)。CLASSES 参数中列出的类按相反顺序删除。none 类总是最后删除。下面描述了删除类时发生的系统操作:

  1. pkgrm 命令创建一个路径名列表。

    pkgrm 命令创建属于指定类的已安装路径名的列表。其他软件包引用的路径名将会从列表中排除,除非其文件类型为 ee 文件类型表示该文件应该在安装或删除时进行编辑。

    如果正被删除的软件包在安装期间修改了任何类型为 e 的文件,该软件包应只删除它添加的行。请勿删除一个非空的可编辑文件。删除软件包添加的行。

  2. 如果不存在类操作脚本,将会删除路径名。

    如果您的软件包没有类的删除类操作脚本,将会删除 pkgrm 命令生成的列表中的所有路径名。


    注 –

    文件类型为 e(可编辑)的文件不会指定给类和关联的类操作脚本。这些文件将在此时被删除,即使路径名与其他软件包共享。


  3. 如果类操作脚本存在,将会执行该脚本。

    pkgrm 命令使用包含项目 1 中生成的列表的脚本标准输入来调用类操作脚本。

  4. pkgrm 命令执行审计。

    成功执行类操作脚本之后,pkgrm 命令会从软件包数据库删除对路径名的引用,除非路径名由其他软件包引用。

类操作脚本

类操作脚本定义一组将在安装或删除软件包期间执行的操作。将会根据其类定义对一组路径名执行这些操作。有关类操作脚本的示例,请参见第 5 章

类操作脚本根据它将处理的类以及这些操作是在软件包安装还是删除期间发生来命名。下表中显示了两种名称格式:

名称格式 

说明 

i.class

在软件包安装期间,对指定类中的路径名进行处理 

r.class

在软件包删除期间,对指定类中的路径名进行处理  

例如,名为 manpage 的类的安装脚本名称将是 i.manpage,删除脚本名称将是 r.manpage


注 –

这种文件名格式不适用于属于 sedawkbuild 系统类的文件。有关这些特殊类的更多信息,请参见特殊系统类


类操作脚本行为

类操作脚本的设计规则

特殊系统类

系统提供四个特殊类:

如果一个软件包中的多个文件需要的特殊处理可完全通过 sedawksh 命令定义,则使用系统类安装的速度比使用多个类及其对应类操作脚本更快。

sed 类脚本

sed 类提供了一种修改目标系统上现有对象的方法。如果存在属于 sed 类的文件,sed 类操作脚本将在安装时自动执行。sed 类操作脚本的名称应该与对其执行指令的文件的名称相同。

sed 类操作脚本按以下格式提供 sed 指令:

两个命令指定应执行指令的时间。位于 !install 命令之后的 sed 指令在软件包安装期间执行。位于 !remove 命令之后的 sed 指令在软件包删除期间执行。这些命令在文件中的使用顺序无关紧要。

有关 sed 指令的更多信息,请参见 sed(1) 手册页。有关 sed 类操作脚本的示例,请参见第 5 章

awk 类脚本

awk 类提供了一种修改目标系统上现有对象的方法。这些修改将以 awk 类操作脚本中的 awk 指令实现。

如果存在属于 awk 类的文件,awk 类操作脚本将在安装时自动执行。这类文件包含如下格式的 awk 类脚本指令:

两个命令指定应执行指令的时间。位于 !install 命令之后的 awk 指令在软件包安装期间执行。位于 !remove 命令之后的指令在软件包删除期间执行。可按照任意顺序使用这些命令。

awk 类操作脚本的名称应该与对其执行指令的文件的名称相同。

待修改的文件用作 awk 命令的输入,该脚本的输出最终将替换原始对象。使用该语法可能不会将环境变量传递给 awk 命令。

有关 awk 指令的更多信息,请参见 awk(1) 手册页。

build 类脚本

build 类可通过执行 Bourne shell 指令创建或修改软件包对象文件。这些指令作为软件包对象提供。如果该软件包对象属于 build 类,这些指令将会在安装时自动运行。

build 类操作脚本的名称应该与对其执行指令的文件的名称相同。该名称还必须可由 sh 命令执行。该脚本的输出将成为生成或修改后的文件新版本。如果脚本未生成任何输出,表明没有创建或修改该文件。因此,该脚本可以修改或创建文件本身。

例如,如果软件包提供了一个缺省文件 /etc/randomtable,并且目标系统上尚不存在该文件,则 prototype 文件条目可能如下所示:


e build /etc/randomtable ? ? ?

软件包对象 /etc/randomtable 可能如下所示:


!install
# randomtable builder
if [ -f $PKG_INSTALL_ROOT/etc/randomtable ]; then
		echo "/etc/randomtable is already in place.";
	    else
		echo "# /etc/randomtable" > $PKG_INSTALL_ROOT/etc/randomtable
		echo "1121554	# first random number" >> $PKG_INSTALL_ROOT/etc/randomtable
fi
 
!remove
# randomtable deconstructor
if [ -f $PKG_INSTALL_ROOT/etc/randomtable ]; then
		# the file can be removed if it's unchanged
		if [ egrep "first random number" $PKG_INSTALL_ROOT/etc/randomtable ]; then
			rm $PKG_INSTALL_ROOT/etc/randomtable;
		fi
fi
 

有关使用 build 类的另一个示例,请参见第 5 章

preserve 类脚本

preserve 类通过确定在安装软件包时是否要覆写现有文件来保留软件包对象文件。使用 preserve 类脚本时的两种可能情况是:

preserve 脚本会将上述两种情况的结果都视为成功。只有在第二种情况中当文件无法复制到目标目录时才会失败。

自 Solaris 7 发行版开始,i.preserve 脚本以及该脚本的一个副本 i.CONFIG.prsv 以及其他类操作脚本都可在 /usr/sadm/install/scripts 目录中找到。

可修改该脚本以包括您希望保留的一个或多个文件名。

manifest 类脚本

manifest 类会自动安装或卸载与 SMF 清单相关联的服务管理工具 (Service Management Facility, SMF) 服务。如果您不熟悉 SMF,请参见《系统管理指南:基本管理》中的第 16  章 “管理服务(概述)”,获取有关如何使用 SMF 来管理服务的信息。

软件包中的的所有服务清单都应由类 manifest 来标识。安装和移除服务清单的类操作脚本包含在软件包子系统中。调用 pkgadd(1M) 时,会导入此服务清单。调用 pkgrm(1M) 时,会删除服务清单中禁用的实例。还会删除清单中没有保留实例的所有服务。如果将 -R 选项提供给 pkgadd(1M) 或 pkgrm(1M),在系统下一次以备用引导路径重新引导时,才会完成这些服务清单操作。

以下软件包信息文件中的部分代码显示了 manifest 类的用法。

# packaging files
i pkginfo
i copyright
i depend
i preinstall
i postinstall
i i.manifest
i r.manifest
#
# source locations relative to the prototype file
#
d none var 0755 root sys
d none var/svc 0755 root sys
d none var/svc/manifest 0755 root sys
d none var/svc/manifest/network 0755 root sys
d none var/svc/manifest/network/rpc 0755 root sys
f manifest var/svc/manifest/network/rpc/smserver.xml 0444 root sys

Procedure如何编写类操作脚本

  1. 将包含信息文件的目录设置为当前工作目录。

  2. prototype 文件中为软件包对象指定所需类名。

    例如,将对象指定给 applicationmanpage 类将如下所示:


    f manpage /usr/share/man/manl/myappl.1l
    f application /usr/bin/myappl
  3. pkginfo 文件中修改 CLASSES 参数,使其包含要在软件包中使用的类名。

    例如,applicationmanpage 类的条目将如下所示:


    CLASSES=manpage application none

    注 –

    none 类始终最先安装,最后删除,无论它在 CLASSES 参数的定义中位置如何。


  4. 如果您要为属于 sedawkbuild 类的文件创建类操作脚本,请将包含软件包对象的目录设置为当前工作目录。

  5. 为属于 sedawkbuild 类的文件创建类操作脚本或软件包对象。

    例如,名为 application 的类的安装脚本将命名为 i.application,而其删除脚本将命名为 r.application

    切记,当一个文件属于具有类操作脚本的类时,脚本必须安装该文件。pkgadd 命令不安装有类操作脚本的文件,虽然它确实执行安装验证。如果您定义了一个类但是没有提供类操作脚本,则对该类执行的唯一操作是将组件从安装介质复制到目标系统(缺省 pkgadd 行为)。

  6. 完成以下任务之一

  7. 生成您的软件包。

    如果需要,请参见如何生成软件包

下一步操作

在生成软件包之后,请安装该软件包以确认它已正确安装并验证其完整性。第 4 章介绍了如何执行此任务,并提供了有关如何将经过验证的软件包转换为分发介质的逐步说明。