![为什么“dpkg --instdir=dir/ -i xxx.deb”也将管理目录设置为“dir”,就像“--root=ddd”选项一样?](https://linux22.com/image/1199841/%E4%B8%BA%E4%BB%80%E4%B9%88%E2%80%9Cdpkg%20--instdir%3Ddir%2F%20-i%20xxx.deb%E2%80%9D%E4%B9%9F%E5%B0%86%E7%AE%A1%E7%90%86%E7%9B%AE%E5%BD%95%E8%AE%BE%E7%BD%AE%E4%B8%BA%E2%80%9Cdir%E2%80%9D%EF%BC%8C%E5%B0%B1%E5%83%8F%E2%80%9C--root%3Dddd%E2%80%9D%E9%80%89%E9%A1%B9%E4%B8%80%E6%A0%B7%EF%BC%9F.png)
我使用的是 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.0
Ubuntu 23.10 下的默认版本)。