2. Linux制作deb包的方法

为了方便管理一些程序或脚本,可以将这些程序以及脚本都制作在一个deb包中, 本章节将介绍如何制作一个deb包, 制作deb的方式很多,如使用dpkg-deb方式、使用checkinstall方式、使用dh_make方式及修改原有的deb包, 本章将介绍如何从零制作一个自己的deb包,以及修改原有的deb包。

2.1. 什么是deb包?

deb包是在linux系统下的一种安装包,有时我们在网上下载的Linux软件安装包也会以deb包的形式出现, 由于它是基于tar包的,所以同样会记录着文件的权限信息(读、写、可执行)、所有者、用户组等。

我们可以使用命令:dpkg -l 来查看系统以及安装了哪些deb包。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
root@npi:/home/debian# dpkg -l
Desired=Unknown/Install/Remove/Purge/Hold
| Status=Not/Inst/Conf-files/Unpacked/halF-conf/Half-inst/trig-aWait/Trig-pend
|/ Err?=(none)/Reinst-required (Status,Err: uppercase=bad)
||/ Name                          Version                             Architectu
+++-=============================-===================================-==========
ii  adduser                       3.118                               all
ii  apt                           1.8.2.2                             armhf
ii  apt-transport-https           1.8.2.2                             all
ii  apt-utils                     1.8.2.2                             armhf
ii  avahi-daemon                  0.7-4+deb10u1                       armhf
ii  base-files                    10.3+deb10u9                        armhf
ii  base-passwd                   3.5.46                              armhf
ii  bash                          5.0-4                               armhf
ii  bind9-host                    1:9.11.5.P4+dfsg-5.1+deb10u3        armhf
ii  bsdmainutils                  11.1.2+b1                           armhf
ii  bsdutils                      1:2.33.1-0.1                        armhf
ii  busybox                       1:1.30.1-4                          armhf
ii  ca-certificates               20200601~deb10u2                    all
ii  connman                       1.36-2.1~deb10u1                    armhf
ii  coreutils                     8.30-3                              armhf
ii  cpio                          2.12+dfsg-9                         armhf
ii  cron                          3.0pl1-134+deb10u1                  armhf
ii  curl                          7.64.0-4+deb10u1                    armhf
lines 1-23

图中为野火linux开发板下所安装的deb包列表,Name所对应的列为已安装的deb包包名, Version表示该包的版本号,Architecture为该包所支持的处理器架构。

2.2. deb包的组成结构

deb包一般分成两部分:

  • 安装的内容,这部分类似linux的根目录,表示需要将软件安装到linux系统上的文件目录。

  • 控制信息(放在DEBIAN目录下),通常DEBIAN目录下有如下几个文件。

    • changelog: 文件记录了deb包的作者、版本以及最后一次更新日期等信息;

    • control: 文件记录了包名、版本号、架构、维护者及描述等信息;

    • copyright: 文件记录了一些版权信息;

    • postinst: 软件在进行正常目录文件拷贝到系统后需要执行的脚本。

    • postrm文件: 软件卸载后需要执行的脚本。

    其中control、postinst、postrm为必要文件。

2.3. 从零开始创建自己的deb包

安装工具及依赖:

sudo apt-get install build-essential debhelper make autoconf automake dpkg-dev fakeroot pbuilder gnupg

首先我们创建如下目录及文件

1
2
3
4
5
6
7
8
hello_deb/
├── DEBIAN
│   ├── control
│   ├── postinst
│   └── postrm
└── opt
   └── hello_deb
      └── hello_deb.sh

在hello_deb目录下创建DEBIAN及opt/hello_deb目录,DEBIAN目录下包含控制信息文件, 而在opt/hello_deb目录下创建hello_deb.sh文件则表示我们需要将hello_deb.sh文件安装到 linux系统的opt/hello_deb目录下。

然后分别给予postinst、postrm、hello_deb.sh文件以可执行权限。

其中control文件所包含信息如下:

hello_deb/DEBIAN/control
1
2
3
4
5
6
7
8
9
Package: hello-deb
Version: 1.0.0
Section: free
Priority: optional
Essential: no
Architecture: armhf
Maintainer: embedfire <embedfire@embedfire.com>
Provides: hell_deb
Description: deb test

