歡迎光臨
每天分享高質量文章

如何構建 RPM 包 | Linux 中國

節省跨多個主機安裝檔案和腳本的時間和精力。
— David Both


致謝
編譯自 | 
https://opensource.com/article/18/9/how-build-rpm-packages
 
 作者 | David Both
 譯者 | Liang Chen (Flowsnow) ????共計翻譯:28.0 篇 貢獻時間:1062 天

節省跨多個主機安裝檔案和腳本的時間和精力。

自20多年前我開始使用 Linux 以來,我已經使用過基於 rpm 的軟體包管理器在 Red Hat 和 Fedora Linux 系統上安裝軟體。我使用過 rpm 程式本身,還有 yum 和 dnf ,用於在我的 Linux 主機上安裝和更新軟體包,dnf 是 yum 的一個近親。 yum 和 dnf 工具是 rpm 實用程式的包裝器,它提供了其他功能,例如查找和安裝包依賴項的功能。

多年來,我創建了許多 Bash 腳本,其中一些腳本具有單獨的配置檔案,我希望在大多數新計算機和虛擬機上安裝這些腳本。這也能解決安裝所有這些軟體包需要花費大量時間的難題,因此我決定通過創建一個 rpm 軟體包來自動執行該過程,我可以將其複製到標的主機並將所有這些檔案安裝在適當的位置。雖然 rpm 工具以前用於構建 rpm 包,但該功能已被刪除,並且創建了一個新工具來構建新的 rpm。

當我開始這個專案時,我發現很少有關於創建 rpm 包的信息,但我找到了一本書,名為《Maximum RPM》,這本書才幫我弄明白了。這本書現在已經過時了,我發現的絕大多數信息都是如此。它也已經絕版,用過的副本也需要花費數百美元。Maximum RPM[1] 的在線版本是免費提供的,並保持最新。該 RPM 網站[2]還有其他網站的鏈接,這些網站上有很多關於 rpm 的文件。其他的信息往往是簡短的,顯然都是假設你已經對該過程有了很多瞭解。

此外,我發現的每個文件都假定代碼需要在開發環境中從原始碼編譯。我不是開發人員。我是一個系統管理員,我們系統管理員有不同的需求,因為我們不需要或者我們不應該為了管理任務而去編譯代碼;我們應該使用 shell 腳本。所以我們沒有原始碼,因為它需要被編譯成二進制可執行檔案。我們擁有的原始碼也應該是可執行的。

在大多數情況下,此專案應作為非 root 用戶執行。 rpm 包永遠不應該由 root 用戶構建,而只能由非特權普通用戶構建。我將指出哪些部分應該以 root 身份執行,哪些部分應由非 root,非特權用戶執行。

準備

首先,打開一個終端會話,然後 su 到 root 用戶。 請務必使用 - 選項以確保啟用完整的 root 環境。 我不認為系統管理員應該使用 sudo 來執行任何管理任務。 在我的個人博客文章中可以找出為什麼:真正的系統管理員不要使用 sudo[3]

  1. [student@testvm1 ~]$ su -

  2. Password:

  3. [root@testvm1 ~]#

創建可用於此專案的普通用戶 student,併為該用戶設置密碼。

  1. [root@testvm1 ~]# useradd -c "Student User" student

  2. [root@testvm1 ~]# passwd student

  3. Changing password for user student.

  4. New password: <Enter the password>

  5. Retype new password: <Enter the password>

  6. passwd: all authentication tokens updated successfully.

  7. [root@testvm1 ~]#

構建 rpm 包需要 rpm-build 包,該包可能尚未安裝。 現在以 root 身份安裝它。 請註意,此命令還將安裝多個依賴項。 數量可能會有所不同,具體取決於主機上已安裝的軟體包; 它在我的測試虛擬機上總共安裝了 17 個軟體包,這是非常小的。

  1. dnf install -y rpm-build

除非另有明確指示,否則本專案的剩餘部分應以普通用戶用戶 student 來執行。 打開另一個終端會話並使用 su 切換到該用戶以執行其餘步驟。 使用以下命令從 GitHub 下載我準備好的開發目錄結構 utils.tar 這個tar 包tarball(LCTT 譯註:tarball 是以 tar 命令來打包和壓縮的檔案的統稱):

  1. wget https://github.com/opensourceway/how-to-rpm/raw/master/utils.tar

