Last active
January 29, 2019 15:06
-
-
Save ruario/11246041 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/sh | |
# | |
# Version: 1.2 | |
# | |
# This script provides a method for tracking software installed from | |
# source. Run it as follows for more information: | |
# | |
# pkgtrack -h | |
# | |
# Copyright 2018 Ruari Odegaard, Oslo, Norway | |
# All rights reserved. | |
# | |
# Redistribution and use of this script, with or without modification, | |
# is permitted provided that the following conditions are met: | |
# | |
# 1. Redistributions of this script must retain the above copyright | |
# notice, this list of conditions and the following disclaimer. | |
# | |
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | |
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | |
# HOLDER BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | |
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | |
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | |
# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF | |
# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | |
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
helptext () { | |
cat << EOH | |
Script usage: | |
$OWNNAME [options] [installation command] | |
Script options: | |
-h, --help Print this help text. | |
-n, --name [package name] Specify the name of the package, | |
otherwise the parent directory | |
name will be used. | |
-l, --list List installed packages | |
-s, --show-contents Show a list of files contained | |
within the package. | |
-ip, --install-package Install a previously backed up | |
package. | |
-id, --install-directory Install the contents of the current | |
directory to root (/) and log it. | |
-u, --uninstall Remove a package you installed | |
previously. | |
-b, --backup Create a backup archive of a | |
previously installed package. | |
Examples: | |
\$ $OWNNAME make install | |
\$ $OWNNAME --name foo ./install-foo.sh | |
\$ $OWNNAME --list | |
\$ $OWNNAME -n foo -s | |
\$ $OWNNAME --uninstall -n foo | |
\$ $OWNNAME -b -n foo | |
\$ $OWNNAME --install-package -n foo.pkg.tar.gz | |
\$ $OWNNAME --install-directory --name foo | |
EOH | |
} | |
noname () { | |
printf "\n\"$PKGNAME\" is not installed, specify a valid name with the \"--name\" option.\n\n" >&2 | |
} | |
extract_dirs () { | |
sed 's,\(.*\)/.*,\1,' "$1" | sort -u | \ | |
while read d; do | |
while echo "$d" | grep -vx .; do | |
d=$(dirname "$d") | |
done | |
done | sort -ur | grep -vxE \ | |
-e '(/s?bin|/etc|/lib(32|64)?|/opt|/var)' \ | |
-e '/usr((/local)?(/s?bin|/doc|/include|/info|/lib(32|64)?|/man(/man[1-9n])?|/share(/doc|/info|/man(/man[1-9n])?)?|/src)?)?' \ | |
-e '/usr/local/etc' | |
} | |
removefiles () { | |
while read f; do | |
# '-e' alone would not find broken symlinks | |
if [ -e "$f" -o -h "$f" ]; then | |
if [ -d "$f" ]; then | |
if ! ls -A "$f" | grep -q ^; then | |
# Don't remove a symlink pointing to a directory, as it could have | |
# been created by the user or the distribution | |
if [ ! -h "$f" ]; then | |
rmdir -v "$f" | |
fi | |
fi | |
else | |
rm -v "$f" | |
fi | |
fi | |
done | |
} | |
listfiles () { | |
ROOTDIRS=$(find / -maxdepth 1 -type d -regextype posix-egrep -regex '/(etc|s?bin|lib.*|opt|usr)') | |
find $ROOTDIRS ! -type d -print > $1 | |
} | |
# Handle options | |
SHOWHELP=n | |
PKGUNINSTALL=n | |
PKGLIST=n | |
PKGSHOW=n | |
PKGINSTALL=n | |
PKGBACKUP=n | |
PKGINSTDIR=n | |
while [ 0 ]; do | |
if [ "$1" = "-h" -o "$1" = "--help" ]; then | |
SHOWHELP=y | |
shift 1 | |
elif [ "$1" = "-n" -o "$1" = "--name" ]; then | |
PKGNAME="$2" | |
shift 2 | |
elif [ "$1" = "-u" -o "$1" = "--uninstall" ]; then | |
shift 1 | |
PKGUNINSTALL=y | |
elif [ "$1" = "-l" -o "$1" = "--list" ]; then | |
shift 1 | |
PKGLIST=y | |
elif [ "$1" = "-s" -o "$1" = "--show-contents" ]; then | |
shift 1 | |
PKGSHOW=y | |
elif [ "$1" = "-ip" -o "$1" = "--install-package" ]; then | |
shift 1 | |
PKGINSTALL=y | |
elif [ "$1" = "-id" -o "$1" = "--install-directory" ]; then | |
shift 1 | |
PKGINSTDIR=y | |
elif [ "$1" = "-b" -o "$1" = "--backup" ]; then | |
shift 1 | |
PKGBACKUP=y | |
else | |
break | |
fi | |
done | |
OWNNAME=$(basename "$0") | |
if [ "$SHOWHELP" = "y" ]; then | |
helptext | |
exit 0 | |
fi | |
if [ "$PKGLIST" = "y" ]; then | |
ls /var/lib/footprints | grep "$1" | |
exit 0 | |
fi | |
if [ -z "$PKGNAME" ]; then | |
PKGNAME=$(basename "$(pwd)") | |
echo "The \"--name\" option was not used so the package name has been set to the name of the directory: $PKGNAME" >&2 | |
fi | |
if echo "$PKGNAME" | grep -Fq '/'; then | |
echo 'The package name must not contain "/". Use "--name" to specify another name.' >&2 | |
exit 1 | |
fi | |
if [ "$PKGSHOW" = "y" ]; then | |
if [ -r "/var/lib/footprints/$PKGNAME" ]; then | |
echo "@${PKGNAME}:" | |
cat "/var/lib/footprints/$PKGNAME" | |
exit 0 | |
else | |
noname | |
helptext | |
exit 1 | |
fi | |
fi | |
if [ "$PKGINSTALL" = "y" ]; then | |
if [ -r "$PKGNAME" ]; then | |
tar -C / -xvf "$PKGNAME" | |
exit 0 | |
else | |
noname | |
helptext | |
exit 1 | |
fi | |
fi | |
if [ "$PKGINSTDIR" = "y" ]; then | |
if [ -r "/var/lib/footprints/$PKGNAME" ]; then | |
echo "$PKGNAME is already installed" >&2 | |
helptext | |
exit 1 | |
else | |
echo "Installing ${PKGNAME}:" | |
mkdir -p /var/lib/footprints | |
find . ! -type d | grep -vF "./var/lib/footprints/$PKGNAME" | \ | |
cpio --quiet -pmdv / 2>&1 | sed 's,^//\.,,' | tee "/var/lib/footprints/$PKGNAME" | |
echo "/var/lib/footprints/$PKGNAME" | tee -a "/var/lib/footprints/$PKGNAME" | |
exit 0 | |
fi | |
fi | |
if [ "$PKGBACKUP" = "y" ]; then | |
if [ -r "/var/lib/footprints/$PKGNAME" ]; then | |
if command -v xz >/dev/null 2>&1; then | |
EXT=xz | |
elif command -v bzip2 >/dev/null 2>&1; then | |
EXT=bz2 | |
else | |
EXT=gz | |
fi | |
sed 's,^/,,' "/var/lib/footprints/$PKGNAME" | tar -C / --format=pax -cvvaf "${PKGNAME}.pkg.tar.$EXT" -T- | |
echo "Created: ${PKGNAME}.pkg.tar.$EXT" | |
exit 0 | |
else | |
noname | |
helptext | |
exit 1 | |
fi | |
fi | |
if [ "$PKGUNINSTALL" = "y" ]; then | |
if [ -r "/var/lib/footprints/$PKGNAME" ]; then | |
PKGUNINSTALL_LIST=$(mktemp -t remove.XXXXXX) | |
cat "/var/lib/footprints/$PKGNAME" > "$PKGUNINSTALL_LIST" | |
extract_dirs "/var/lib/footprints/$PKGNAME" >> "$PKGUNINSTALL_LIST" | |
removefiles < "$PKGUNINSTALL_LIST" | |
rm -f "$PKGUNINSTALL_LIST" | |
exit 0 | |
else | |
noname | |
helptext | |
exit 1 | |
fi | |
fi | |
if [ -z "$1" ]; then | |
echo "You must specify an installation command (e.g. \"$OWNNAME make install\")" >&2 | |
helptext | |
exit 1 | |
fi | |
# The original tracking script, before I added all the fancy stuff above! ;) | |
BEFORE=$(mktemp -t before.XXXXXX) | |
AFTER=$(mktemp -t after.XXXXXX) | |
listfiles $BEFORE | |
$@ | |
listfiles $AFTER | |
mkdir -p /var/lib/footprints | |
diff --normal $BEFORE $AFTER | sed -n 's/^> //p' > "/var/lib/footprints/$PKGNAME" | |
echo "/var/lib/footprints/$PKGNAME" >> "/var/lib/footprints/$PKGNAME" | |
rm -f $BEFORE $AFTER | |
echo "Created log: /var/lib/footprints/$PKGNAME" |
You may notice that the script only logs files that are created by the install process, not directories. This is done intentionally as it keeps the logs from being overly bloated and makes them easier to read.
Directories are far more likely to be shared between many applications, rather than being tied to the specific package you installed. Thus it is also a more accurate representation of the package contents.
See also createpkg
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Save the above somewhere in your path. Then just preface it to any install command you wish to track, e.g.:
or perhaps:
A suitably name log file will be created in
/var/lib/footprints/
, listing all the files that where installed. This log can be used to remove those files or create a backup of the installation using and archiver like tar, cpio or zip.