要在 BE 之间共享数据,需使用一个共享的数据集,以及一个从 BE 中目录结构指向该共享数据集的符号链接。IPS 软件包提供 BE 中的符号链接。同一个或另一个软件包提供创建和挂载共享数据集的 SMF 服务。软件包在 BE 中安装到新的共享数据集时,BE 中的链接与Oracle Solaris 中现有的共享内容中介绍的指向 /var/share 的链接类似。BE 中运行的应用程序通过该链接对共享区域进行写入和读取。
最佳做法是创建一个数据集,方便在不同 BE 中运行的许多应用程序可以在该数据集中共享内容。为要共享的每个数据目录创建单独的数据集会导致在每个非全局区域中创建多个数据集,而在每个区域创建多个数据集并不可取。例如,您可以创建挂载在 /opt/share 上的 OPTSHARE 数据集。不同的应用程序可以在 /opt/share 下的不同目录中共享数据。
虽然您可以使用不同的软件包和服务创建共享数据集,但是请注意,此类软件包可能通过其他 BE 安装。尽管创建数据集的软件包和服务未安装在当前 BE 中,共享数据集也可能可用。这些示例中介绍的应用程序软件包提供的服务会检查数据集是否已经存在,如果数据集不存在,将进行创建。
此过程介绍如何提供共享数据集以及从当前 BE 指向共享数据集的链接,以便使该应用程序可以与多个 BE 中的多个应用程序共享数据。应用程序软件包将提供以下各项:
创建共享数据集的 SMF 服务
当前 BE 中目标为共享数据集的链接
此示例中的软件包仅显示了创建共享数据集和链接到共享数据集所需的步骤。应用程序的其他操作(例如,可执行文件和配置文件)在此示例中将被忽略。
为软件包开发创建一个区域,其中包含 BE 中所需要的目录以及一个指向 BE 外共享区域的链接。
$ mkdir -p proto/lib/svc/manifest/site $ mkdir -p proto/lib/svc/method
$ mkdir -p proto/opt/myapp $ ln -s ../../opt/share/myapp/logfiles proto/opt/myapp/logfiles
在 proto/lib/svc/method 中,创建一个执行以下任务的脚本:
创建数据集 rpool/OPTSHARE(在多个 BE 之间共享)。每个池只需要创建一次共享数据集。池中当前和未来所有 BE 均可以访问该数据集。在创建数据集之前,检查数据集是否已经存在。
在共享数据集中创建所需的目录结构,包括本示例中的链接目标:/opt/share/myapp/logfiles。
该脚本是服务的启动方法。在此示例中,脚本名为 myapp-share-files.sh。在下一个步骤中创建服务清单时,将需要该文件名。
脚本需要使用以下原型中显示的元素。请注意,sh 缺省为 ksh93。smf_method_exit 需要 smf_include.sh 文件。smf_method_exit 的第三个参数将显示在服务日志文件和 svcs 命令的输出中。
#!/bin/sh # Load SMF shell support definitions . /lib/svc/share/smf_include.sh # Create rpool/OPTSHARE with mount point /opt/share if it does not already exist # Create /opt/share/myapp/logfiles if it does not already exist # After this script runs, the service does not need to remain online. smf_method_exit $SMF_EXIT_TEMP_DISABLE done "shared area created"
在 proto/lib/svc/manifest/site 中,使用 svcbundle 命令创建服务。在 service-name 中,包括类别 site,因为该类别为内部服务。start-method 的值为上一步中创建的脚本的名称。
$ svcbundle -s service-name=site/myapp-share-files \ -s start-method=/lib/svc/method/myapp-share-files.sh -o myapp-share-files.xml
编辑生成的服务清单,在 template 数据区域中添加 common_name 和 description 信息。此外还可以添加 documentation 和其他模板数据。您可能还需要更改某些缺省设置,例如里程碑相关项或启动方法的超时。缺省情况下,创建的实例名为 default 并处于启用状态。
确保服务清单有效:
$ svccfg validate myapp-share-files.xml
使用 pkgsend generate 命令从软件包开发区域创建初始软件包清单。
$ pkgsend generate proto | pkgfmt > share.p5m.1 $ cat share.p5m.1 dir path=lib owner=root group=bin mode=0755 dir path=lib/svc owner=root group=bin mode=0755 dir path=lib/svc/manifest owner=root group=bin mode=0755 dir path=lib/svc/manifest/site owner=root group=bin mode=0755 file lib/svc/manifest/site/myapp-share-files.xml \ path=lib/svc/manifest/site/myapp-share-files.xml owner=root group=bin \ mode=0644 dir path=lib/svc/method owner=root group=bin mode=0755 file lib/svc/method/myapp-share-files.sh \ path=lib/svc/method/myapp-share-files.sh owner=root group=bin mode=0755 dir path=opt owner=root group=bin mode=0755 dir path=opt/myapp owner=root group=bin mode=0755 link path=opt/myapp/logfiles target=../../opt/share/myapp/logfiles
为软件包指定名称、版本、摘要和描述。
删除 opt、lib/svc/manifest/site 和 lib/svc/method 目录操作,因为这些目录已由其他软件包提供。
将服务清单的组更改为 sys,以便与 /lib/svc/manifest 中的其他清单相匹配。
将服务清单的模式更改为 0444,将服务方法更改为 0555,以便与系统中的其他清单和方法相匹配。
为服务清单添加执行器以及方法文件,以便在那些文件安装或更新时重新启动 manifest-import 服务。
set name=pkg.fmri value=myapp@2.0 set name=pkg.summary value="Deliver shared directory" set name=pkg.description value="This example package delivers a directory \ and link that allows myapp content to be shared across BEs." set name=variant.arch value=$(ARCH) set name=info.classification \ value=org.opensolaris.category.2008:Applications/Accessories <transform dir path=opt$->drop> <transform dir path=lib$->drop> <transform dir path=lib/svc$->drop> <transform dir path=lib/svc/manifest$->drop> <transform dir path=lib/svc/manifest/site$->drop> <transform dir path=lib/svc/method$->drop> <transform file path=lib/svc/manifest/site/myapp-share-files.xml -> \ edit group bin sys> <transform file path=lib/svc/manifest/site/myapp-share-files.xml -> \ edit mode 0644 0444> <transform file path=lib/svc/manifest/site/myapp-share-dir.xml -> \ add restart_fmri svc:/system/manifest-import:default> <transform file path=lib/svc/method/myapp-share-files.sh -> \ edit mode 0755 0555> <transform file path=lib/svc/method/myapp-share-dir.sh -> \ add restart_fmri svc:/system/manifest-import:default>
$ pkgmogrify -DARCH=`uname -p` share.p5m.1 share.mog | pkgfmt > share.p5m.2 $ cat share.p5m.2 set name=pkg.fmri value=myapp@2.0 set name=pkg.summary value="Deliver shared directory" set name=pkg.description \ value="This example package delivers a directory and link that allows myapp content to be shared across BEs." set name=info.classification \ value=org.opensolaris.category.2008:Applications/Accessories set name=variant.arch value=i386 file lib/svc/manifest/site/myapp-share-files.xml \ path=lib/svc/manifest/site/myapp-share-files.xml owner=root group=sys \ mode=0444 file lib/svc/method/myapp-share-files.sh \ path=lib/svc/method/myapp-share-files.sh owner=root group=bin mode=0755 dir path=opt/myapp owner=root group=bin mode=0555 link path=opt/myapp/logfiles target=../../opt/share/myapp/logfiles
使用 pkgdepend 命令自动生成和解析软件包的相关项。解析相关项的输出将自动存储在后缀为 .res 的文件。
此示例为 ksh93 生成了相关项。此外也可能生成其他相关项,具体取决于启动方法。另外,服务和服务实例在 org.opensolaris.smf.fmri 中声明。
$ pkgdepend generate -md proto share.p5m.2 | pkgfmt > share.p5m.3 $ pkgdepend resolve -m share.p5m.3
以下行会添加到输出 share.p5m.3.res 文件中:
set name=org.opensolaris.smf.fmri value=svc:/site/myapp-share-files \ value=svc:/site/myapp-share-files:default depend fmri=pkg:/shell/ksh93@93.21.0.20110208-0.175.2.0.0.37.1 type=require depend fmri=pkg:/system/core-os@0.5.11-0.175.2.0.0.37.0 type=require
$ pkglint share.p5m.3.res
$ pkgsend -s site publish -d protosl share.p5m.3.res pkg://site/myapp@2.0,5.11:20140417T000014Z PUBLISHED
安装软件包。
$ pkg install -g ./site myapp
确认数据集和链接存在。
$ zfs list rpool/OPTSHARE NAME USED AVAIL REFER MOUNTPOINT rpool/OPTSHARE 38.5K 24.8G 38.5K /opt/share $ ls -l /opt/myapp lrwxrwxrwx 1 root root 21 Apr 16 17:32 logfiles -> /opt/share/myapp/logfiles
卸载软件包。/opt/myapp/logfiles 链接应被删除,服务清单和方法脚本也应被删除。rpool/OPTSHARE 数据集仍应存在,因为它不属于打包内容:该数据集是由服务创建的。
此过程扩展了前一过程。在此示例中,有些需要共享的数据已经存在。应用程序软件包会提供一个暂存区域,将要共享的数据复制到暂存区域。SMF 服务会将数据从暂存区域移动到共享区域。
除链接外,软件包还在 BE 中提供一个暂存区域,用于保存将重新定义为链接的目录中已经存在的未打包内容。
除创建共享数据集外,SMF 服务会将暂存区域中存在的所有内容移动到共享区域。
将出现的所有 logfiles 更改为 logs。
$ mkdir -p proto/lib/svc/manifest/site $ mkdir -p proto/lib/svc/method $ mkdir -p proto/opt/myapp $ ln -s ../../opt/share/myapp/logs proto/opt/myapp/logs
在此示例中,myapp@1.0 软件包将 /opt/myapp/logs 作为目录安装,而 myapp 应用程序会将内容写入此目录。当此新的 myapp@3.0 软件包将 /opt/myapp/logs 作为链接安装时,/opt/myapp/logs 目录中的任何内容将保存在 /var/pkg/lost+found 中。要将该内容保存到新共享区域,可提供一个区域用于保存该内容的副本。
$ mkdir -p proto/opt/myapp/.migrate/logs
服务会将内容从 BE 中的该暂存区域移动到共享区域。
myapp@3.0 软件包写入 /opt/myapp/logs 的内容将通过链接直接转到共享区域,如上一示例所示。
将以下任务添加到前一过程中创建的 proto/lib/svc/method/myapp-share-files.sh 脚本:将内容从暂存区域移动到共享区域。
不要使用服务删除空的暂存区域。暂存区域为打包内容,只应通过卸载软件包删除。
#!/bin/sh # Load SMF shell support definitions . /lib/svc/share/smf_include.sh # Create rpool/OPTSHARE with mount point /opt/share if it does not already exist # Create /opt/share/myapp/logfiles if it does not already exist # Move any content from /opt/myapp/.migrate/logs to /opt/share/myapp/logs # After this script runs, the service does not need to remain online. smf_method_exit $SMF_EXIT_TEMP_DISABLE done "myapp shared files moved"
$ svcbundle -s service-name=site/myapp-share-files \ -s start-method=/lib/svc/method/myapp-share-files.sh -o myapp-share-files.xml
使用 svccfg validate 命令确保服务清单有效。
除以下修改,清单与上一示例中的软件包清单基本相同:
将出现的所有 logfiles 更改为 logs。
添加以下两项操作:
dir path=opt/myapp/.migrate owner=root group=bin mode=0755 dir path=opt/myapp/.migrate/logs owner=root group=bin mode=0755
向上一示例中的 pkgmogrify 的 share.mog 输入文件添加以下行。salvage-from 属性会将 /opt/myapp/logs 目录中的任何未打包内容移动到 /opt/myapp/.migrate/logs 目录。然后,服务将 /opt/myapp/.migrate/logs 中的内容移动到 /opt/share/myapp/logs。
<transform dir path=opt/myapp/.migrate/logfiles -> \ add salvage-from /opt/myapp/logfiles>
将该软件包命名为 myapp@3.0。
运行 pkgmogrify,如上一示例中所示。
创建 /opt/myapp/logs 作为常规目录,并向其放入一些文件。
安装 myapp@3.0 软件包。确认以下方面:已正确检测数据集是否存在并加以正确处理,新链接存在,/opt/myapp/logs 目录为空目录,/opt/myapp/.migrate/logs 目录存在且为空目录,/opt/share/myapp/logs 目录存在并包含最初位于 /opt/myapp/logs 目录中的内容。