1. 程式人生 > >使用spec文件語法創建一個rpm

使用spec文件語法創建一個rpm

sbin upd 環境 border 默認 自己 erase 刪除索引 -h

How to create an RPM package/zh-hk

< How to create an RPM package


此頁面包含 Packaging:ScriptletSnippets 的 zh_CN 翻譯,由於不具有 ScriptletSnippets 的編輯權限,故在此保存翻譯。

Contents

[hide]
  • 1 RPM 打包腳本綜述
  • 2 默認 Shell
  • 3 語法
  • 4 腳本片段命令
  • 5 編寫腳本片段
    • 5.1 在腳本片段間保存狀態
    • 5.2 Macros
    • 5.3 Trigger
  • 6 代碼片段
    • 6.1 共享庫
    • 6.2 用戶和組
    • 6.3 服務
      • 6.3.1 Init 腳本約定
    • 6.4 GConf
      • 6.4.1 為已修改的宏重建包
      • 6.4.2 EPEL 說明
    • 6.5 GSettings Schema
    • 6.6 gdk-pixbuf 加載器
    • 6.7 GTK+ 模塊
    • 6.8 GIO 模塊
    • 6.9 Texinfo
    • 6.10 Scrollkeeper
    • 6.11 desktop-database
    • 6.12 mimeinfo
    • 6.13 Icon 緩存
    • 6.14 Systemd
      • 6.14.1 新軟件包
        • 6.14.1.1 Scriptlets
      • 6.14.2 將軟件包從 SysV init 腳本遷移至 Systemd Unit
    • 6.15 Shells
  • 7 參考

RPM 打包腳本綜述

Rpm spec 文件有幾個部分,允許軟件包執行代碼來完成安裝和卸載操作。這些軟件包中的腳本片段大多用於更新系統信息。此頁面提供 RPM 腳本片段概述和一些常見軟件包的 spec 腳本片段的示例。更完整的腳本片段,請參閱 Maximum RPM book 。

默認 Shell

在 Fedora ,您可以直接使用默認的 bash shell (/bin/sh)。因此,所有腳本片段可以安全地在 bash 中運行。

語法

基本語法在 %build, %install 以及 rpm spec 文件的其他部分都是一致的。腳本支持一個特殊標記, -p 允許腳本直接調用一個程序,而不必啟用 shell 來運行程序。(即 %post -p /sbin/ldconfig

)

腳本片段還傳遞一個參數,用於表示本軟件包的個數。執行特定動作時,通過向 $1 傳遞不同值,來表示不同動作(安裝/升級/卸載),除了 %pretrans 和 %posttrans 它們的 $1 為 0 (rpm 4.4+ 支持 %pretrans 和 %posttrans)。對於安裝、升級和卸載,所傳遞的參數值如下表所示:

安裝(install) 升級(update/upgrade) 卸載(remove/erase)
%pretrans $1 == 0 $1 == 0 (N/A)
%triggerprein 安裝本包: $1 == 0, $2 == 1
安裝目標包: $1 == 1, $2 == 0
$1 == 1, $2 == 1 (N/A)
%pre $1 == 1 $1 == 2 (N/A)
%post $1 == 1 $1 == 2 (N/A)
%triggerin $1 == 1, $2 == 1 升級本包: $1 == 2, $2 == 1
升級目標包: $1 == 1, $2 == 2
(N/A)
%triggerun (N/A) $1 == 1, $2 == 1 卸載本包: $1 == 0, $2 == 1
卸載目標包: $1 == 1, $2 == 0
%preun (N/A) $1 == 1 $1 == 0
%postun (N/A) $1 == 1 $1 == 0
%triggerpostun (N/A) 升級目標包: $1 == 1, $2 == 1 卸載目標包: $1 == 1, $2 == 0
%posttrans $1 == 0 $1 == 0 (N/A)

註意,如果安裝相同軟件包的多個版本,這些參數值將會不同(這發生於同時安裝包,如 kernel 和 multilib 包。然而,它會引發錯誤,防止軟件包升級完成)。所以,使用以下結構的腳本是個好主意:

%pre
if [ $1 -gt 1 ] ; then   # -gt大於
fi

...對於 %pre 和 %post 腳本,檢查它的值等於 2。

除了一些特殊情況(如果有的話),我們希望所有的腳本退出時返回 0。因為 rpm 默認配置不使用 -e 參數執行 shell 腳本,不包括明確的 exit 調用(可能出現非 0 返回值),在腳本中,最後一個命令的退出狀態決定了腳本片段的退出狀態。大多數命令包含 "|| :" 後綴,這會強制以 0 狀態退出,無論命令是否可以正常工作。通常,最重要的是在腳本片段的最後一個命令添加此後綴,或在腳本的最後一行添加 ":" 或 "exit 0" 命令。註意,根據情況,使用其他的錯誤檢測/預防措施可能更合適,事先運行一些命令進行檢查,檢查成功才執行之後的命令。

腳本片段以非 0 狀態退出會中斷安裝/升級/刪除操作,避免事務中的包執行進一步的操作(見腳本片段命令部分),這可以防止舊包被刪除,同時也在 rpmdb 留下了重復記錄,在文件系統上留下了無主文件。某些情況下,事務中的腳本片段執行失敗,可能導致部分安裝失敗(不會中斷)。這往往局限於,軟件包不影響事務繼續執行,而此時中斷安裝之後的某些包,會導致更嚴重的系統問題。

腳本片段命令

%pre 和 %post 腳本片段分別在軟件包安裝前和安裝後執行。%preun 和 %postun 腳本片段分別在軟件包卸載前和卸載後執行。%pretrans 和 %posttrans 腳本片段分別在軟件包事務開始和結束時執行。升級軟件包時,按如下順序執行腳本片段:

  1. 檢查軟件包依賴、下載軟件包和 DRPM
  2. (all)%pretrans:事務開始時,執行新軟件包的此段代碼
  3. ...... (操作其它軟件包) ......
  4. (any)%triggerprein:此包的新版本安裝之前,觸發此包或其他包的腳本(如果有)
  5. (new)%triggerprein:指定的其他軟件包安裝之前,觸發此腳本
  6. (new)%pre:執行新軟件包的 %pre 腳本
  7. ...... (安裝所有新文件) ......
  8. (new)%post:執行新軟件包的 %post 腳本
  9. (any)%triggerin:安裝此軟件包時,觸發此包或其他包的腳本(如果有)
  10. (new)%triggerin:安裝指定的其他軟件包時,觸發此腳本
  11. (old)%triggerun:卸載指定的其他軟件包的舊版本時,觸發此腳本
  12. (any)%triggerun:卸載此軟件包的舊版本時,觸發此包或其他包的腳本(如果有)
  13. (old)%preun:執行舊軟件包的 %preun 腳本
  14. ...... (刪除所有舊文件) ......
  15. (old)%postun:執行舊軟件包的 %postun 腳本
  16. (old)%triggerpostun:指定的其他軟件包的舊版本已卸載之後,觸發此腳本
  17. (any)%triggerpostun:此包的舊版本已卸載之後,觸發其他包的腳本(如果有,此包腳本不運行)
  18. ...... (操作其它軟件包) ......
  19. (all)%posttrans:事務結束時,執行新軟件包的此段代碼
  20. 驗證軟件包,Done

Trigger 示例:

Trigger 用於在操作指定包時,運行您包中的一些代碼。通常因為您的包使用其他包的服務,或為其他包提供服務。參考以下的 Trigger 部分。提供以下示例以幫助理解:

%triggerin -p /usr/bin/perl -- ruby > 2.0, perl > 5.20  # -p 指定其他解釋器

以下情況觸發此段代碼:

  • 已安裝此包,ruby 或 perl 被安裝/升級時
  • 已安裝 ruby 或 perl,此包被安裝/升級時

編寫腳本片段

以下是一些編寫高質量打包腳本的建議。

在腳本片段間保存狀態