此 tar 包包含將由最終 rpm 程式安裝的所有檔案和 Bash 腳本。 還有一個完整的 spec 檔案,你可以使用它來構建 rpm。 我們將詳細介紹 spec 檔案的每個部分。

作為普通學生 student,使用你的家目錄作為當前工作目錄(pwd),解壓縮 tar 包。

  1. [student@testvm1 ~]$ cd ; tar -xvf utils.tar

使用 tree 命令驗證 ~/development 的目錄結構和包含的檔案,如下所示:

  1. [student@testvm1 ~]$ tree development/

  2. development/

  3. ├── license

  4.   ├── Copyright.and.GPL.Notice.txt

  5.   └── GPL_LICENSE.txt

  6. ├── scripts

  7.   ├── create_motd

  8.   ├── die

  9.   ├── mymotd

  10.   └── sysdata

  11. └── spec

  12.     └── utils.spec

  13. 3 directories, 7 files

  14. [student@testvm1 ~]$

mymotd 腳本創建一個發送到標準輸出的“當日訊息”資料流。 create_motd 腳本運行 mymotd 腳本並將輸出重定向到 /etc/motd 檔案。 此檔案用於向使用 SSH 遠程登錄的用戶顯示每日訊息。

die 腳本是我自己的腳本,它將 kill 命令包裝在一些代碼中,這些代碼可以找到與指定字串匹配的運行程式並將其終止。 它使用 kill -9 來確保 kill 命令一定會執行。

sysdata 腳本可以顯示有關計算機硬體,還有已安裝的 Linux 版本,所有已安裝的軟體包以及硬碟驅動器元資料等數萬行資料。 我用它來記錄某個時間點的主機狀態。 我以後可以用它作為參考。 我曾經這樣做是為了維護我為客戶安裝的主機記錄。

你可能需要將這些檔案和目錄的所有權更改為 student:student 。 如有必要,使用以下命令執行此操作:

  1. chown -R student:student development

此檔案樹中的大多數檔案和目錄將通過你在此專案期間創建的 rpm 包安裝在 Fedora 系統上。

創建構建目錄結構

rpmbuild 命令需要非常特定的目錄結構。 你必須自己創建此目錄結構,因為沒有提供自動方式。 在家目錄中創建以下目錄結構:

  1. ~ rpmbuild

  2.     ├── RPMS

  3.       └── noarch

  4.     ├── SOURCES

  5.     ├── SPECS

  6.     └── SRPMS

我們不會創建 rpmbuild/RPMS/X86_64 目錄,因為它是特定於體系結構編譯的 64 位二進制檔案。 我們有 shell 腳本,不是特定於體系結構的。 實際上,我們也不會使用 SRPMS 目錄,它將包含編譯器的源檔案。

檢查 spec 檔案

每個 spec 檔案都有許多部分,其中一些部分可能會被忽視或省略,取決於 rpm 構建的具體情況。 這個特定的 spec 檔案不是工作所需的最小檔案的示例,但它是一個包含不需要編譯的檔案的中等複雜 spec 檔案的很好例子。 如果需要編譯,它將在 %build 部分中執行,該部分在此 spec 檔案中省略掉了,因為它不是必需的。

前言

這是 spec 檔案中唯一沒有標簽的部分。 它包含運行命令 rpm -qi [Package Name] 時看到的大部分信息。 每個資料都是一行,由標簽和標簽值的文本資料組成。

  1. ###############################################################################

  2. # Spec file for utils

  3. ################################################################################

  4. # Configured to be built by user student or other non-root user

  5. ################################################################################

  6. #

  7. Summary: Utility scripts for testing RPM creation

  8. Name: utils

  9. Version: 1.0.0

  10. Release: 1

  11. License: GPL

  12. URL: http://www.both.org

  13. Group: System

  14. Packager: David Both

  15. Requires: bash

  16. Requires: screen

  17. Requires: mc

  18. Requires: dmidecode

  19. BuildRoot: ~/rpmbuild/

  20. # Build with the following syntax:

  21. # rpmbuild --target noarch -bb utils.spec

