SBdocs - SlackBuilder Tutorials - getpkg

Last updated:

getpkg


getpkg is a non interactive command that takes one or more package names or pkgs.lst files as an argument. It will verify if the package(s) need to be installed, upgraded or is up-to-date. If the package is to be installed/upgraded it will download the package to a cache directory and tell slackware's installpkg to install it, then remove the downloaded package from the cache. After processing all command line arguments it will silently update the package database.

Note: getpkg does not resolve dependencies.

Examples of use

--> getpkg kodi
root /
%%%%%%%%%%% kodi install
at the location /var/pkgcache/Slackbuilder-x86_64-14.2
 24550K .......... .......... ........                        100% 2.58M=12s
Verifying package kodi-16.1-x86_64-4_Skn.txz.
Installing package kodi-16.1-x86_64-4_Skn.txz:
PACKAGE DESCRIPTION:
# kodi (Multi-platform Media Center)
#
# XBMC is an award winning media center application for Linux, Mac OS X,
# Windows and XBox. The ultimate hub for all your media, XBMC is easy to
# use, looks slick, and has a large helpful community.  XBMC supports
# viewing and playing a vast library of audio, video and image formats.
# XBMC has a sophisticated library management system that allows you to
# organize all your media to give you quick and immediate access.
#
# Homepage: http://kodi.tv
#
Executing install script for kodi-16.1-x86_64-4_Skn.txz.
Package kodi-16.1-x86_64-4_Skn.txz installed.

If already installed then .....

--> getpkg kodi
root /
%%%%%%%%%%% kodi is up-to-date

If not an available pkg

--> getpkg nada
root /

The root / line indicates the mountpoint mntpt variable which in this case is the default root directory /. mntpt is used instead of something like ROOT so as not to muck up other environment variables from other commands. Namely slackware's pkgtools. ROOT_DEV is used in others. I have not yet discovered mntpt used anywhere else.

An example of a different mntpt....Note: The mntpt directory must already exist. It is not created automatically.

--> mntpt=/mnt/installdir getpkg nada
root /mnt/installdir
Error: incomplete SQL: INSERT INTO PKGS (ID, NAME, FILE,  LOCATION, SIZE_COMP, SIZE_UNCOMP) VALUES

The error is because there is no slackware installation at /mnt/installdir and 'nada' is not a real pkg. getpkg runs a database update after it attempts to install a package(s). There are actually two databases created. One for availabe packages and one for installed packages. Since there is no installed packages yet there is a database error.

Installing a real package...

 --> mntpt=/mnt/installdir getpkg kodi
root /mnt/installdir
%%%%%%%%%%% kodi install
at the location /var/pkgcache/Slackbuilder-x86_64-14.2
 24550K .......... .......... ........                        100% 2.20M=11s
Verifying package kodi-16.1-x86_64-4_Skn.txz.
Installing package kodi-16.1-x86_64-4_Skn.txz:
PACKAGE DESCRIPTION:
# kodi (Multi-platform Media Center)
#
# XBMC is an award winning media center application for Linux, Mac OS X,
# Windows and XBox. The ultimate hub for all your media, XBMC is easy to
# use, looks slick, and has a large helpful community.  XBMC supports
# viewing and playing a vast library of audio, video and image formats.
# XBMC has a sophisticated library management system that allows you to
# organize all your media to give you quick and immediate access.
#
# Homepage: http://kodi.tv
#
Executing install script for kodi-16.1-x86_64-4_Skn.txz.
Package kodi-16.1-x86_64-4_Skn.txz installed.

This works because 'kodi' is a real pkg.

Then if you try ....

--> mntpt=/mnt/installdir getpkg nada
root /mnt/installdir

There is no error because now the installed package database is not empty.

Note: The above example is just for demonstration purposes and is not recommended in practice since the CACHE environment variable has not been defined for the mntpt. At this point the host database has been altered to coincide with the mntpt. Just run pkg-info -u to correct the problem. In short the installdir package cache needs to be isolated from the host's. This is achieved by changing the CACHE variable. The cache directory will be created automatically if it does not exist.

Intended Use

getpkg can of course be used directly but is meant as a building block for other more sophisticated commands. It is used in getpkgs which is inturn used in the installer 'slkn-setup', slkn-usbboot's 'mkimg' and slackpacks's 'sbuilder' commands among others.