有時腳本需要保存之前腳本的一些狀態,以便在之後運行腳本時使用。這常用於對腳本片段進行優化。例如:

  • 如果 %posttrans 需要在軟件包升級時註銷一些信息,但舊軟件包刪除時,包含這些信息的文件也一並被刪除,%pre%post 腳本片段需要在文件中保存這些信息,以便 %posttrans 腳本可以訪問。
  • 如果我們只想讓 %posttrans 中的程序在每次事務時工作,我們需要編寫一個標誌文件,使 %posttrans 執行相應動作。

為了解決這些問題,腳本片段需要輸出供 %posttrans 使用的信息。我們建議使用 %{_localstatedir}/lib/rpm-state/ 子目錄保存信息。例如, 當安裝 eclipse 插件時,腳本需要在 %{_localstatedir}/lib/rpm-state/eclipse/ 創建一個文件。 %posttrans 運行腳本檢查文件是否存在。如果存在,執行相應動作,並刪除文件。這樣,每次事務時腳本只執行一次操作。

技術分享 在 Fedora 中,我們要求 %{_localstatedir}/lib/rpm-state/ 目錄屬於 rpm 或 filesystem 軟件包。使用事務時,軟件包需要創建自己的 %{_localstatedir}/lib/rpm-state/ 子目錄。

Macros

復雜的腳本片段可以記錄在 rpm 宏中。這有兩個好處:

  1. 標準包的作者只需要記住宏,不需要記住它復雜的內容。
  2. 宏的實現可能改變,而無需更新包。

編寫宏時,FPC 需要審閱宏(指南中記錄了打包者需要做什麽)。

原則上,宏不能包含腳本片段的起始標記(如 %pre)。這也意味著,一個宏不能同時定義 %pre%post 需要執行的動作。相反,需要編寫一個宏在 %pre 執行,編寫另一個宏在 %post 執行。此原則使所有 spec 文件可以以同樣的方式使用宏,即使它們已定義了 %pre%post

Trigger

Trigger 用於在操作指定包時,運行您包中的一些代碼。通常因為您的包使用其他包的服務,或為其他包提供服務。Trigger 語法如下:

%trigger{un|in|postun} [[-n] <subpackage>] [-p <program>] -- <trigger>

有一個很好的例子。假設您正在為 Emacs 和 Xemacs 編輯器打包一個很好的插件。它可以和這些編輯器一起工作,但根據不同編輯器,需要做不同配置。安裝插件時,可以檢查 Emacs 和 Xemacs 是否已安裝,並配置插件。但是,如果用戶稍後安裝 Xemacs,那麽會發生什麽呢?您的插件在 Xemacs 不可用,除非用戶卸載並重裝插件。通過觸發器,可以告訴此包,“已安裝 Xemacs,需要執行插件配置”。怎麽樣,很贊吧!

%triggerin -- emacs  # 以下情況執行:已安裝此包, emasc 被安裝/升級時;已安裝 emacs,此包被安裝/升級時。
# 安裝插件相關代碼
%triggerin -- xemacs # 以下情況執行:已安裝此包,xemasc 被安裝/升級時;已安裝 xemacs,此包被安裝/升級時。
# 安裝插件相關代碼
%triggerun -- emacs  # 以下情況執行:已安裝此包, emacs 被卸載時;已安裝 emacs,此包被卸載時。
# 卸載插件相關代碼
%triggerun -- xemacs # 以下情況執行:已安裝此包,xemacs 被卸載時;已安裝 xemacs,此包被卸載時。
# 卸載插件相關代碼

rpm 向觸發器腳本傳遞了兩個參數。$1 表示腳本完成時本軟件包的個數。$2 表示腳本完成時被觸發的軟件包的個數。

代碼片段

共享庫

安裝共享庫需要運行 /sbin/ldconfig 來更新動態鏈接器的緩存文件。可調用以下語句:

%post
/sbin/ldconfig
%postun
/sbin/ldconfig

僅需要運行 ldconfig 時,可使用 -p 選項避免運行 shell:

%post -p /sbin/ldconfig
%postun -p /sbin/ldconfig

建議使用第二種方式,這樣會自動添加 /sbin/ldconfig 依賴到軟件包(另外,可以避免啟用不必要的 Shell 進程來執行腳本)。

用戶和組

這些問題在 separate page 討論。

服務

Init 腳本約定

完整 SysV 風格的 init 腳本指南: Packaging/SysVInitScript
腳本片段細節: Packaging/SysVInitScript#InitscriptScriptlets

GConf

GConf 是 GNOME 桌面目前使用的配置方案。程序使用的默認值保存在 [NAME].schemas 文件,並安裝至 %{_sysconfdir}/gconf/schemas/[NAME].schemas。gconf 守護進程註冊並監控這些配置,並在配置變化時通知應用程序。schema 文件中包含了每個值的解釋(使用 gconf-editor 查詢數據庫時顯示這些信息)。

在構建包的過程中,必須禁止安裝 schema,並在實際安裝時,使用 gconf 守護進程註冊 [NAME].schemas 值;在刪除時,註銷這些值。腳本片段包含以下 4 個步驟。

創建包時,禁止安裝 Gconf schema:

%install
export GCONF_DISABLE_MAKEFILE_SCHEMA_INSTALL=1
make install DESTDIR=$RPM_BUILD_ROOT
...

GCONF_DISABLE_MAKEFILE_SCHEMA_INSTALL 環境變量在包構建過程中,禁止安裝 schema。另一種方法是通過 configure 標識設置:

%build
%configure --disable-schemas
...

不幸的是,此選項需要上遊開發者修改 Makefile.am 進行處理 。如果 Makefile.am 未配置,此選項不會生效,需使用環境變量代替。

第 2 步:

BuildRequires: GConf2
Requires(pre): GConf2
Requires(post): GConf2
Requires(preun): GConf2
...
%pre
%gconf_schema_prepare schema1 schema2
%gconf_schema_obsolete schema3

在這一部分,我們使用 2 個宏卸載/更新舊 schema。

%gconf_schema_prepare 用於任何 GConf schema。它需要卸載當前已安裝的 schema。它需要不包含路徑和後綴的空格分隔的 schema 列表。註意宏幕後的工作,這個宏在 %post 中只處理已更改的 Gconf schema。

%gconf_schema_obsolete 標記廢棄包之前提供的 schema。如果系統存在舊 schema,它會將其註銷。如果舊 schema 不存在,則不執行動作。此宏接受空格分隔的 schema 列表。以下示例可能用於軟件包已改名的情況。如果舊 schema 名為 foo.schemas,新 schema 名為 foobar.schemas,你應該使用:

%gconf_schema_prepare foobar
%gconf_schema_obsolete foo

下一步,對新安裝的 schema 進行處理:

%post
%gconf_schema_upgrade schema1 schema2

%gconf_schema_upgrade 接受以空格分隔的 schema 列表。在宏幕後,它實際註冊新版本的 schema 並註銷舊版本。

最後一步,在包刪除時註銷 schema:

%preun
%gconf_schema_remove schema1 schema2

當包升級時,rpm 調用 %pre 腳本來註冊和註銷 schema。當包卸載時,使用 %preun 腳本。%gconf_schema_remove 接受空格分隔的 schema 列表,並提供刪除方法。

為已修改的宏重建包

當宏修改時,使用這些宏的軟件包必須重建,以適應這些變化。repoquery 命令用於查找包含 schema 的軟件包:

repoquery --whatprovides "/etc/gconf/schemas/*" |sort |uniq |wc -l

EPEL 說明

EPEL 不包含 macros.gconf2,所以請按此說明操作: Packaging:EPEL#GConf

GSettings Schema

GSettings是 GNOME 3 桌面的配置系統。它代替了 GNOME 2 中使用的 GConf 系統。GSettings 支持可插拔後端,本地的 GNOME 使用 DConf 存儲設置。GSettings API 和工具屬於 glib2 軟件包。