rpmbuild 程式會忽略註釋行。我總是喜歡在本節中添加註釋,其中包含創建包所需的 rpmbuild 命令的確切語法。

Summary 標簽是包的簡短描述。

NameVersion 和 Release 標簽用於創建 rpm 檔案的名稱,如 utils-1.00-1.rpm。通過增加發行版號碼和版本號,你可以創建 rpm 包去更新舊版本的。

License 標簽定義了發佈包的許可證。我總是使用 GPL 的一個變體。指定許可證對於澄清包中包含的軟體是開源的這一事實非常重要。這也是我將 License 和 GPL 陳述句包含在將要安裝的檔案中的原因。

URL 通常是專案或專案所有者的網頁。在這種情況下,它是我的個人網頁。

Group 標簽很有趣,通常用於 GUI 應用程式。 Group 標簽的值決定了應用程式選單中的哪一組圖標將包含此包中可執行檔案的圖標。與 Icon 標簽(我們此處未使用)一起使用時,Group 標簽允許在應用程式選單結構中添加用於啟動程式的圖標和所需信息。

Packager 標簽用於指定負責維護和創建包的人員或組織。

Requires 陳述句定義此 rpm 包的依賴項。每個都是包名。如果其中一個指定的軟體包不存在,DNF 安裝實用程式將嘗試在 /etc/yum.repos.d 中定義的某個已定義的儲存庫中找到它,如果存在則安裝它。如果 DNF 找不到一個或多個所需的包,它將丟擲一個錯誤,指出哪些包丟失並終止。

BuildRoot 行指定頂級目錄,rpmbuild 工具將在其中找到 spec 檔案,併在構建包時在其中創建臨時目錄。完成的包將儲存在我們之前指定的 noarch 子目錄中。

註釋顯示了構建此程式包的命令語法,包括定義了標的體系結構的 –target noarch 選項。因為這些是 Bash 腳本,所以它們與特定的 CPU 架構無關。如果省略此選項,則構建將選用正在執行構建的 CPU 的體系結構。

rpmbuild 程式可以針對許多不同的體系結構,並且使用 --target 選項允許我們在不同的體系結構主機上構建特定體系結構的包,其具有與執行構建的體系結構不同的體系結構。所以我可以在 x86_64 主機上構建一個用於 i686 架構的軟體包,反之亦然。

如果你有自己的網站,請將打包者的名稱更改為你自己的網站。

