为什么“dpkg --instdir=dir/ -i xxx.deb”也将管理目录设置为“dir”,就像“--root=ddd”选项一样?

为什么“dpkg --instdir=dir/ -i xxx.deb”也将管理目录设置为“dir”,就像“--root=ddd”选项一样?

我使用的是 Ubuntu 22.04.3 LTS。我创建了一个名为 的文件helloworld.deb,其源文件结构如下:

helloworld
├── DEBIAN
│   └── control
└── usr
    └── games
        └── mygame.sh

我曾经dpkg-deb --build helloworld制作过这个helloworld.deb文件。然后我把sudo dpkg --instdir=phonyRoot -i helloworld.deb它安装在一个名为的文件夹中phonyRoot

我执行tree phonyRoot并得到以下内容:

phonyRoot
├── usr
│   └── games
│       └── mygame.sh
└── var
    └── lib
        └── dpkg
            ├── info
            │   ├── format
            │   ├── helloworld.list
            │   └── helloworld.md5sums
            ├── lock
            ├── lock-frontend
            ├── status
            ├── status-old
            ├── triggers
            │   ├── Lock
            │   └── Unincorp
            └── updates

8 directories, 10 files

然后我执行了dpkg -l | grep helloworld,但无法获取有关刚刚安装的包的任何信息。

如上所示,--instdir=phonyRoot还将管理目录更改为phonyRoot文件夹。似乎该选项--admindir=dir也是在后台添加的。根据手册,这与选项的行为相同--root=dir

为什么的行为--instdir=dir和手册里的描述不符呢?

答案1

简单来说

版本之前的 DPKG(随 Ubuntu 23.10 一起提供)似乎存在一个问题1.22.0,可以通过DPKG_ADMINDIR在命令行上明确设置环境变量来解决,如下所示:

sudo DPKG_ADMINDIR="/var/lib/dpkg" dpkg --instdir=...

详细

--instdir,实际上,它本身似乎并没有做到这一点...请看下面的演示:

$tree myapp/
myapp/
├── DEBIAN
│   ├── control
│   └── install
└── usr
    └── bin
        └── myap

4 directories, 3 files
$
$
$tree dir
dir

0 directories, 0 files
$
$
$head myapp/{DEBIAN,usr/bin}/*
==> myapp/DEBIAN/control <==
Package: myapp
Version: 0.01
Architecture: all
Maintainer: my contact
Section: extras
Priority: optional
Homepage: my homepage
Description: myapp description

==> myapp/DEBIAN/install <==
myapp usr/bin/

==> myapp/usr/bin/myap <==
#!/bin/bash

printf '%s\n' {1..9}
$
$
$dpkg --version
Debian 'dpkg' package management program version 1.22.0 (amd64).
This is free software; see the GNU General Public License version 2 or
later for copying conditions. There is NO warranty.
$
$
$dpkg -b myapp/
dpkg-deb: building package 'myapp' in 'myapp.deb'.
$
$
$sudo dpkg --instdir=dir -i myapp.deb 
Selecting previously unselected package myapp.
(Reading database ... 217181 files and directories currently installed.)
Preparing to unpack myapp.deb ...
Unpacking myapp (0.01) ...
Setting up myapp (0.01) ...
$
$
$tree dir
dir
└── usr
    └── bin
        └── myap

3 directories, 1 file
$
$
$./dir/usr/bin/myap 
1
2
3
4
5
6
7
8
9
$
$
$dpkg -s myapp
Package: myapp
Status: install ok installed
Priority: optional
Section: extras
Maintainer: my contact
Architecture: all
Version: 0.01
Description: myapp description
Homepage: my homepage
$
$
$dpkg --root=dir -l
$

注意 (Reading database ... 217181 files and directories currently installed.)因为它是从原始系统范围的默认值读取的,admindir因此/var/lib/dpkg数字很大217181......事实上它不应该这样做,正如明确指出的那样dpkg -b --help

--instdir=<directory>      Change installation dir without changing admin dir.

同时,--root确实:

$tree dir2
dir2

0 directories, 0 files
$
$
$sudo dpkg --root=dir2 -i myapp.deb 
Selecting previously unselected package myapp.
(Reading database ... 0 files and directories currently installed.)
Preparing to unpack myapp.deb ...
Unpacking myapp (0.01) ...
Setting up myapp (0.01) ...
$
$
$tree dir2
dir2
├── usr
│   └── bin
│       └── myap
└── var
    └── lib
        └── dpkg
            ├── info
            │   ├── format
            │   ├── myapp.install
            │   ├── myapp.list
            │   └── myapp.md5sums
            ├── lock
            ├── lock-frontend
            ├── status
            ├── status-old
            ├── triggers
            │   ├── Lock
            │   └── Unincorp
            └── updates

9 directories, 11 files
$
$
$./dir2/usr/bin/myap 
1
2
3
4
5
6
7
8
9
$
$
$dpkg --root=dir2 -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      Architecture Description
+++-==============-============-============-=================================
ii  myapp          0.01         all          myapp description
$

注意 (Reading database ... 0 files and directories currently installed.)因为它是从备用admindir处读取的dir2/var/lib/dpkg,因此是数字0

正如所述man dpkg

--root=dir
       Changing root changes instdir to dir and admindir to dir/var/lib/dpkg.

...确实如此,但是:

--instdir=dir
      Change  default installation directory which refers to the directory where packages
      are to be installed. instdir is also  the  directory  passed  to  chroot(2)  before
      running package's installation scripts, which means that the scripts see instdir as
      a root directory.  (Defaults to /)

... 似乎没有改变admindir,而是改变了软件包安装脚本的根目录,因此可能需要查看软件包中的那些脚本(如果有的话)或者查看相关内容或其他内容。

也就是说,--instdir的行为虽然不一定直接记录在手册的描述中,但可能取决于环境变量是否DPKG_ADMINDIR设置...引用自diff from 1.21.1ubuntu2 to 1.21.7ubuntu1

+    man: Clarify --admindir and --instdir default values
+    
+    These depend on the DPKG_ADMINDIR and DPKG_ROOT environment variables
+    being set or not. Although this is mentioned in the ENVIRONMENT section
+    it is not obvious directly from the command-line options descriptions.

...并且您可以看到实际效果(在 之前的 DPKG 版本中1.22.0),如果您确保环境变量已正确设置,例如通过在命令行本身上明确设置它,如下所示:

sudo DPKG_ADMINDIR="/var/lib/dpkg" dpkg --instdir=dir -i myapp.deb

然而,根据上面的演示,这个问题似乎已经得到解决,使用 DPKG 版本(1.22.0Ubuntu 23.10 下的默认版本)。

相关内容