The example above shows how to change the install directory by changing the mntpt environment variable. There are other variables that change the default behavior too. Like the ARCH, SVRSN ( slackware version ), SRC and CACHE.

Note: the default CACHE directory is /var/pkgcache. This needs to be changed for a different mntpt location so as not to corrupt the host's database. Specifically for installed packages.

The following is an example of how to script your own command to install a package and it's recursive dependencies into a mntpt. The mntpt can be any mounted device or directory...

Building a custom script

Assuming you already have a mntpt directory created ( we'll use the example above ) and a package of interest to install ( continuing with the example we'll use kodi ) the next step is to get a list of dependencies if any exists. The ldeps command is suited for this purpose...

  --> ldeps -s kodi
libdvdcss
libmicrohttpd
tinyxml
yajl
crossguid
dcadec
libmpeg2
libass
jdk

the -s option returns a simple flat list of recursive dependencies. Lets go ahead and store that in a file for use later. We need to add kodi to the list as well.

(ldeps -s kodi ; echo kodi) > kodi.lst

The name of the file is arbitrary.

You can install this list from the command line without a script like this...first update the database...

--> SRC=HTTP:localhost/Slackbuilder-x86_64-14.2 mntpt=/mnt/installdir CACHE=/tmp/my_cache pkg-info -u
 SRC ==> localhost/Slackbuilder-x86_64-14.2/PACKAGES.TXT
    50K ..........                                            100%  315M=0s

Then...

--> SRC=HTTP:localhost/Slackbuilder-x86_64-14.2 mntpt=/mnt/installdir CACHE=/tmp/my_cache getpkg kodi.lst
root /mnt/installdir
%%%%%%%%%%% libdvdcss install
at the location /tmp/my_cache/Slackbuilder-x86_64-14.2
   100K .......... .......... .....                           100%  377M=0s
Verifying package libdvdcss-1.4.0-x86_64-1_Skn.txz.
Installing package libdvdcss-1.4.0-x86_64-1_Skn.txz:
PACKAGE DESCRIPTION:
# libdvdcss (DVD decryption library)
#
# libdvdcss is a cross-platform library for transparent DVD device
# access with on-the-fly CSS decryption.  It is used by libdvdread
# and most DVD players such as VLC because of its portability and
# because, unlike similar libraries, it does not require your DVD
# drive to be region locked.
#
# Home Page: http://developers.videolan.org/libdvdcss/
#
Executing install script for libdvdcss-1.4.0-x86_64-1_Skn.txz.
Package libdvdcss-1.4.0-x86_64-1_Skn.txz installed.

%%%%%%%%%%% libmicrohttpd install
at the location /tmp/my_cache/Slackbuilder-x86_64-14.2
   150K .......... .......... .......... .......              100%  292M=0.001s
Verifying package libmicrohttpd-0.9.48-x86_64-1_Skn.txz.
Installing package libmicrohttpd-0.9.48-x86_64-1_Skn.txz:
PACKAGE DESCRIPTION:
# libmicrohttpd (HTTP server C library)
#
# GNU libmicrohttpd is a small C library that is supposed to make it
# easy to run an HTTP server as part of another application.
#
# GNU libmicrohttpd is free software and part of the GNU project.
#
Executing install script for libmicrohttpd-0.9.48-x86_64-1_Skn.txz.
Package libmicrohttpd-0.9.48-x86_64-1_Skn.txz installed.

%%%%%%%%%%% tinyxml install
.
.
.
.
.

%%%%%%%%%%% kodi install
at the location /tmp/my_cache/Slackbuilder-x86_64-14.2
 24550K .......... .......... ........                        100%  245M=0.3s
Verifying package kodi-16.1-x86_64-4_Skn.txz.
Installing package kodi-16.1-x86_64-4_Skn.txz:
PACKAGE DESCRIPTION:
# kodi (Multi-platform Media Center)
#
# XBMC is an award winning media center application for Linux, Mac OS X,
# Windows and XBox. The ultimate hub for all your media, XBMC is easy to
# use, looks slick, and has a large helpful community.  XBMC supports
# viewing and playing a vast library of audio, video and image formats.
# XBMC has a sophisticated library management system that allows you to
# organize all your media to give you quick and immediate access.
#
# Homepage: http://kodi.tv
#
Executing install script for kodi-16.1-x86_64-4_Skn.txz.
Package kodi-16.1-x86_64-4_Skn.txz installed.