描述部分(%description

spec 檔案的 %description 部分包含 rpm 包的描述。 它可以很短,也可以包含許多信息。 我們的 %description 部分相當簡潔。

  1. %description

  2. A collection of utility scripts for testing RPM creation.

準備部分(%prep

%prep 部分是在構建過程中執行的第一個腳本。 在安裝程式包期間不會執行此腳本。

這個腳本只是一個 Bash shell 腳本。 它準備構建目錄,根據需要創建用於構建的目錄,並將相應的檔案複製到各自的目錄中。 這將包括作為構建的一部分的完整編譯所需的原始碼。

$RPM_BUILD_ROOT 目錄表示已安裝系統的根目錄。 在 $RPM_BUILD_ROOT 目錄中創建的目錄是真實檔案系統中的絕對路徑,例如 /user/local/share/utils/usr/local/bin 等。

對於我們的包,我們沒有預編譯源,因為我們的所有程式都是 Bash 腳本。 因此,我們只需將這些腳本和其他檔案複製到已安裝系統的目錄中。

  1. %prep

  2. ################################################################################

  3. # Create the build tree and copy the files from the development directories    #

  4. # into the build tree.                                                         #

  5. ################################################################################

  6. echo "BUILDROOT = $RPM_BUILD_ROOT"

  7. mkdir -p $RPM_BUILD_ROOT/usr/local/bin/

  8. mkdir -p $RPM_BUILD_ROOT/usr/local/share/utils

  9. cp /home/student/development/utils/scripts/* $RPM_BUILD_ROOT/usr/local/bin

  10. cp /home/student/development/utils/license/* $RPM_BUILD_ROOT/usr/local/share/utils

  11. cp /home/student/development/utils/spec/* $RPM_BUILD_ROOT/usr/local/share/utils

  12. exit

請註意,本節末尾的 exit 陳述句是必需的。

檔案部分(%files

spec 檔案的 %files 這一部分定義了要安裝的檔案及其在目錄樹中的位置。 它還指定了要安裝的每個檔案的檔案屬性(%attr)以及所有者和組所有者。 檔案權限和所有權是可選的,但我建議明確設置它們以消除這些屬性在安裝時不正確或不明確的任何可能性。 如果目錄尚不存在,則會在安裝期間根據需要創建目錄。

  1. %files

  2. %attr(0744, root, root) /usr/local/bin/*

  3. %attr(0644, root, root) /usr/local/share/utils/*

安裝前(%pre

在我們的實驗室專案的 spec 檔案中,此部分為空。 這應該放置那些需要 rpm 中的檔案安裝前執行的腳本。

安裝後(%post

spec 檔案的這一部分是另一個 Bash 腳本。 這個在檔案安裝後運行。 此部分幾乎可以是你需要或想要的任何內容,包括創建檔案、運行系統命令以及重新啟動服務以在進行配置更改後重新初始化它們。 我們的 rpm 包的 %post 腳本執行其中一些任務。

  1. %post

  2. ################################################################################

  3. # Set up MOTD scripts                                                          #

  4. ################################################################################

  5. cd /etc

  6. # Save the old MOTD if it exists

  7. if [ -e motd ]

  8. then

  9.    cp motd motd.orig

  10. fi

  11. # If not there already, Add link to create_motd to cron.daily

  12. cd /etc/cron.daily

  13. if [ ! -e create_motd ]

  14. then

  15.    ln -s /usr/local/bin/create_motd

  16. fi

  17. # create the MOTD for the first time

  18. /usr/local/bin/mymotd > /etc/motd

此腳本中包含的註釋應明確其用途。

卸載後(%postun

此部分包含將在卸載 rpm 軟體包後運行的腳本。 使用 rpm 或 dnf 刪除包會刪除檔案部分中列出的所有檔案,但它不會刪除安裝後部分創建的檔案或鏈接,因此我們需要在本節中處理。

此腳本通常由清理任務組成,只是清除以前由 rpm 安裝的檔案,但 rpm 本身無法完成清除。 對於我們的包,它包括刪除 %post 腳本創建的鏈接並恢復 motd 檔案的已儲存原件。

  1. %postun

  2. # remove installed files and links

  3. rm /etc/cron.daily/create_motd

  4. # Restore the original MOTD if it was backed up

  5. if [ -e /etc/motd.orig ]

  6. then

  7.    mv -f /etc/motd.orig /etc/motd

  8. fi

清理(%clean

這個 Bash 腳本在 rpm 構建過程之後開始清理。 下麵 %clean 部分中的兩行刪除了 rpm-build 命令創建的構建目錄。 在許多情況下,可能還需要額外的清理。

  1. %clean

  2. rm -rf $RPM_BUILD_ROOT/usr/local/bin

  3. rm -rf $RPM_BUILD_ROOT/usr/local/share/utils

變更日誌(%changelog

此可選的文本部分包含 rpm 及其包含的檔案的變更串列。最新的變更記錄在本部分頂部。

  1. %changelog

  2. * Wed Aug 29 2018 Your Name <Youremail@yourdomain.com>

  3.   - The original package includes several useful scripts. it is

  4.     primarily intended to be used to illustrate the process of

  5.     building an RPM.

使用你自己的姓名和電子郵件地址替換標題行中的資料。

構建 rpm

spec 檔案必須位於 rpmbuild 目錄樹的 SPECS 目錄中。 我發現最簡單的方法是創建一個指向該目錄中實際 spec 檔案的鏈接,以便可以在開發目錄中對其進行編輯,而無需將其複製到 SPECS 目錄。 將 SPECS 目錄設為當前工作目錄,然後創建鏈接。

  1. cd ~/rpmbuild/SPECS/

  2. ln -s ~/development/spec/utils.spec

運行以下命令以構建 rpm。 如果沒有錯誤發生,只需要花一點時間來創建 rpm。

  1. rpmbuild --target noarch -bb utils.spec

檢查 ~/rpmbuild/RPMS/noarch 目錄以驗證新的 rpm 是否存在。

  1. [student@testvm1 ~]$ cd rpmbuild/RPMS/noarch/

  2. [student@testvm1 noarch]$ ll

  3. total 24

  4. -rw-rw-r--. 1 student student 24364 Aug 30 10:00 utils-1.0.0-1.noarch.rpm

  5. [student@testvm1 noarch]$

測試 rpm

以 root 用戶身份安裝 rpm 以驗證它是否正確安裝並且檔案是否安裝在正確的目錄中。 rpm 的確切名稱將取決於你在前言部分中標簽的值,但如果你使用了示例中的值,則 rpm 名稱將如下麵的示例命令所示:

  1. [root@testvm1 ~]# cd /home/student/rpmbuild/RPMS/noarch/

  2. [root@testvm1 noarch]# ll

  3. total 24

  4. -rw-rw-r--. 1 student student 24364 Aug 30 10:00 utils-1.0.0-1.noarch.rpm

  5. [root@testvm1 noarch]# rpm -ivh utils-1.0.0-1.noarch.rpm

  6. Preparing...                          ################################# [100%]

  7. Updating / installing...

  8.    1:utils-1.0.0-1                    ################################# [100%]

檢查 /usr/local/bin 以確保新檔案存在。 你還應驗證是否已創建 /etc/cron.daily中的 create_motd 鏈接。

使用 rpm -q --changelog utils 命令查看更改日誌。 使用 rpm -ql utils 命令(在 ql 中為小寫 L )查看程式包安裝的檔案。

  1. [root@testvm1 noarch]# rpm -q --changelog utils

  2. * Wed Aug 29 2018 Your Name <Youremail@yourdomain.com>

  3. - The original package includes several useful scripts. it is

  4.     primarily intended to be used to illustrate the process of

  5.     building an RPM.

  6. [root@testvm1 noarch]# rpm -ql utils

  7. /usr/local/bin/create_motd

  8. /usr/local/bin/die

  9. /usr/local/bin/mymotd

  10. /usr/local/bin/sysdata

  11. /usr/local/share/utils/Copyright.and.GPL.Notice.txt

  12. /usr/local/share/utils/GPL_LICENSE.txt

  13. /usr/local/share/utils/utils.spec

  14. [root@testvm1 noarch]#

刪除包。

  1. rpm -e utils

試驗

現在,你將更改 spec 檔案以要求一個不存在的包。 這將模擬無法滿足的依賴關係。 在現有依賴行下立即添加以下行:

  1. Requires: badrequire

構建包並嘗試安裝它。 顯示什麼訊息?

我們使用 rpm 命令來安裝和刪除 utils 包。 嘗試使用 yum 或 dnf 安裝軟體包。 你必須與程式包位於同一目錄中,或指定程式包的完整路徑才能使其正常工作。

總結

在這篇對創建 rpm 包的基礎知識的概覽中,我們沒有涉及很多標簽和很多部分。 下麵列出的資源可以提供更多信息。 構建 rpm 包並不困難;你只需要正確的信息。 我希望這對你有所幫助——我花了幾個月的時間來自己解決問題。

我們沒有涵蓋原始碼構建,但如果你是開發人員,那麼從這一點開始應該是一個簡單的步驟。

創建 rpm 包是另一種成為懶惰系統管理員的好方法,可以節省時間和精力。 它提供了一種簡單的方法來分發和安裝那些我們作為系統管理員需要在許多主機上安裝的腳本和其他檔案。

資料

◈ Edward C. Baily,《Maximum RPM》,Sams 出版於 2000 年,ISBN 0-672-31105-4
◈ Edward C. Baily,《Maximum RPM[1]》,更新在線版本
◈ RPM 文件[4]:此網頁列出了 rpm 的大多數可用在線文件。 它包括許多其他網站的鏈接和有關 rpm 的信息。

via: https://opensource.com/article/18/9/how-build-rpm-packages

作者:David Both[6] 選題:lujun9972 譯者:Flowsnow 校對:wxy

本文由 LCTT 原創編譯,Linux中國 榮譽推出

赞(0)

分享創造快樂

© 2021 知識星球   网站地图