程序使用的 GSettings schema 文件保存在 %{_datadir}/glib-2.0/schemas 目錄。schema 文件是擴展名為 .gschema.xml 的 XML 文件。運行時,GSettings 使用已編譯的二進制緩存(平臺無關),緩存通過 glib-compile-schemas 創建。只要修改 schema,就需要運行 /usr/bin/glib-compile-schemas 更新緩存。

%postun
if [ $1 -eq 0 ] ; then
    /usr/bin/glib-compile-schemas %{_datadir}/glib-2.0/schemas &> /dev/null || :
fi

%posttrans
    /usr/bin/glib-compile-schemas %{_datadir}/glib-2.0/schemas &> /dev/null || :

gdk-pixbuf 加載器

gdk-pixbuf 庫屬於 gdk-pixbuf2 軟件包。它用於在 GNOME 中加載各種圖像格式。gdk-pixbuf 可通過載入模塊來擴展對圖像格式的支持。這些模塊必須安裝在 %{_libdir}/gdk-pixbuf-2.0/2.10.0/loaders。為了避免載入所有模塊,gdk-pixbuf 在 %{_libdir}/gdk-pixbuf-2.0/2.10.0/loaders.cache 文件中保存模塊信息緩存。當模塊更改時,需要調用 /usr/bin/gdk-pixbuf-query-loaders 程序更新緩存信息。gdk-pixbuf-query-loaders 包含 -32 和 -64 版本,用於生成對應架構的緩存。

維護緩存文件的腳本是:

%postun
    /usr/bin/gdk-pixbuf-query-loaders-%{__isa_bits} --update-cache &> /dev/null || :

%post
if [ $1 -eq 1 ] ; then
    # For upgrades, the cache will be regenerated by the new package‘s %postun
    /usr/bin/gdk-pixbuf-query-loaders-%{__isa_bits} --update-cache &> /dev/null || :
fi

註意, %{__isa_bits} 宏根據軟件包架構返回 32 或 64。

GTK+ 模塊

GTK+ 工具包(gtk3)支持通過加載模塊來提供主題引擎,輸入方法,打印後端或其他功能。這些模塊必須安裝至 %{_libdir}/gtk-3.0 或 %{_libdir}/gtk-3.0/3.0.0 目錄。對於輸入法,GTK+ 使用 %{_libdir}/gtk-3.0/3.0.0/immodules.cache 緩存記錄輸入法模塊信息。當修改輸入法時,需要調用 gtk-query-immodules-3.0 更新緩存信息。gtk-query-immodules-3.0 包含 -32 和 -64 版本,用於生成對應架構的緩存。

維護緩存文件的腳本是:

%postun
/usr/bin/gtk-query-immodules-3.0-%{__isa_bits} --update-cache &> /dev/null || :

%post
if [ $1 -eq 1 ] ; then
    # For upgrades, the cache will be regenerated by the new package‘s %postun
    /usr/bin/gtk-query-immodules-3.0-%{__isa_bits} --update-cache &> /dev/null || :
fi

3.0版本的可執行文件,是由於 gtk2 包含相同功能的工具(gtk-query-immodules-2.0)。註意, %{__isa_bits} 宏根據軟件包架構返回 32 或 64。

GIO 模塊

GIO 共享庫屬於 glib2 軟件包。它是 GNOME 中的底層堆棧。GIO 可以通過模塊中的 extension points 實現擴展。這些擴展模塊必須安裝至 %{_libdir}/gio/modules。為了避免載入所有模塊,GIO 在相同目錄的 giomodule.cache 文件中記錄可用模塊的緩存信息。當模塊改變時,通過調用 gio-querymodules 程序更新緩存信息。 gio-querymodules 包含 -32 和 -64 版本,用於生成對應架構的緩存。

維護緩存文件的腳本是:

%postun
/usr/bin/gio-querymodules-%{__isa_bits} %{_libdir}/gio/modules &> /dev/null || :

%post
# We run this after every install or upgrade because of a cornercase
# when installing the second architecture of a multilib package 
/usr/bin/gio-querymodules-%{__isa_bits} %{_libdir}/gio/modules || :

註意, %{__isa_bits} 宏根據軟件包架構返回 32 或 64。

Texinfo

GNU 項目和許多其他程序使用 texinfo 文件格式保存文檔。這些 info 文件保存在 /usr/share/info/。安裝或刪除軟件包時,install-info 添加新文件至 info 索引中,並在卸載時刪除它們。

Requires(post): info
Requires(preun): info
...
%post
/sbin/install-info %{_infodir}/%{name}.info %{_infodir}/dir || :

%preun
if [ $1 = 0 ] ; then
  /sbin/install-info --delete %{_infodir}/%{name}.info %{_infodir}/dir || :
fi

這兩個腳本使用 install-info 在安裝時將 info 頁的信息添加至 info 索引文件,並在卸載時刪除索引信息。 "|| :" 可防止在系統已配置為不安裝任何 %doc 文件,或使用只讀掛載 %_netsharedpath /usr/share時,命令執行失敗。

Scrollkeeper

在當前 Fedora 中, scrollkeeper 已被 rarian 代替。rarian 不需要使用腳本片段進行處理。關於 EPEL 源的進一步說明,請訪問 Packaging:EPEL#Scrollkeeper

desktop-database

當 desktop entry 包含 MimeType 關鍵字時,應添加以下腳本。

%post
/usr/bin/update-desktop-database &> /dev/null || :

%postun
/usr/bin/update-desktop-database &> /dev/null || :

註意:對於 Fedora Core 5 之後的版本,使用相同的 mimeinfo 文件和 gtk-icon-cache。即 spec 文件不需要為此添加 Require desktop-file-utils 。對於舊發行版,應添加以下語句:

Requires(post): desktop-file-utils
Requires(postun): desktop-file-utils