若以后想升级这个deb包,可以修改该包的版本号Version,值得注意的是Architecture, 前面我们也有讲到,就是该deb包所支持的处理器架构, 因为最终要将该deb包安装到arm开发板上,而arm处理器架构为armhf, 所以我们应该在Architecture中填入armhf属性,大家可根据自己的需求做相应修改即可, 如果不知道你的处理器架可以通过dpkg -l命令来查看已安装的deb包持支的架构, 或者输入lscpu查看处理器信息,若想支持所有架构,可以填入all属性, 如果Architecture属性与当前处理器架构属性不匹配的话,deb包将无法成功安装, 且control的属性信息必须以字母或者数字开头,不然可能导致打包出错。

postinst文件包含信息如下:

hello_deb/DEBIAN/postinst
1
2
3
4
5
#!/bin/bash

if [ "$1" = "upgrade" ] || [ "$1" = "install" ];then
        echo "hello_deb installing"
fi

当安装了该deb包以后,系统会默认执行postinst脚本, 通常我们利用该脚本来搭建一些为软件执行的环境(如创建目录、修改权限等), 值得注意的是该文件需具有可执行权限。 这里写的比较简单,判断第一个参数,仅供参考。

postrm文件包含信息如下:

hello_deb/DEBIAN/postrm
1
2
3
4
5
6
7
8
#!/bin/bash

if [ "$1" = "upgrade" ] ; then
        echo "upgrade"
elif [ "$1" = "remove" ] || [ "$1" = "purge" ] ; then
        echo "remove"

fi

当卸载了该deb包以后,系统会默认执行postrm脚本,通常我们利用该脚本来清理环境, 值得注意的是该文件具有可执行权限。 这里写的比较简单,判断第一个参数,仅供参考。

最后我们来看下真正的程序主体,为了简单起见,此处以一个简单的脚本为例。

hello_deb/opt/hello_deb/hello_deb.sh
1
2
3
4
#! /bin/bash

echo Hello deb!
echo This is a test script!!!

脚本仅仅是打印两句信息,用户可自行设置需要执行的程序。

万事俱备,只欠东风,当备齐了制作deb包的基本原材料之后我们便可以开始制作属于自己的deb包了, 进入hello_deb目录下,也就是DEBIAN及home文件夹所在的目录,接着输入如下命令来构建软件包。

sudo dpkg-deb -b ../hello_deb ../hello_deb_1.0.0_armhf.deb

其中dpkg-deb是构建deb包命令,-b参数表示要构建一个deb包, ../hello_deb参数表示要构建deb包原材料的路径, ../hello_deb_1.0.0_armhf.deb参数表示将该deb包构建在当前目录的上级目录中, 一般我们构建deb包的名字都会遵循这么一个原则, 其命名方式为:软件名称+软件版本号+该软件所支持的处理器架构, 如软件名为hello_deb,版本号为1.0.0,所支持的处理器架构为armhf。

打包成功后会输出如下信息,并可在上级目录查看到deb安装包:

1
2
3
4
5
qinghui@ebf-dev:~/deb/hello_deb$ sudo dpkg-deb -b ../hello_deb ../hello_deb_1.0.0_armhf.deb
dpkg-deb: 正在 '../hello_deb_1.0.0_armhf.deb' 中构建软件包 'hello-deb'。
qinghui@ebf-dev:~/deb/hello_deb$ ls ..
hello_deb  hello_deb_1.0.0_armhf.deb
qinghui@ebf-dev:~/deb/hello_deb$

制作好自己的deb包后我们需要验证一下是否真的制作成功, 可以如下命令查看已制作的deb包文件内容:

1
2
3
4
5
6
7
8
#命令
dpkg -c  hello_deb_1.0.0_armhf.deb

#打印信息
drwxrwxr-x qinghui/qinghui   0 2021-04-15 11:16 ./
drwxrwxr-x qinghui/qinghui   0 2021-04-15 11:16 ./opt/
drwxrwxr-x qinghui/qinghui   0 2021-04-15 11:22 ./opt/hello_deb/
-rwxrwxr-x qinghui/qinghui  65 2021-04-15 11:22 ./opt/hello_deb/hello_deb.sh