You don't have to define the SRC if your ok with the settings in /etc/pkg-tools/RC. But you can for whatever reason you may have need of.

Putting it in a script

#!/bin/bash
#
# install_pkgs....
# arguments can be a file or standard input or a combination of both
# ----------------------------------------------------------------

eval $(svrsn)

# make sure there is a space at the end of each SRC entry

SRC+="HTTP:mirrors.kernel.org/slackware/slackware${SUFFIX}-${SVRSN} "
SRC+="HTTP:slackonly.com/pub/packages/${SVRSN}-${RCH} "
SRC+="HTTP:localhost/Slackbuilder-${ARCH}-${SVRSN} "

export CACHE="/tmp/my_cache"
export mntpt="/mnt/installdir"
export SRC="${SRC}"

while :; do
  case $1 in
    -u) pkg-u # shorthand for pkg-info -u
        shift
      ;;
  esac
  break
done

# input should be package name(s) or package list file(s) 
getpkg $@

Call it like so...with a file and/or a package as arguments...we need to update the database first..but this can be done all at once with the -u option...

--> ./install_pkgs -u kodi.lst chkrootkit
Downloading data files...
 HTTP:mirrors.kernel.org/slackware/slackware64-14.2
   700K .......... .......                                    100% 1.69M=0.5s
     0K .......... .......... .......... .......... ......    100%  426K=0.1s
     0K                                                       100% 24.9M=0s
 HTTP:slackonly.com/pub/packages/14.2-x86_64
  3100K .......... .......... .......... .........            100%  881K=3.2s
 HTTP:localhost/Slackbuilder-x86_64-14.2
   850K .......... .......... .........                       100%  167M=0.006s
Building sqlite database...

root /mnt/installdir
%%%%%%%%%%% libdvdcss is up-to-date
%%%%%%%%%%% libmicrohttpd up-to-date
%%%%%%%%%%% yajl is up-to-date
%%%%%%%%%%% crossguid is up-to-date
%%%%%%%%%%% dcadec is up-to-date
%%%%%%%%%%% libmpeg2 is up-to-date
%%%%%%%%%%% libass is up-to-date
%%%%%%%%%%% jdk is up-to-date
%%%%%%%%%%% kodi is up-to-date
%%%%%%%%%%% chkrootkit install
at the location /tmp/my_cache/14.2-x86_64
   300K ..                                                    100% 4239G=0.3s
Verifying package chkrootkit-0.50-x86_64-1_slonly.txz.
Installing package chkrootkit-0.50-x86_64-1_slonly.txz:
PACKAGE DESCRIPTION:
# chkrootkit (Check Rootkit)
#
# chkrootkit is a common unix-based program intended to help system
# administrators check their system for known rootkits. It is a shell
# script using common UNIX/Linux tools like the strings and grep
# commands to search core system programs for signatures and for
# comparing a traversal of the /proc filesystem with the output of
# the ps (process status) command to look for discrepancies.
#
# Homepage: http://www.chkrootkit.org
#
Package chkrootkit-0.50-x86_64-1_slonly.txz installed.

Notice that since I already installed the packages in kodi.lst it shows everything is up-to-date, But the extra package on the end gets installed.

svrsn is a command that is part of the slackerson-utils package. It provides ARCH SVRSN SUFFIX and RCH environment variables and is used throughout the SlackBuilder tools. Here is what it provides...

--> svrsn
ARCH=x86_64 SVRSN=14.2 SUFFIX=64 RCH=x86_64

RCH provides the variable for the slackonly SRC line. This variable is needed for sources that use x86 to represent a 32bit ARCH. You can define the ARCH variable on the command line. Notice how everything changes for a 32bit architecture....

--> ARCH=i686 svrsn
ARCH=i686 SVRSN=14.2 SUFFIX= RCH=x86

As you have probably noticed I have been using a x86_64 ARCH as my host system for all my examples. But you can install a 32bit system from a 64bit host by changing the ARCH variable. Of course you can change any of the other variables if need be.

Summary

With this script we now have a no nonsense command that can install multiple package list files and/or single packages as arguments. By creating another script that calls it with a predefined set of package list files you can install a complete OS with one command. Of course you would still have to configure the installation and such. This is how 'getpkgs' sort of works but it uses packages lists attached to a SRC defined in /etc/slkn-setup/SRC.

A new command is born

