Today I will tell on an abstract example how to
properly create a * .deb package for Ubuntu / Debian. We will make the binary package. Packages that compile binaries from source codes are not considered here: after you have mastered the knowledge outlined below, you can understand the essence and use similar examples in the future using ready-made examples :)
The article will not have any unnecessary fuss "manually": the package format has evolved into a fairly simple, and most importantly, a logical structure, and everything is done literally on the knee, using a couple of specialized utilities.
As a bonus, at the end of the article there will be an example of quickly creating your own local repository: installing packages from the repository allows you to automatically track dependencies, and of course! - install everything with one console command on several machines :)
')
For those who do not want to go into the powerful software installation system in Linux, I recommend visiting
the CheckInstall program site : it automatically creates a deb-package from the âmake installâ command;) And we, along with the curious, -
Sources
Information is trusted from many places, but here are two main ones:
The article details the basics of creating packages that are sufficient to obtain sufficiently powerful application installation management. More advanced features are omitted, but direct links to documentation for those interested are suggested.
The article is not a copy or a translation of any documentation: it is a collection of knowledge, lying in the form of notes, and now decorated in the form of an article. For clarity, there are examples everywhere, explanations on the fingers, convenient features I found and some typical mistakes that can be made out of ignorance.
Training
Why is this all about?
Yes, CheckInstall can create a work package, but it does not support all the goodies that deb packages are capable of :) Namely:
- Scripts running before, after
and instead of installing the package :) - Automatic configuration files management: the package will not allow to wipe the old configs without new ones
- Working with templates: the ability to ask the user questions during installation (!!!)
- Modify files of other packages
What is required
Of course, tar, gz, ar archivers will be enough to create a full-fledged package, but you can eliminate the extra fuss, and use the tools created to make life easier :)
We put:
$ sudo apt-get install dpkg debconf debhelper lintian
What do we do
For example, a certain script /usr/bin/super.sh will be considered. It doesn't matter what's inside, the main thing is how it will appear on the right place :)
Folder preparation
In the home directory (or where convenient) create a folder in which all files of the future package will be located:
mkdir ~/supersh
. Further we will call its
package root .
At the root of the package create a folder "DEBIAN" (in capital letters, this is important!). This folder contains package generation control information, and is not copied to disk when the package is installed.
Also, the root folder of the package contains the future âroot of the diskâ: when installing the package, all files (except the âdebianâ folder) are unpacked into the root /. Therefore, our script should follow this path relative to the package root: âusr / bin / super.shâ
White on black:
mkdir -p ~/supersh/DEBIAN #
mkdir -p ~/supersh/usr/bin #
cp super.sh ~/supersh/usr/bin/ #
As a result, we have:
supersh/DEBIAN/
supersh/usr/
supersh/usr/bin/
supersh/usr/bin/super.sh
Build Package: DEBIAN / *
As I said, the DEBIAN folder contains files used during installation. Here I will describe (with examples) each file.
To create a full-fledged package, the control file âcontrolâ is sufficient; all the others are used either to attach textual information (changelog, license), or to manage advanced application installation features.
From the files described below in the folder DEBIAN / * we select the necessary ones and fill in according to the instructions :)
In our example, only
mandatory DEBIAN / control is really used.
DEBIAN / control: Basic Information
control is the central package file that describes all the basic properties. The file is a text file consisting of âAttribute: Valueâ pairs. You can use comments: the "#" symbol at the beginning of the line (the feature was added in the dpkg version> = 1.10.11, you should not hope for comments :).
The table shows all the fields defined for the control file. Required fields are
in bold : without them, the package will not be considered as composed correctly.
Attribute | Description | Examples |
---|
- basic - |
---|
Package: | Package Name: [a-zA-Z0-9-] - only Latin, numbers, and hyphen. The name is used during installation: apt-get install <package> | Package: supersh |
Version: | Version of the package (and the program inside). Used to determine whether to update. The format is as follows: <_>-<_> . I recommend to always indicate the version of the package: when changing the structure of the package, the figure is increased by one. Valid characters are quite voluntary: you can use the date and letters. See examples in your repository today :) | Version: 1.0-1<br>Version: 2009.12.12-1 |
Provides | The application name (possibly virtual) registered in the system as a result of the installation of this package. Rarely used: mainly if you need to change the name of the package, or if more than one package offers the same functionality. For example, the Apache and nginx packages provide the httpd: Provides: httpd daemon feature You probably encountered an error when trying to install: "is a virtual package". This is it :) | Provides: supersh |
Maintainer | The name and mail of the package maintainer: the person who âdebianizedâ the application. The format is arbitrary, but the <e-mail> accepted <e-mail> | Maintainer: o_O Tync <oo-tync.habrahabr.ru> |
Architecture | The processor architecture for which the package is intended. Valid values: i386, amd64, all, source
all used for scripts: they are portable, right? :)
source used for compiled source packages. | Architecture: all |
Section | Specifies the task for which the application is typically used (group of applications). Possible values: admin, base, comm, contrib, devel, doc, editors, electronics, embedded, games, gnome, graphics, hamradio, interpreters, kde, libs, libdevel, mail, math, misc, net, news, non-free , oldlibs, otherosfs, perl, python, science, shells, sound, tex, text, utils, web, x11 | Section: misc |
Description | Description of the package. The description consists of two parts: a short description (70 characters) on the same line, and a long description on subsequent lines, starting with a space . In the extended description, all line breaks are ignored. A single point is used to insert \ n. | Description: Short.<br>âŁLong <br>âŁgoes here.<br>âŁ.<br>âŁNew line. |
- connections and dependencies - |
---|
Depends | A comma-separated list of packages that are required to install this package. After the package name, you can indicate the limit on the version in parentheses using the operators: <<, =, >>, <=,> =. If the operator is not specified, it is used> = | Depends: dpkg, libz (>= 1.2.3), jpeg (= 6b), png (< 2.0) |
Pre-depends | List of packages that are required during the installation of this package. These dependencies may be required for package installation scripts: for example, the flash-installer package requires wget Version restrictions can be used (see Depends). | Pre-Depends: wget (>= 1.0) |
Conflicts | List of packages that cannot be installed at the same time. Installation will fail if at least one of the listed packages is already installed. | Conflicts: crapscript |
Replaces | The list of packages whose files are modified by this package. Required if you create a âpatch packageâ that changes something: otherwise, when replacing files of someone else's package, an error will occur during installation. For example, I have such a package of patch UT2004 and removes the sound of the proposed rocket launcher :) | Replaces: ut2004 |
Recommends | List of recommended packages for installation These packages are optional, but are usually used with current | Recommends: superplatform |
Suggests | List of packages offered for installation. These packages are not required, but with them the program works even better :) In theory, the package manager should offer to install them. | Suggests: supersh-modules |
Build-depends | (For Architecture: source only) List of packages required to compile the source. Same as Depends, but logically separated. | Build-Depends: cmake |
- extra - |
---|
Installed-Size | The size of the package files in kilobytes. Just a figure, rounded to the nearest integer. Used by the package manager to determine the total required disk space. | Installed-Size: 3 |
Priority | Package priority: how important is it in the system? Possible values: extra, optional, standard, important, required (such packages are not removed at all!). | Priority: optional |
Esssential | If you set this attribute to âyesâ, the package cannot be deleted. | Esssential: yes |
Origin | Line: from where the programs are received in the package. Usually the authorâs site URL, mail or name is used. | Origin: brain |
X-source | Full link to * .tar.gz archive with sources | X-Source: ...*.tgz |
Yes, these are the solid features of the control file :)
And in our example, it looks like this:
Package: supersh
Version: 1.0-1
Section: misc
Architecture: all
Depends: bash, sed (>= 3.02-8)
Maintainer: o_O Tync <oo-tync.habrahabr.ru>
Description: Super Shell Script
âŁA super example script.
âŁ.
âŁIt does nothing :)
DEBIAN / copyright: Š / license
The text of the license. The file is not required, but it is better to underline your authorship;)
DEBIAN / changelog: change history
Changelog in a special format: use dpkg to get the version number, revision, distribution and importance of the package. It is better to look in the
official documentation ;) and I will only give an example:
supersh (1.0-1) stable; urgency=medium
* Testing.
-- o_O Tync <oo-tync.habrahabr.ru> Sun, 13 Dec 2009 00:11:46 +0300
DEBIAN / rules: compilation rules
Used to manage package compilation: this is when
Architeture: source
:)
See the
official documentation.DEBIAN / conffiles: list of configuration files
Usually packages contain clumps of configuration files, for example, placed in / etc. Obviously, if the config in the package is updated, the user will lose his edited config. This problem is easily solved by using folders of the âconfig.dâ type, the contents of which are included in the main config, replacing the recurring options.
The file "DEBIAN / conffiles" allows you to solve the problem differently: it contains a list of configuration files (one per line). If in the current version of the package one of these files is updated, the user receives a warning about the conflict of versions of configs, and can choose: delete, replace, or make a merge.
Every linuxid who has been digging into configs probably came across this situation :) And his legs are growing from here.
On each line there should be a full absolute path to each config. For example:
/etc/supersh/init.conf
/etc/supersh/actions.conf
DEBIAN / dirs: a list of folders to create
âThe list of absolute paths to folders that are required by the program, but for some reason are not created.â Says the official documentation. In practice, all the folders used by the program are listed here: where the binaries lie and which are used by the program.
One per line. For example:
/var/log/supersh
/var/lib/supersh
Convenient to use to create multiple empty folders.
DEBIAN / menu: creating menu items
Tricky file to create menu items. It did not work for me :) It seems that its contents are used either in unusual window managers, or in some kind of console menu ... or it was used before and was forgotten :)
Example:
?package(supersh):needs="text" section="Applications/Programming" title="Super Shell Script" command="/usr/bin/super.sh"
TODO: find out why. This is written in the
man5 menufile
, to be honest, I did not penetrate :)
UPD: The correct way to add a menu item
The file / DEBIAN / menu creates an unknown and itâs not clear where: the graphic menu items are still not created. Therefore, we will do right :)
In
/usr/share/applications
we see a bunch of
*.desktop
files: these are menu items. They are text files with syntax like an ini file. We open, learn, do the same and put the resulting
*.desktop
file into
usr/share/applications/
. The icon for it should be in
usr/share/pixmaps
.
After that, in the postinst script you need to add the execution of the update menu command:
if [ "$1" = "configure" ] && [ -x "`which update-menus 2>/dev/null`" ] ; then
update-menus
fi
The work with package installation scripts will be discussed below.
Thanks to
Condorious for the tip :)
DEBIAN / md5sums: file checksums
Used to verify the integrity of the package. Important file.
It is filled like this (cwd = package root):
$ md5deep -r usr > DEBIAN/md5sums
DEBIAN / watch: monitoring the site where the program was downloaded from
The function is useful if you are a maintenite from several dozen packages, and it is difficult to keep track of all the updates.
The file contains instructions for uscan and uupdate. Using this feature, you can monitor the site from which the source package was obtained, and ensure quality control of the distribution in general.
Example:
# Site Directory Pattern Version Script
ftp.obsession.se /gentoo gentoo-(.*)\.tar\.gz debian uupdate
And another example for uscan (1):
version=3
madwimax.googlecode.com/files/madwimax-(.*)\.tar\.gz
Better read the
official documentation , such powerful things are infrequently required by mere mortals :)
DEBIAN / cron.d: install cron jobs
The file contains a piece of crontab for installation. An example explains everything:
#
# Launches super.sh periodically
#
0 4 * * * root [ -x /usr/bin/super.sh ] && usr/bin/super.sh
DEBIAN / inid.d: init-script
The contents of the init-script are written to this file. About writing init scripts in the internet can be found
Scripting
We come to the most interesting part: embedding scripts in deb packages. Scripts allow you to manage the installation, reinstallation and removal of a package by performing actions that cannot be done by simply copying files to the right places. This may be downloading additional files (as flash-installer does), modifying existing ones, and also displaying interactive (GUI or ncurses) dialogs that allow the user to configure the package for himself: for example, mysql asks which password to set to root.
All scripts are executed from the root user (and how else :). They also receive arguments (which are optional to process), specifying at what stage the installation is located. Read more about it
here .
DEBIAN / (preinst | postinst | prerm | postrm): installation scripts
In total, you can create up to four scripts in one package:
Script | Purpose |
---|
DEBIAN / preinst | Runs before installing the package: it can prepare something for a successful installation. |
---|
DEBIAN / postinst | It is executed immediately after installing the package: it configures the installed package so that it is ready for operation. It also runs the interactive configuration of the package: this is done using dh_input and the DEBIAN / templates file |
---|
DEBIAN / prerm | It is executed immediately before removing the package: usually this script cleans up the installation paths of the package so that nothing extra is left over :) |
---|
DEBIAN / postrm | Runs immediately after removing a package: cleans up leftovers |
---|
Please note that errors that occur in these scripts
are not logged in any way : nothing more interesting than the script's return code is not saved anywhere, and logging must be done manually! Users of one of my packages failed to install on Linux Mint, and it was not even possible to ask them for a log of errors (which is not present) in order to find out the reason :)
I recommend using the following disc at the beginning of each script: it will save any errors that occur in the syslog.
#!/bin/bash
set -e # fail on any error
set -u # treat unset variables as errors
# ======[ Trap Errors ]======#
set -E # let shell functions inherit ERR trap
# Trap non-normal exit signals:
# 1/HUP, 2/INT, 3/QUIT, 15/TERM, ERR
trap err_handler 1 2 3 15 ERR
function err_handler {
local exit_status=${1:-$?}
logger -s -p "syslog.err" -t "ootync.deb" "supersh.deb script '$0' error code $exit_status (line $BASH_LINENO: '$BASH_COMMAND')"
exit $exit_status
}
... ...
exit 0
WARNING: the disc has not been tested extensively yet, check it out once more! I came across the impossibility of debugging recently :)
DEBIAN / templates: templates for dialogs
As already mentioned, in the DEBIAN / config script, you can ask the user questions: enter a line, select one of the options, tick, ... This is the âlibraryâ bash of the debhelper functions of the debconf package, which also knows a lot of useful things. I donât consider them here :)
The DEBIAN / templates file contains the data used when displaying dialog boxes (GUI or ncurses). The file contains blocks separated by an empty line. Each block defines the resources used in one particular dialog box.
The cap for all types of dialog is standard:
Template: supersh/template-name
Type: string
Default: Default-value
Description: Dialog-title
âŁDialog-text
Template - unique (within one package) template identifier. If a script needs to call a specific dialog, this is the name that is used.
Type - the type of template. The following types are defined: string, password, boolean, select, multiselect, text, note, error.
Default-value is the default value: the user can simply accept it.
Description - as in the control file, consists of two fields: a short description, and a long text. The first is the âwindowâ title, the second is a more detailed description of what is required of the user. It is recommended not to use words like âenterâ, but immediately the essence: âGreeting the scriptâ, âMount pointâ, ...
Type of | Template Description |
---|
string | Invitation to enter a text string |
---|
password | Password prompt There is no Default value for this template type for obvious reasons :) |
---|
boolean | Tick ââ:) Has a string value of "true" or "false" |
---|
select | Ability to select one of several options. Options are offered in an additional attribute of the template:
Choices: yes, no, maybe |
---|
multiselect | Ability to select multiple options tick. Options are offered in an additional attribute of the template:
Choices: sex, drugs, rock-n-roll |
---|
text | Displays text: some not-so-important information. |
---|
note | Displays text: important information |
---|
error | Displays the text: very important information, critical. |
---|
For text, note, error templates there is also no Default value, since they only display information :)
Let's play with the following template:
Template: supersh/greeting
Type: string
Description: Welcome message
âŁThe message you wish the script to welcome you with.
Default: Greetings, my master!
Basics of using debconf and debhelper
These are only workable sketches. In the original, read about templates and working with them here:
man 7 debconf-devel
:)
To use templates in your DEBIAN / config configuration script, you must first enable the debhelper functions:
. /usr/share/debconf/confmodule
. /usr/share/debconf/confmodule
. Also, this file must be included in the postinst script: otherwise the DEBIAN / config script will not run at all!
These features are available in the debconf package; don't forget to enable it depending!
Primitive use case. DEBIAN / config file
#!/bin/bash -e
# debconf
. /usr/share/debconf/confmodule
case "$1" in
configure|reconfigure)
#
db_input medium "supersh/greeting" || true #
db_go || true #
#
db_get "supersh/greeting" # $RET
greeting="$RET"
echo "$greeting" > /etc/supersh/greeting.txt
;;
*)
echo "config called with unknown argument \`$1'" >&2
exit 1
;;
esac
#
db_input medium "supersh/greeting" || true #
db_go || true #
#
db_get "supersh/greeting" # $RET
greeting="$RET"
echo "$greeting" > /etc/supersh/greeting.txt
There is already an unpleasant ambush: note that the dialogue priority of the medium is transferred to the db_input function. For debconf, you can set a minimum priority: dialogs with a priority below which are not displayed, but the default value (template default) is taken! To prevent this EXACTLY from happening - we use the priority of critical :) In addition, when installing from the GUI, the threshold for displaying questions is higher, and many of them are not displayed at all.
Possible priorities: low - always use default, medium - default is usually quite suitable, high - default is undesirable, critical - user's attention is vital.
|| true
|| true
used to prevent the script from dying due to the "-e" key sent by bash.
In this script, it is also recommended to use that disc for catching errors, otherwise debugging problems may occur with the distributed package :)
All the subtleties of using debconf (functions, methods, parameters, error codes) are described in a rather verbose manner:
man debconf-devel
.
One last thing: when removing a package with the purge command, debconf should also clear the package information from its database. For example, it saves user selection when db_input requests.
To clear this data, add the following to the postinst script:
if [ "$1" == "purge" ] && [ -e /usr/share/debconf/confmodule ] ; then
. /usr/share/debconf/confmodule
db_purge
fi
Putting the package! :)
Hooray! All the necessary files are created, are on the right daddy. Now it's time to pack :)
The first thing to do is to recursively set all the files in the root of the user's package and the root group: root (or others if necessary). It is necessary then that the package files are packed into a tar.gz archive which preserves both the rights of access to the files and the owner. Because you need to perform:
$ sudo chown -R root:root .
However, this is not necessary. There is a great fakeroot command that, when creating an archive, will replace the owner of files with root.
In our example, the script should have a doable bit.
Then we go back to the folder so that the root folder of the package can be seen, and the package is created with a
light kick by itself:
$ fakeroot dpkg-deb --build supersh
The created package must be renamed to correspond to the naming order of * .deb packages: <package name> _ <version> _ <architecture> .deb
$ mv supersh.deb supersh_1.0-1_all.deb
Everything, the package is ready!
Automatic package check
There is a lintian utility that allows you to check a package and identify common errors in its structure. This is done like this:
$ lintian supersh_1.0-1_all.deb
Package installation
$ sudo dpkg -i supersh_1.0-1_all.deb
Create your own package repository
Now we have our own package. When there are several, and even more so with dependencies, it turns out that it is much more convenient to quickly raise your own local micro-repository, and include it in the list of package manager sources :) Here I will describe the quick HowTo âhow to create your repositoryâ. The idea will be easy to develop by reading the relevant documentation :)
First install the assistant:
$ sudo apt-get install reprepro
Description of the future repository
Center repository - its description. The main thing in it is the list of repository components. We will create soft and games components.
Select a folder for the future repository. All actions are made from its root.
Create a conf / distributions file with the following content:
Description: my local repository
Origin: Ubuntu
Suite: testing
AlsoAcceptFor: unstable experimental
Codename: karmic
Version: 5.0
Architectures: i386 amd64 source
Components: soft games
UDebComponents: soft games
In our business of creating a simple repository, all fields do not play a fundamental role, and are used only for the visual definition of "what is what" :)
Creating a repository
The repository is described! Now we will generate a blank based on the description. Commands are executed in the repository root:
$ reprepro export
$ reprepro createsymlinks
And add the ready repository to /etc/apt/sources.list:
deb file:///path/to/repo/ karmic soft games
This repository can also be shared using a web server.
Package Management in the repository
Put in the root of the repository * .deb files to add, and add them to the soft component of the karmic distribution:
reprepro -C soft includedeb karmic *.deb
Now packages are available from the package manager :)
Removing packages:
reprepro -C soft remove karmic supersh
The finish
The article describes the materials for creating deb packages.
Emphasis is placed on moments for which the network does not have a sufficiently clear description. I hope that my attempt to explain simply and clearly did not fail :)Homework :)) - quite well documented things that are easy to find in man's and articles:- Creating source packages that compile source files: using the example of Zabbix, the mabrao habrauzer told about it perfectly in his article
- Debconf, debhelper in configuration scripts: read mana by debconf-devel and debhelper. They also allow you to create a skeleton package with the dh_make command.
- Advanced ways to create documentation in packages: DEBIAN / docs, DEBIAN / manpage. * Files
- Creating init scripts
- Cron job management
- Signing the repository with gpg key
UPD: @ ICD2 tells you that there is a GUI program for creating packages: GiftWrap .Cheers! :)
PS The article probably contains inaccuracies and errors. Let's comb it together! :)