(訪問 http://bugzilla.redhat.com/180898 和 http://bugzilla.redhat.com/180899)

mimeinfo

當軟件包在 %{_datadir}/mime/packages 安裝 XML 文件時,需使用以下腳本。

%post
/bin/touch --no-create %{_datadir}/mime/packages &>/dev/null || :

%postun
if [ $1 -eq 0 ] ; then
  /usr/bin/update-mime-database %{_datadir}/mime &> /dev/null || :
fi

%posttrans
/usr/bin/update-mime-database %{?fedora:-n} %{_datadir}/mime &> /dev/null || :

註意,與 gtk-update-icon-cache 代碼類似,這些腳本只在安裝 shared-mime-info 軟件包時運行,但不需要指定 Requires: shared-mime-info 。如果未安裝 shared-mime-info,update-mime-database 不會運行。然而這並不重要,因為大部分系統默認安裝 shared-mime-info。

Icon 緩存

如果應用程序在 %{_datadir}/icons/ 的子目錄(如 hicolor)安裝圖標,則必須更新圖標緩存,以便菜單正常顯示圖標。這包括:更新圖標上層目錄的時間戳,並運行 gtk-update-icon-cache。‘touch‘ 頂層目錄以便兼容 Icon theme specification 的環境可以刷新緩存,並且 gtk-update-icon-cache 的運行也需要基於目錄的時間戳。

註意,不需要為此添加依賴關系。如果 gtk-update-icon-cache 不可用,則不會更新圖標緩存,同上,如果 "touch" 不可用,則不會更新圖標緩存。不添加 gtk-update-icon-cache(即 gtk2 >= 2.6.0)或 "touch" 依賴,使軟件包(spec)對系統的兼容性更好。例如,舊發行版或最小化安裝方式,通常在 spec 文件、rpmdb 和源的元數據中不包含這些包的條目。

%post
/bin/touch --no-create %{_datadir}/icons/hicolor &>/dev/null || :

%postun
if [ $1 -eq 0 ] ; then
    /bin/touch --no-create %{_datadir}/icons/hicolor &>/dev/null
    /usr/bin/gtk-update-icon-cache %{_datadir}/icons/hicolor &>/dev/null || :
fi

%posttrans
/usr/bin/gtk-update-icon-cache %{_datadir}/icons/hicolor &>/dev/null || :

Systemd

包含 systemd unit 文件的軟件包,需要使用腳本以確保妥善處理這些服務。默認服務可以啟用或禁用。確定哪些情況下可以啟動服務,請參考 FESCo 策略: Starting_services_by_default。升級包時,如果服務正在運行,則會重啟服務;如果服務未運行,則不啟動它。同時,如果服務當前被禁用,則服務不會啟用。

新軟件包

技術分享 什麽是新軟件包?
在這段文字中,一個新軟件包指不包含任何 SysV init 腳本文件的包。

Scriptlets

Fedora 18+ 之後的 systemd 軟件包,提供了一系列宏來幫助處理 systemd 服務。這些宏的功能相當於舊版本 Fedora 的啟動腳本,但它還加入了 systemd "presets" 支持,參考文檔: https://fedoraproject.org/wiki/Features/PackagePresets
註意不要使用 %systemd_requires 宏。

Requires(post): systemd
Requires(preun): systemd
Requires(postun): systemd
BuildRequires: systemd

[...]
%post
%systemd_post apache-httpd.service

%preun
%systemd_preun apache-httpd.service

%postun
%systemd_postun_with_restart apache-httpd.service 

有些服務不支持重啟(如 D-Bus 和某些存儲守護進程)。如果你的服務不需要在升級時重啟,使用以下 %post 腳本代替以上腳本:

%postun
%systemd_postun

如果你的軟件包包含的一個或多個 systemd unit,需要在安裝時默認啟用,它們 必須 符合 Fedora preset policy。

宏的細節信息,請參考以下鏈接:
http://cgit.freedesktop.org/systemd/systemd/tree/src/core/macros.systemd.in
http://www.freedesktop.org/software/systemd/man/daemon.html

將軟件包從 SysV init 腳本遷移至 Systemd Unit

當從包含 SysV init 腳本的軟件包升級至包含 systemd unit 文件的軟件包時,將使用新的管理策略,不遷移用戶之前的配置。因此,可以簡單的使用以上腳本,不必擔心將 SysV 的相關信息遷移到 systemd。

技術分享 在發行版之間遷移
軟件包嚴禁從 systemd 更新到一個不包含 systemd 的版本。由於遷移將重置系統管理服務。只允許在 Fedora 版本間進行遷移。

Shells

/etc/shells 配置文件用於控制應用程序是否可以作為系統的用戶登錄 shell。它包含用於系統的有效 shells。如果你制作了一個新的 shell 軟件包,你需要將 shell 添加至此文件。詳細參考: man 5 SHELLS 獲得更多信息。

由於此配置可以編輯,所以首先需要確定配置已包含相關路徑。如果路徑不存在,就需要查看 shell 的二進制文件路徑。自從 Fedora 17 應用 UsrMove Feature 後,/bin 作為 /usr/bin 目錄的軟鏈接,我們需要導出所有路徑至 /etc/shells 文件。以下腳本,以打包名為 "foo" 的 shell 為例:

%post
if [ "$1" = 1 ]; then
  if [ ! -f %{_sysconfdir}/shells ] ; then
    echo "%{_bindir}/foo" > %{_sysconfdir}/shells
    echo "/bin/foo" >> %{_sysconfdir}/shells
  else
    grep -q "^%{_bindir}/foo$" %{_sysconfdir}/shells || echo "%{_bindir}/foo" >> %{_sysconfdir}/shells
    grep -q "^/bin/foo$" %{_sysconfdir}/shells || echo "/bin/foo" >> %{_sysconfdir}/shells
fi

%postun
if [ "$1" = 0 ] && [ -f %{_sysconfdir}/shells ] ; then
  sed -i ‘\!^%{_bindir}/foo$!d‘ %{_sysconfdir}/shells
  sed -i ‘\!^/bin/foo$!d‘ %{_sysconfdir}/shells
fi

參考

http://wiki.wenyinos.org/post-39.html

使用spec文件語法創建一個rpm