The 'install_pkgs' command above has limited use and is not as robust as using 'getpkgs' for an installation method. It is just a teaser to demonstrate the concept on how to script with the package manager tool. But with a little modification it can be turned into an actual useful command for the system.

pkg-get is an interactive command that will take a single package name as an argument. It will install the package and its dependencies after verifying each one to determine its installation status ( to install, upgrade, or pkg is up-to-date ). Then asks if you want to continue.

It would be nice to have an alternative to 'pkg-get' that will..

  • take multiple arguments ( but no files )
  • and for each one install it along with its recursive dependencies
  • without having to prepare a pkg.lst file first
  • and will do so no questions asked

We can eliminate the extra task of preparing a file by incorporating the 'ldeps' command in the script. I also want to remove the ability to supply a file as an argument to avoid any overhead of trying to process too many dependencies. In case a package is listed in the file that has already been installed as a dependency of a previously listed package. Package lists can get pretty long so no need for any of that. In that same spirit we should also eliminate the same effect from CLI provided arguments that may share dependencies as well.

Normally getpkg updates the database after completing its task. This happens after each call to it. Not after each package has been installed. Consequently if the same package is supplied more than once it will get installed that many times. We need to prevent that by sanitizing the packs list.

Here is the new command....

#!/bin/bash
#
# pkg-getd....
# takes multiple pkgs as arguments and installes each pkg with
# its recursive dependencies
# ----------------------------------------------------------------

while :; do
  case $1 in
    -u) pkg-u 
        shift
      ;;
  esac
  break
done

echo "Checking for dependencies..."
for input in $@; do
  [[ -f $input ]] && continue
  Packs+="$(ldeps -s $input) "
  Packs+="$input "
done

# if two or more pkgs share dependecies we don't want to install the same pkg multiple 
# times so...remove multiple occurances and rebuild list...
echo "sanitizing dependency list..."
Packs=$(echo $Packs  | tr ' ' '\n' | sed -e '/^$/d' -e 's/^/%/;s/$/%/')
for pkg in ${Packs}; do
  Packs=$(echo $Packs | sed -e 's/'"$pkg"'//g')
  Packs+="$pkg "
done
packs=$(echo $Packs | sed -e 's/%%/ /g;s/%//g')

for pks in $packs; do
  echo $pks
done

[[ $packs ]] && getpkg $packs

It doesn't really need the while loop to update. But it's nice to have if you want to change the environment variables mntpt, SRC or CACHE and an update is necessary.

Here it is in action with the call to 'getpkg' commented out....

--> time ./pkg-getd kodi
Checking for dependencies...
libdvdcss
libmicrohttpd
tinyxml
yajl
crossguid
dcadec
libmpeg2
libass
jdk
kodi

real  0m0.324s
user  0m0.226s
sys 0m0.099s


Versus 'pkg-get'

--> time pkg-get kodi

Pkg-get...
--------------------------------------------------------------------------------
Dependency-Check => kodi
Finding recursive dependencies for....kodi
Done!                          
There are 10 dependencies to verify

libdvdcss is up-to-date
libmicrohttpd is up-to-date
tinyxml is up-to-date
yajl is up-to-date
crossguid is up-to-date
dcadec is up-to-date
libmpeg2 is up-to-date
libass is up-to-date
jdk is up-to-date
kodi is up-to-date


There are 0 pkgs to be installed/upgraded....
--------------------------------------------------------------------------------

real  0m0.763s
user  0m0.449s
sys 0m0.227s


Notice it is a little over twice as fast collecting the dependency list. But 'pkg-get' pre preps the list and will only feed 'getpkg' packages that need to be installed or upgraded. The new 'pkg-getd' will send 'getpkg' everything and let it do the verifying which will actually take longer when complete.

Here it is with 'getpkg' line uncommented to demonstrate the time difference.

--> time ./pkg-getd kodi
Checking for dependencies...
libdvdcss
libmicrohttpd
tinyxml
yajl
crossguid
dcadec
libmpeg2
libass
jdk
kodi
root /
%%%%%%%%%%% libdvdcss is up-to-date
%%%%%%%%%%% libmicrohttpd is up-to-date
%%%%%%%%%%% tinyxml is up-to-date
%%%%%%%%%%% yajl is up-to-date
%%%%%%%%%%% crossguid is up-to-date
%%%%%%%%%%% dcadec is up-to-date
%%%%%%%%%%% libmpeg2 is up-to-date
%%%%%%%%%%% libass is up-to-date
%%%%%%%%%%% jdk is up-to-date
%%%%%%%%%%% kodi is up-to-date