也可使用如下命令查看deb包信息:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
#命令
dpkg --info  hello_deb_1.0.0_armhf.deb

#打印信息
new Debian package, version 2.0.
size 976 bytes: control archive=500 bytes.
   190 字节,    9 行      control
   100 字节,    7 行   *  postinst             #!/bin/bash
   133 字节,    8 行   *  postrm               #!/bin/bash
Package: hello-deb
Version: 1.0.0
Section: free
Priority: optional
Essential: no
Architecture: armhf
Maintainer: embedfire <embedfire@embedfire.com>
Provides: hell_deb
Description: deb test

将该deb包拷贝到linux开发板的文件系统下, 输入“sudo dpkg -i hello_deb_1.0.0_armhf.deb”命令即可安装, 其中-i 参数表示安装软件,即install, 并且在安装完软件之后可以输入“dpkg -s hello-dev”命令查看是否安装了软件。 如下所示

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
root@npi:/home/debian# sudo  dpkg -i hello_deb_1.0.0_armhf.deb
Selecting previously unselected package hello-deb.
(Reading database ... 12164 files and directories currently installed.)
Preparing to unpack hello_deb_1.0.0_armhf.deb ...
Unpacking hello-deb (1.0.0) ...
Setting up hello-deb (1.0.0) ...
root@npi:/home/debian# dpkg -s hello-deb
Package: hello-deb
Status: install ok installed
Priority: optional
Section: free
Maintainer: embedfire <embedfire@embedfire.com>
Architecture: armhf
Version: 1.0.0
Provides: hell_deb
Description: deb test

或者输入“dpkg -l | grep hello-deb”命令查看你的软件是否在已安装软件列表里面。

1
2
root@npi:/home/debian# dpkg -l | grep hello-deb
ii  hello-deb                     1.0.0                               armhf        deb test

验证安装完成之后查看开发板/opt/hello_deb目录下是否存在hello_deb.sh文件。

1
2
3
4
root@npi:/home/debian# ls /opt/
backup  hello_deb  scripts  source
root@npi:/home/debian# ls /opt/hello_deb/
hello_deb.sh

执行看看效果

1
2
3
root@npi:/home/debian# /opt/hello_deb/hello_deb.sh
Hello deb!
This is a test script!!!

到此,制作deb包的基本流程已介绍完毕。

2.4. 从根据已有deb包修改内容

下面介绍下如何修改已有的deb包,以刚刚创建的deb包为例。

在已有的deb包目录下新建一个update_deb目录,使用 dpkg -X 命令对deb包进行解压。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
qinghui@ebf-dev:~/deb$ ls
hello_deb  hello_deb_1.0.0_armhf.deb
qinghui@ebf-dev:~/deb$ mkdir update_deb
qinghui@ebf-dev:~/deb$ ls
update_deb  hello_deb  hello_deb_1.0.0_armhf.deb
qinghui@ebf-dev:~/deb$ dpkg -X  hello_deb_1.0.0_armhf.deb  update_deb/
./
./opt/
./opt/hello_deb/
./opt/hello_deb/hello_deb.sh

进入update_deb目录下可看到并没DEBIAN相关目录,在update_deb目录下使用 dpkg -e 解压出 控制相关信息。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
qinghui@ebf-dev:~/deb/update_deb$ ls
opt
qinghui@ebf-dev:~/deb/update_deb$ dpkg -e  ../hello_deb_1.0.0_armhf.deb
qinghui@ebf-dev:~/deb/update_deb$ ls
DEBIAN  opt
qinghui@ebf-dev:~/deb/update_deb$ tree
.
├── DEBIAN
│   ├── control
│   ├── postinst
│   └── postrm
└── opt
    └── hello_deb
        └── hello_deb.sh

3 directories, 4 files
qinghui@ebf-dev:~/deb/update_deb$

此时就可以对程序主体进行修改了,我们在opt/hello_deb/hello_deb.sh下添加一句打印消息, 如下所示

update_deb/opt/hello_deb/hello_deb.sh
1
2
3
4
5
#! /bin/bash

