PIUPARTS(1)
π NAME π
okay bestie, meet piuparts(1) β the .deb installation, upgrade, and removal testing suite. no cap, this is the quality-assurance bestie for Debian packages. π«Ά
πΈ SYNOPSIS πΈ
piuparts [-a -p -v -V] [-d distro] [-i filename] [-I regexp] [-l logfile] [-m URL] [--bindmount dir] [package ...] [changes_file ...]
π DESCRIPTION π
okay so piuparts tests that Debian packages handle installation, upgrading, and removal correctly. It does this by creating a minimal Debian installation in a chroot, and installing, upgrading, and removing packages in that environment, and comparing the state of the directory tree before and after. Then piuparts reports any files that have been added, removed, or modified during this process. it's giving forensic package-hygiene energy. π
piuparts is meant as a quality assurance tool for people who create Debian packages to test them before they upload them to the Debian package archive.
By default, piuparts can do three different tests:
- A simple install-purge test within one Debian distribution (chosen with the
-doption, unstable by default). It sets up the chroot with the desired distribution, then installs and purges the packages, and reports problems. - A simple install-upgrade-purge test within one Debian distribution. This test is like the install-purge test, but it installs the packages first via
apt-getand then upgrades them with the package files given on the command line. If the command line has package names (option--aptused), or no tested package is known toapt-get(new packages), this test is skipped, otherwise it is performed automatically. - An upgrade test between Debian releases. This test is enabled by using the
-doption multiple times and disables the other two tests. It sets up the chroot with the first distribution named, then upgrades it to each successive one, and then remembers the directory tree state at the end. After this, it starts over with the chroot of the first distribution, installs the desired packages (viaapt-get install), and does the successive upgrading (viaapt-get dist-upgrade). Then, if package files (and not just package names) were given on the command line, it installs them. Finally, it reports problems against the state of the directory tree at the last distribution compared with the state without the packages having been installed. This test can be quite slow to execute. Note that this does not work withexperimental, becauseapt-getdoes not automatically upgrade to packages inexperimental. To test a particular package or group of packages inexperimental, use the second test.
Command line arguments are the paths to package files (e.g., piuparts_1.0-1_all.deb), paths to changes files (e.g., piuparts_1.0-1_i386.changes), or names of packages, if the --apt option is given.
When processing changes files, by default, all packages in a changes file will be processed together with all individual packages given on the command line. Then each package given on the command line is processed in a single group. If --single-changes-list is used, the packages in all changes files are processed together along with any individual packages that were given on the command line. To avoid this behaviour, it is possible to specify --single-packages.
piuparts outputs to the standard output some log messages to show what is going on. If a log file is used, the messages go there as well.
piuparts requires root rights to test packages. It does not have to be run in the initial namespace though. When running it as non-root, it'll create a new Linux namespace and rerun itself as root inside said namespace. For this to work, your user needs have an subuid range (which happens by default since a few years) and you need to install the uidmap package to provide setuid helpers newuidmap and newgidmap.
β¨ OPTIONS β¨
Options must come before the other command line arguments. periodt.
-a,--aptβ The package arguments on the command line are to be treated as package names and installed viaapt-get installinstead of being names of package files, to be installed viadpkg -i.--allow-databaseβ Allow starting MySQL and PostgreSQL database servers in the chroot for packages requiring database access in their maintainer scripts.
Do not use this option if there is already a database server running on the system runningpiuparts(orpiuparts-slave)! In master-slave setups with multiple slaves running on one host collisions may occur, these will be detected bydetect_piuparts_issuesand the affected packages will be tested again.
--archarch β Create chroot and run tests for (non-default) architecture arch. The default is the output fromdpkg --print-architecture.-btarball,--basetgztarball β Use tarball as the contents of the initial chroot, instead of building a new one withdebootstrap.
The tarball can be created with the -s option, or you can use one that pbuilder has created (see -p). If you create one manually, make sure the root of the chroot is the root of the tarball. Despite the option name implying gzip compression, the compression scheme is deduced by tar from the filename suffix.
--bindmountdir β Bind-mount a directory inside the chroot.--bootstrapcmdcmd β Set alternative chroot bootstrap command (including command line options). The default isdebootstrap --variant=minbase. Needs to be compatible with typicaldebootstrapcommand line options such as--archand--include. Formmdebstrapuse:--bootstrapcmd=mmdebstrap --skip=check/empty --variant=minbase.-dname,--distributionname β Which Debian distribution to use: a code name (for examplebullseye,bookwormorsid) orexperimental. The default issid(=unstable).-Dflavor,--defaultsflavor β Use default settings suitable for a particular flavor of Debian: eitherdebianorubuntu. The default isdebian.--do-not-verify-signaturesβ Do not verify signatures from the Release files when runningdebootstrap. Also setAPT::Get::AllowUnauthenticatedaccordingly in/etc/apt/apt.confin the chroots.--dpkg-force-confdefβ Makedpkguse--force-confdef, which letsdpkgalways choose the default action when a modified conffile is found.
This option will makepiupartsignore errors it was designed to report and therefore should only be used to hide problems in depending packages. This option shall normally not be used. (See#466118(https://bugs.debian.org/466118).)
--dpkg-noforce-unsafe-ioβ Prevent runningdpkgwith--force-unsafe-io.--force-unsafe-iocausesdpkgto skip certain file system syncs known to cause substantial performance degradation on some filesystems. Thus, including this option reverts to safe but slower behavior. The--dpkg-noforce-unsafe-iois required for running tests on distributions older thansqueeze.--no-eatmydataβ Prevent use ofeatmydata. The--no-eatmydataoption is required for running tests onsqueezeor older distributions.--extra-old-packagespkg1[,pkg2]... β Install additional old packages before upgrading. Allows testing package renames/merges where the old package is no longer available in the new distribution and the new one utilizesConflicts/Replaces. The argument is a comma separated list of package names and the option can be given multiple times. For install/purge tests these packages will be installed before the package that is to be tested.-edirname,--existing-chrootdirname β Use the specified directory as source for the new chroot, instead of building a new one withdebootstrap. This is similar to--basetgz, but the contents are not archived. See also the--hard-linkoption.--distupgrade-to-testdebsβ Use the"testdebs"repository to override the packages in the distupgrade target distribution. This allows one to test complex upgrade paths before the packages enter the archive.--extra-repodeb-line β Provide an additional (unparsed) line to be appended tosources.list, for example:
'deb <URL> <distrib> <components>'
or
'deb file:// </bind/mount> ./'
Useful for e.g. backports, security or local repositories that cannot be handled by --mirror. May be repeated to add more than one line.
--fake-essential-packagespkg1[,pkg2]... β Install additional packages in the base chroot that are not removed after the test. These are available during purge and for checking against mistreatment. Takes a comma separated list of package names and can be given multiple times.--hard-linkβ When the--existing-chrootoption is used, and the source directory is on the same filesystem, hard-link files instead of copying them. This is faster, but any modifications to files will be reflected in the originals.-ifilename,--ignorefilename β Add a filename to the list of filenames to be ignored when comparing changes before and after installation. By default,piupartsignores files that always change during a package installation and uninstallation, such asdpkgstatus files. The filename should be relative to the root of the chroot (e.g.,var/lib/dpkg/status). Filenames prefixed with a:will be logged verbosely if found. This option can be used as many times as necessary.-Iregexp,--ignore-regexpregexp β Add a regular expression pattern to the list of patterns for filenames to be ignored when comparing changes before and after installation. Patterns prefixed with a:will log verbosely all matching files. This option can be used as many times as necessary.--install-purge-installβ Purge package after installation and reinstall. All dependencies are available during purge.--install-recommendsβ Enable installation ofRecommends.--install-suggestsβ Enable installation ofSuggests.--install-remove-installβ Remove package after installation and reinstall. For testing installation in config-files-remaining state.-k,--keep-envβ Depending on which option is passed, keep the environment used for testing after the program ends- By default it doesn't remove the temporary directory for the chroot,
- or if
--schrootis used, the schroot session is not terminated, - or if
--docker-imageis used, the container created is not destroyed.
-K filename,--keyring filenameβ use filename as the keyring to hand to debootstrap when it's building chroots for you.--keep-sources-listβ don't touch the chroot's/etc/apt/sources.list. leave it exactly as it is, bestie π--list-installed-filesβ list out all the files that got added to the chroot, both after the package itself is installed and after its dependencies are installed. receipts for everything π--lvm-volume lvm-volumeβ use the lvm-volume you name as the source for the chroot instead of building a fresh one with debootstrap. it snapshots that LVM volume and mounts the snapshot over at the chroot path. fancy.--lvm-snapshot-size snapshot-sizeβ sets the snapshot-size used when a new LVM snapshot gets made (default:1G).-l filename,--log-file filenameβ append the log file to filename, on top of the normal standard output. so you get both.--log-level levelβ show messages starting from loglevel level. the possible values are:error,info,dump,debug. the default isdump.--max-command-output-size sizeβ caps the maximum permitted command output at size (in MB) for debugging runs that go over the default of 8 MB.--merged-usrβ when debootstrap is creating the chroot, use the--merged-usroption so the chroot comes out with/bin,/lib, and/sbinas symlinks to their/usrcounterparts. iconic layout β¨--no-merged-usrβ when debootstrap is creating the chroot, use the--no-merged-usroption.-m URL,--mirror URLβ which Debian mirror to use, queen. default is the first mirror named in/etc/apt/sources.list, orhttp://deb.debian.org/debianif nothing's found there. you can use this option multiple times to use multiple mirrors β but heads up, only the first mirror is used with debootstrap.
the 'components' used for a mirror can be set with this option too: a space separated list inside the same argument (so yes, you have to quote the whole argument in the shell). if no components are given explicitly, the usual Debian components are used (main, contrib, non-free, and non-free-firmware). for mirrors read from /etc/apt/sources.list, the components are read from that same place.
note thatfile:addresses work if the directories are made accessible from inside the chroot with--bindmount. iykyk π«Ά
--no-adequateβ don't run adequate after installation. the default is to run adequate, provided it's installed.--no-check-valid-untilβ sets the apt optionAcquire::Check-Valid-Until=falseinside the chroot, which makes it ignore the expiration of Release files. you need this for testing archived releases.--no-diversionsβ don't check for broken diversions.-n,--no-ignoresβ forget all built-in and other ignores that have been set so far. any-ior-Iarguments that come after this one will be obeyed, but none of the ones that come before it. clean slate energy π§Ό-N,--no-symlinksβ don't check for broken symlinks.--fail-if-inadequateβ fail on inadequate results from running adequate. the default is to just issue those errors as warnings.--fail-on-broken-symlinksβ fail on broken symlinks. default is to just issue those errors as warnings.--no-upgrade-testβ skip testing the upgrade from an existing version in the archive.--no-install-purge-testβ skip the install and purge test.-p,--pbuilderβ use/var/cache/pbuilder/base.tgzas the base tarball. it's a shorthand so you don't have to use-bfor it. convenience queen π--pedantic-purge-testβ be pedantic when checking whether a purged package left files behind. if this option is not set, files left in/tmpare ignored.--proxy URLβ use the proxy at URL to reach the Debian mirror(s). this takes precedence over thehttp_proxyenvironment variable. using a local proxy is recommended, because piuparts may use large amounts of bandwidth repeatedly downloading the same files. like, a LOT of bandwidth π-s filename,--save filenameβ save the chroot, once it's been set up, as a tarball into filename. then you can feed it back in with-b. β¨-B filename,--end-meta filenameβ load chroot package selection and file meta data from filename. see the functioninstall_and_upgrade_between_distros()inpiuparts.pyfor the defaults. mostly useful for large scale distro upgrade tests.-S filename,--save-end-meta filenameβ save chroot package selection and file meta data into filename for later use. again, see the functioninstall_and_upgrade_between_distros()inpiuparts.pyfor the defaults. mostly useful for large scale distro upgrade tests.--scriptsdir directoryβ the directory where your custom scripts are placed. by default this is not set. for more info about this, go readREADME_server.txt. π--schroot SCHROOT-NAMEβ use the schroot session named SCHROOT-NAME as the testing environment, instead of building a new one with debootstrap.--docker-image DOCKER-IMAGEβ use a container created from the docker image DOCKER-IMAGE as the testing environment, instead of building a new one with debootstrap. this only supports overlay2 for now, and it uses the MergedDir layer, where piuparts can access, add, edit, and remove files easily by directly accessing the directory. π³--single-changes-listβ normally, when processing changes files, piuparts processes the packages in each individual changes file separately. this option sets piuparts to scan the packages of all changes files together, along with any individual package files that may have been given on the command line.--single-packagesβ process every package file or package name individually, so piuparts runs multiple times. can be useful with conflicting packages.--shell-on-errorβ start an interactive shell inside the chroot after an error occurs. this should help you debug failures directly inside the piuparts test environment. the chroot cleanup will continue after the shell terminates.
note: this does not work if the piuparts command is prefixed withtimeout, which is usually the case in command lines copied straight out of logfiles from a master-slave setup. removing thetimeoutpart is sufficient. π
--skip-minimizeβ allow skipping the minimize chroot step. useful when you want to test several packages with piuparts: you can prepare a tarball that's already minimized and skip this step in all the tests. this is the default now.--minimizeβ minimize the chroot with debfoster. this used to be the default until#539142(https://bugs.debian.org/539142) was fixed.--skip-cronfiles-testβ skip testing the output from the cron files left in the system after removing a package.--skip-logrotatefiles-testβ skip testing the output from the logrotate files left in the system after removing a package.--testdebs-repo deb-lineβ provide an additional line to be appended tosources.list, for example:
'deb [ trusted=yes ] <URL> <distrib> <components>'
or
'deb [ trusted=yes ] file:// </bind/mount> ./'
if only a URL or local path is given as the argument, deb [ trusted=yes ], file://, and ./ will be prepended/appended as needed. the "testdebs" repository provides the packages to be tested (and some additional dependencies, if needed, e.g. all packages built from the same source package as the (binary) package being tested), and it can be used for testing complex installation and upgrade scenarios involving dependencies that are not yet in the archive. this repository will be available only for installing the target packages. dependency resolution will be done by apt-get. the packages to be tested can be passed as .debs or as package names (with --apt).
the trusted=yes option causes this (and only this) repository to be trustworthy even if the Packages file is not signed, such that a (globally acting) --do-not-verify-signatures will not be needed. bestie, it's giving trust issues but make it targeted π―
-t directory,--tmpdir directoryβ use directory as the place where temporary files and directories get created. the default is the environment variableTMPDIR, or/tmpif that's not set.
note: the temporary directory must not be mounted with thenodevornosuidmount option.
--update-retries num-retriesβ rerunapt-get updateup to num-retries times. useful for working around temporary network failures and hashsum mismatch errors. network said no, we say try again π--upgrade-before-dist-upgradeβ perform two-stage upgrades:apt-get upgrade && apt-get dist-upgrade.-v,--verboseβ this option no longer has any meaning, but it's still accepted for backwards compatibility. it's retired but it still shows up to the party π-V,--versionβ write out the version number of the program.--warn-on-debsums-errorsβ print a warning rather than failing if debsums reports modified files.--warn-on-leftovers-after-purgeβ print a warning rather than failing if files are left behind after purge.--warn-on-othersβ print a warning rather than failing if files are left behind, modified, or removed by a package that was not given on the command-line.
this way, you can basically isolate the purge test to your own packages. if a package that got brought in as a dependency doesn't purge cleanly, the test will not fail because of it (but a warning message will be printed).
behavior with multiple packages given on the command-line could be problematic, particularly if the dependency tree of one package in the list includes another one in the list. therefore, it's recommended to use this option with one package at a time. one at a time, bestie, we don't do chaos runs π
--warn-on-usr-move disabled|warn|failβ whether to enable the test (with a warning or a failure) that checks if files are moved between/bin|sbin|lib*and/usr/bin|sbin|lib*. accepted values:disabled(default),warn,fail.
π EXAMPLES π
okay bestie, storytime β you just built a shiny new version of your Debian package and you're about to yeet it into Debian unstable. it's sitting there at ../foo_1.0-2_i386.deb and you're lowkey stressed wondering if it even installs and uninstalls properly. here's literally what you do:
piuparts ../foo_1.0-2_i386.deb
and if that package already exists in the Debian archive? the command above also checks that it upgrades properly. two-for-one, we love to see it β¨
now say you want that same test but pointed at a specific mirror, and only the main component. easy:
piuparts -m 'http://gytha/debian main' ../foo_1.0-2_i386.deb
want the same vibe but for your .changes files instead? just hand piuparts your changes files and it'll process each package inside them as though you'd passed all those packages on the command line to piuparts yourself. iconic behaviour, honestly:
piuparts ../foo_1.0-2_i386.changes
piuparts -m 'http://gytha/debian main' ../foo_1.0-2_i386.changes
and finally, the main character move π β testing that a package installs properly in the stable (currently bullseye) Debian release, can be upgraded to testing (currently bookworm) and unstable (sid), and then uninstalls without problems:
piuparts -a -d bullseye -d bookworm -d sid foo
periodt. that's the whole journey, install β upgrade β uninstall, no drama. π
πΈ ENVIRONMENT πΈ
TMPDIRβ the location for temporary files and directories, bestie. if it's not set, we just use/tmp. oh and also go peek at the--tmpdiroption, iykyk.
π NOTES π
okay so real talk β the output of commands run by piuparts is limited to three megabytes. to change that limit, the source code needs to be edited. and if a command goes over that limit? it gets aborted. no cap, no mercy π
π¦ SEE ALSO π¦
pbuilder(1)debootstrap(8)
π AUTHOR π
Lars Wirzenius (<liw@iki.fi>) and others π
and that's a wrap, bestie!! this gorgeous little page is PIUPARTS(1), dated Jan 27, 2026 β go forth, test your packages, and slay π«Άπ
β¨
π¦ where this page comes from
- ubuntu resolute: piuparts 1.6.0build1 Β· GPL-2.0-or-later
- ubuntu stonking: piuparts 1.6.0build1 Β· GPL-2.0-or-later
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms