Turning an i386 (32 bit) installation of Debian into an amd64 (64 bit) installation is becoming popular and, with the new multi-arch capabilities available in Debian since the release of Debian 7 "Wheezy", it's possible to do this in place and without a lot of difficulty. This procedure works on a base install in a VM as well as on a desktop machine with KDE and lots of other things installed (roughly 1800 packages in total). YMMV!
There are several other recipes published on how to do this and I have obviously learnt from these recipes. I've tried to simplify and make the process more robust than what was undertaken (or at least what was documented) there.
Other recipes have advised stripping the machine back to bare bones prior to starting. While that certainly helps apt in its quest to navigate the dependency graph, it's not strictly necessary. The recipe here has been tested with
- a basic installation including the
standard task
fromtasksel
- a basic installation plus
standard task
plusxfce4
plusxorg
That this recipe worked with non-trivial installations and without additional hand tweaking perhaps indicates that this is a more general recipe for turning an i386 box into an amd64 one.
Planning
First, make sure that the i386 packages you have installed actually have downloadable amd64 counterparts. All packages listed by the command below are going to cause problems later -- they can be:
- leftover detritus from previous releases (you can probably remove them)
- locally compiled packages that you will need to recompile for amd64; removing them now and then installing the amd64 version at the end might be the easiest approach
- 3rd party i386 packages (like skype or crossover) which will remain on the system as they are and continue to use the i386 libraries
# aptitude search '?narrow(?not(?archive("^[^n][^o].*$")),?version(CURRENT))?architecture(i386)'
Every package listed by that command will require a plan.
For those not so familiar with
aptitude
search patterns, the search pattern selects package versions
that are currently installed (?narrow(…, ?version(CURRENT))
)
and are available from archives other than now
and are from the i386 architecture (~ri386
)
(there are alternative patterns
and a
discussion in the BTS
about how better to do this).
Kernel space and preparations
The machine needs to be running a 64 bit kernel before any of the
crossgrading can happen. Fortunately, Debian already provides
amd64 kernels within the i386 architecture so this is trivial to do.
The recipe below will use dctrl-tools
and aptitude
so make sure they are installed and, if everything starts going wrong,
it's important to have a statically linked (that is to say, indestructable)
version of the busybox
Swiss-army knife around.
# apt-get install linux-image-amd64 busybox-static dctrl-tools aptitude # dpkg --add-architecture amd64 # apt-get update # reboot
Make sure you boot into the amd64 kernel; unfortunately, it will sort lower than the i386 kernel in the grub menu so this won't be automatic.
Pre-filling apt's cache
It's convenient to get apt to download as many packages right now so that we're not reliant on apt later (in case it breaks as we change libraries underneath it) or we break networking during the crossgrade process. Aptitude can produce a list of all the packages currently installed on the system and then we can ask apt to download their amd64 counterparts.
# cd /var/cache/apt/archives # apt-get clean # aptitude search --disable-columns -F%p '~ri386~i!~o' | xargs -n1 apt-get -o APT::Architecture=amd64 download
Note that the xargs -n1
stage is somewhat inefficient
because apt will keep rereading its cache for each invocation and that will
slow the process down. This is being done so that any i386-specific packages
(libc6-i686 for instance)
that are installed won't prevent apt from downloading all the packages
it does know about. Alternatively, filter the list of packages generated
by the aptitude search
and remove the -n1
.
For those not so familiar with
aptitude
search patterns, the search pattern selects packages that are
from the i386 architecture (~ri386
)
and are installed (~i
)
and are not obsolete (~o
that is they are not left over from
a previous release or locally installed).
Getting as far as possible with multi-arch
A lot of progress can be made by just installing the amd64 version of every library that is present and is already marked as being Multi-Arch: same. This means that a good number of libraries are pre-installed before the drastic work begins and it means that as soon as we start installing applications packages, they will start working.
# grep-status --field=Status "install ok installed" | grep-dctrl --field=Multi-Arch same --show-field=Package --no-field-names | sed 's/$/:amd64/' | xargs -n1 apt-get -y install
Warning: The use of apt here is slightly problematic -- installing the libraries
can potentially lead to large swathes of packages being removed here. The
packages will get reinstalled later on because they will match the *.deb
used in a later loop, but it's suboptimal. The reason this can go awry
here looks like Multi-arch: same
libraries depending on non-multiarch'd libraries
(the details are hard to tease our after the fact).
Adding a --no-remove
to the apt-get
call above
should prevent that from happening (untested).
To explain the rest of this command line,
grep-status
selects all installed packages,
the list is filtered down by grep-dctrl
to include only
those that are Multi-Arch: same
and then we tell apt to install the amd64 versions of those packages.
Once again, we do many (inefficient) apt runs to make sure this doesn't fail
because of packages like libc6-i686 which is Multi-Arch: same
but doesn't exist for amd64.
Note: there might be some file overwrite conflicts in this; they are from buggy packages. If it's something boring like the changelog, then just delete the changelog and reinstall the package for amd64. Removing the i386 package is also an option if you know you're not going to need it soon, but that can make apt stressed because the package list is no longer consistent.
Go mad and make it amd64
Now we're up to the irreversible and much more dangerous step: actually converting the installation over to amd64. The approach here is to use busybox to unpack a few key binary packages for us and then to let dpkg install all the packages we've already downloaded into the cache using apt.
We crudely destroy the old i386 files from the packages we will unpack
using busybox because busybox's dpkg-deb
applet refuses to
overwrite existing files. Sending a list of files (and some notes about diversions)
to xargs rm
is going to generate lots of noisy but harmless
errors about not being able to delete directories with rm
.
# dpkg -L dpkg dash findutils | xargs rm # busybox dpkg-deb -x dpkg* / # busybox dpkg-deb -x dash* / # busybox dpkg-deb -x findutils* / # for i in *.deb; do dpkg -i --force-depends $i; done # apt-get -f install
The binary packages will be unpacked in alphabetical order by the for
loop which is silly since that will unpack them in the wrong order according to the
dependencies, but since we don't necessarily have a working Essential set yet,
it doesn't really matter. It's sufficient to push dpkg through the problem with
--force-depends
and marvel at how good dpkg is at doing the right
thing and continuing to configure packages when it can and how robust
maintainer scripts are in being idempotent. The multiple calls to dpkg in this loop
is once again going to be slower than one large call, particularly as many of the
benefits of triggers are lost in doing this (man-db will be rebuilt a lot...).
The reason for doing this rather than just "dpkg -i *.deb
"
is that others have observed
dpkg struggling to handle this crazy step in one run and we don't
want small and expected failures to prevent dpkg from trying more packages.
Trading a little time on dpkg doing this all for us automatically
rather than requiring manual fixing is definitely preferable.
In my experience, the apt-get -f install
call at the end
usually doesn't actually have anything to do in any case, but it's a good opportunity
to make sure apt is happy about its new situation.
Note that after unpacking dpkg with busybox, dpkg --print-architecture
will report amd64
although the new dpkg package hasn't actually been
installed yet; that comes later.
By the time we get to apt-get -f install
, we have a fully functioning
amd64 apt and we should have a fully functioning amd64 system.
Remember that for apt-get
, the -f
option
stands for --fix-broken
and has nothing to do with force.
Once more, you may see file overwrite bugs. It's possible that
apt-get -f install
won't know how to deal with this situation
and you will have to dpkg -r foo:i386
to remove the i386 package
and then apt-get -f install
again).
The final apt-get -f install
stage may well fail with lots
of complaints and a generic "problem solver generated breaks" statement.
To solve this (manually), all that is required is a little judicious removal
of remaining i386 packages that apt is complaining about and perhaps some
aptitude download packagename; dpkg -i packagename_*deb
invocations followed by another attempt at apt-get -f install
.
Once again, a little imperfect that apt might need a little
hand-holding to solve the problems here, depending on how complicated the
original system was.
Cleaning up
The cross-grade can leave aptitude quite confused about what it should
be doing, with lots of packages marked as being in an iB
or
pB
state:
$ aptitude search ~b … iB zip - Archiver for .zip files pB zip:i386 - Archiver for .zip files
Where i
means "currently installed",
p
means "currently purged" and
B
means "will be broken by other actions". To cancel whatever
current actions aptitude has in mind and revert to the current state that apt
already has:
# aptitude keep-all
The old i386 kernel isn't going to be able to run userspace any more
so it may as well be removed. Expect some harmless warnings about
vmlinuz.old
and initrd.img.old
from the maintainer scripts during this process.
# aptitude remove '~ri386~nlinux-~i'
Our final check is to look over the remaining i386 packages on the machine. Hopefully it's only library packages but there's a chance there are a couple of library runtime packages that have remained. Manually install the amd64 versions of any non-library packages to get the ones for your (new) native architecture.
# aptitude search '~ri386~i' # aptitude search '~ri386~i!~slibs'
The first search shows all i386 packages still installed; the second searches for i386 packages that are installed that are not from the archive section "libs".
If you know you don't want to keep any i386 libraries around, then they can all be cleaned out in one swoop.
# aptitude remove '~ri386~i' # dpkg --remove-architecture i386
Last edited: Saturday March 1, 2014
Copyright © 1996-2014 Stuart Prescott