echo Hello deb!
echo This is a test script!!!
echo update deb!

修改DEBIAN/control下的版本信息,修改如下

update_deb/DEBIAN/control
1
2
3
4
5
6
7
8
9
Package: hello-deb
Version: 1.0.1
Section: free
Priority: optional
Essential: no
Architecture: armhf
Maintainer: embedfire <embedfire@embedfire.com>
Provides: hell_deb
Description: deb test

此时便可以重新打包应用程序了。

1
2
qinghui@ebf-dev:~/deb/update_deb$ sudo dpkg-deb -b ../update_deb ../hello_deb_1.0.1_armhf.deb
dpkg-deb: 正在 '../hello_deb_1.0.1_armhf.deb' 中构建软件包 'hello-deb'

2.5. 简单实例:通过安装deb包创建开机自启服务

通过安装deb包在野火开发板上实现程序开机自启,在实际项目上的应用极为普遍, 不少的用户经常有这方面的困扰,下面通过一个简单的实例介绍相关如何使用创建开机自动的deb程序。

创建一个新的deb包目录,文件结构如下

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
hello_deb
├── DEBIAN
│   ├── control
│   ├── postinst
│   └── postrm
├── etc
│   └── systemd
│       └── system
│           └── hello.service
└── opt
    └── hello_deb
        └── hello_deb.sh

其中 /etc/systemd/system/hello.service 为自启服务, /opt/hello_deb/hello_deb.sh 为程序主体。 DEBIAN目录为deb包的一些描述信息以及安装卸载执行脚本等,对于一些基本概念此处便不再赘述, 直接查看各个文件中的内容。

DEBIAN/control文件内容如下所示

DEBIAN/control
1
2
3
4
5
6
7
8
9
Package: hello-deb
Version: 1.0.0
Section: free
Priority: optional
Essential: no
Architecture: armhf
Maintainer: embedfire <embedfire@embedfire.com>
Provides: hell_deb
Description: deb test

DEBIAN/postinst文件内容如下所示,脚本的内容很简单只是使能了hello相关服务并启动它。

DEBIAN/postinst
1
2
3
4
5
6
echo "......................................................"
echo "..............hello_deb installing...................."
echo "......................................................"

systemctl enable hello
systemctl start hello

DEBIAN/postinst文件内容如下所示,当卸载程序时,关闭hello相关服务。

DEBIAN/postrm
1
2
3
4
5
6
if [ "$1" = "upgrade" ] ; then
   echo "upgrade"
elif [ "$1" = "remove" ] || [ "$1" = "purge" ] ; then
   echo "remove"
   systemctl disable hello
fi

/etc/systemd/system/hello.service服务内容如下,重点在于第六行,指定需要执行的程序。

/etc/systemd/system/hello.service
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
[Unit]

Description = hello daemon

[Service]
ExecStart = /opt/hello_deb/hello_deb.sh
Restart = always
Type = simple

[Install]
WantedBy = multi-user.target

/opt/hello_deb/hello_deb.sh为程序主体,内容如下所示,以每3秒的速度向/tmp/hello.log 写入Hello Embedfire。

/opt/hello_deb/hello_deb.sh
1
2
3
4
5
6
7
#!/bin/bash

while true
do
     echo Hello Embedfire >> /tmp/hello.log
     sleep 3
done

将以上目录打包构建成deb文件并在板子上使用dpkg命令安装即可。 重启后使用``systemctl status hello`` 查看服务相关状态如下。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
root@npi:~# systemctl status hello
● hello.service - hello daemon
   Loaded: loaded (/etc/systemd/system/hello.service; enabled; vendor preset: en
   Active: active (running) since Mon 2021-05-31 15:52:32 CST; 56s ago
Main PID: 340 (hello_deb.sh)
   Tasks: 2 (limit: 385)
   Memory: 408.0K
   CGroup: /system.slice/hello.service
         ├─340 /bin/bash /opt/hello_deb/hello_deb.sh
         └─503 sleep 3

May 31 15:52:32 npi systemd[1]: Started hello daemon.

也可通过查看/tmp/hello.log文件查看程序是否正确执行。