real  0m4.441s
user  0m2.737s
sys 0m0.741s

Since there are no packages to install 'pkg-get' completes its job faster. If there is a long list of packages to install then 'pkg-getd' at this point can be very time consuming.

Improving performance

I'll go ahead and add a loop to verify the packages to ease the burden on 'getpkg'. There is a command verifypkg shipped with the pkg-tools package just for this purpose. And I might as well add in a usage bit too while I'm at it.

#!/bin/bash
#
# pkg-getd....
# takes multiple pkgs as arguments and installes each pkg with
# its recursive dependencies
# ----------------------------------------------------------------

USAGE="
  $(basename $0) [Option] [pkg(s)]
  (Requires at least one pkg as an argument)

  [Options] 
    -u (update the pkg database)
  
  Install pkg(s) and its recursive dependencies

";

[[ "$#" -eq 0 ]] && {
  echo "$USAGE";
  exit
}

# update database
while :; do
  case $1 in
    -u) pkg-u
        shift
      ;;
  esac
  break
done

# get deps
echo ""
echo "Checking for dependencies..."
for input in $@; do
  [[ -f $input ]] && continue
  Packs+="$(ldeps -s $input) "
  Packs+="$input "
done

# if two or more pkgs share dependecies we don't want to install the same pkg multiple 
# times so...remove multiple occurances and rebuild list...
echo "sanitizing dependency list..."
Packs=$(echo $Packs  | tr ' ' '\n' | sed -e '/^$/d' -e 's/^/%/;s/$/%/')
for pkg in ${Packs}; do
  Packs=$(echo $Packs | sed -e 's/'"$pkg"'//g')
  Packs+="$pkg "
done
Packs=$(echo $Packs | sed -e 's/%%/ /g;s/%//g')

# verify packages
echo "verifying packages..."
hr="-----------------------------------------------------------------"
echo $hr
for pkg in ${Packs}; do
  method=`verifypkg ${pkg}`
  case ${method} in
    upgrade)
      packs+="$pkg ";
      echo "$pkg will be upgraded";
    ;;
    install)
      packs+="$pkg ";
      echo "$pkg will be installed";
    ;;
    uptodate)
      echo "$pkg is up-to-date";
    ;;
    nosrc)
      echo "$pkg has nosrc"
    ;;
    nopkg)
      echo "No such package $pkg";
    ;;
  esac
done
echo $hr

[[ $packs ]] && getpkg $packs

'pkg-get' still performs better due to a more sophisticated dependency checking routine. But we have gotten quite a bit more umph over 'getpkg' alone.

--> time ./pkg-getd kodi
Checking for dependencies...
sanitizing dependency list...
verifying packages...
-----------------------------------------------------------------
libdvdcss is up-to-date
libmicrohttpd is up-to-date
tinyxml is up-to-date
yajl is up-to-date
crossguid is up-to-date
dcadec is up-to-date
libmpeg2 is up-to-date
libass is up-to-date
jdk is up-to-date
kodi is up-to-date
-----------------------------------------------------------------

real	0m1.324s
user	0m1.130s
sys	0m0.643s

Wrapping up

As you can see it is a fairly trivial matter to slap a command together to meet our whim. By incorporating 4 pkg-tools commands ( pkg-info, ldeps, verifypkg, getpkg ) and a little logical glue we have managed to create a rather sophisticated command that rivals the most popular package managers in function.

Performance? Uhh. Not so sure. With 10 or less packages supplied as arguments, yes. But if you throw tens of packages at it, each with moderately long dependency lists, the verification process can be quite time consuming and more than a little annoying. Escpecialy when those packages start sharing dependencies. This is why I limited 'pkg-get' to 1 argument in the first place.

A different verification paradigm would need to be implemented to deal with very large package lists which could reach into the 100's or even 1000's. In that event bulk file processing is the best choice.

Suggested use

pkg-getd is best used with 10 or less packages supplied as arguments.

Note: This command gets right to work no questions asked. Use it responsibly. It is not a search tool !

Comment in the Forum.

© 2015 - 2023  -   SlackBuilder  -   All Rights Reserved.

By: Lance Peterson -- Slackerson