Estimated reading time: 3 minutes

Gentoo one liners

On our Linux list at work the topic of Gentoo usage arose again today. Originally, the topic was about interesting one liners used to maintain a Gentoo system. I found myself posting extended replies to some of the questions and I’m reposting a few of those here.

How do I get just the list of packages that are installed but not in world?

The constraint here is packages that were installed with --oneshot, or manually removed from /var/lib/portage/world, which means that they will no longer be updated automatically. I often use this for packages I’m just playing with, and it appears lots of others do the same. While the output of emerge --pretend --depclean is all that is really needed, the question is how to get a list of just the packages.

$ emerge --pretend --depclean
<snipped heaps of output>
gnome-base/orbit
    selected: 2.14.17
protected: none
    omitted: none

app-text/iso-codes
    selected: 3.8
protected: none
    omitted: none

dev-libs/dbus-glib
    selected: 0.76
protected: none
    omitted: none

sys-apps/dbus
    selected: 1.2.3-r1
protected: none
    omitted: none

>>> 'Selected' packages are slated for removal.
>>> 'Protected' and 'omitted' packages will not be removed.

Packages installed:   477
Packages in world:    86
Packages in system:   50
Required packages:    348
Number to remove:     129

The output we want can be easily matched with RegEx, and the bash alias below will list just the packages by piping the output through sed. We can even use the one liner as input to a larger function if we only want to see top-level packages; that is packages that aren’t listed as dependencies of other packages:

alias pkgclean="emerge ----pretend --depclean | sed -n '/^ [a-z]/s,^ ,,p' | sort"

toppkgclean() {
    local depfiles=$(find /var/db/pkg/ -name RDEPEND -o -name PDEPEND)
    local cleanlist=$(pkgclean)
    for package in ${cleanlist}
    do
        LC_ALL=C grep -q ${package} ${depfiles} || echo ${package}
    done
}

Is it possible to use :command:`bash` completion to complete package names
for use in :file:`package.keywords`?

I actually wrote the following little function in reply to a user asking a similar question in #gentoo on Freenode a couple of months ago:

arch_unmask() {
    local s done
    if [[ -z $1 ]]
    then
        echo "${FUNCNAME} <category/package> [arch]"
        return 1
    fi
    for s in $(portageq envvar PORTDIR PORTDIR_OVERLAY)
    do
        if [[ -d $s/$1 ]]
        then
            echo $1 $2 >>/etc/portage/package.keywords/testing
            done=1
            break
        fi
    done
    if [[ -z "${done}" ]]
    then
        echo "Doesn't exist ‘$1’"
        return 1
    fi
}
complete -F _emerge arch_unmask

Note

If you’re using our Gentoo boxes at the office the function will be much faster if you replace the call to portageq by /var/lib/repos/*, as our package trees are always installed there. The portageq call is mainly there for users who use /usr/portage and /usr/local/portage, or other such monstrosities.

The final question I looked at was:

Is there an easy way to clean all the old modules from /lib/modules?

Assuming you are trying to remove all modules that don’t belong to the current kernel this is very easy using bash’s extglob support. It may need to be enabled in your session, you can test whether it is enabled with shopt extglob.

$ echo /lib/modules/*
/lib/modules/2.6.31.1 /lib/modules/2.6.31.2-jr2 /lib/modules/2.6.31.3-mk1
$ echo /lib/modules/!($(uname -r))
/lib/modules/2.6.31.1 /lib/modules/2.6.31.2-jr2

The !($(uname -r)) syntax tells bash to match all but 2.6.31.3-mk1 (the output of uname -r on my system), there are plenty of other uses for extglob and the documentation has examples.


Authenticate this page by pasting this signature into Keybase.

Have a suggestion or see a typo? Edit this page