CS615A -- Aspects of System Administration - Spring 2011 - HW#2 - Sample Solution

HW#2: Package Management on different OS

Summary

On this page you will find a sample solution for HW#2. In particular, you will find the annotated script(1) output for the assignment on the Fedora instance. (Note: This is actually the annotated output from 2010 (which many of you have already found and used to help you with your assignment, though none of you mentioned it). The full, unannotated output from the instances used in 2011 can be found in these files: fedora, ubuntu and solaris. Each file illustrates a number of different issues encountered.)

toggle all segments

SSH configuration

In this code segment, you can see my ~/.ssh/config that allows me ssh to the EC2 hosts without having to specify what user or what key to use. Since the hostkeys for these hosts are unknown or changing, there is no point in me trying to retain them in ~/.ssh/known_hosts or enforce strict hostkey checking.
[show code segment] [toggle all code segments]

Instance creation

In this code segment, you can see the relevant environment variables and the commands I ran to create the Fedora instance.
[show code segment] [toggle all code segments]

Native package installation

In this code segment, you can see the command(s) run to install the packages using the native package manager, yum.
[show code segment] [toggle all code segments]

Native package installation -- sipcalc

In this code segment, you can see the command(s) run to install the package "sipcalc". This package was not available in the default YUM repository, so we had to try to find a suitable package elsewhere. The website rpmfind can at times be used to find binary packages built by other people. Instead of using yum, we now use the rpm command to install the binary package.
[show code segment] [toggle all code segments]

Installation of pkgsrc

In this code segment, you can see the command(s) run to install pkgsrc.
[show code segment] [toggle all code segments]

pkgsrc -- building anything

In this code segment, you can see the command(s) attempted to install our first package from source using pkgsrc. Somewhat discouragingly, it will immediately fail, as we neglected to carefully read the documentation, which told us that we might need to install another library before we could use pkgsrc.

[show code segment] [toggle all code segments]

pkgsrc - installing ncurses-devel

Alright, so we need to install the ncurses-devel package, again using yum:
[show code segment] [toggle all code segments]

pkgsrc -- building gcc

Now that we have the required curses library, we can start to try to install the packages requested in the assignment. Let's start with "gcc".

In this code segment, you can see the command(s) attempted to install lang/gcc using pkgsrc. Note that this would build and install gcc version 2.95.x; our native compiler previously installed using yum is gcc version 4.1 -- a significant difference, as we will learn.

[show code segment] [toggle all code segments]

Different compilers implement different language standards. Newer compilers, while frequently trying to retain backwards compatibility, need to at times enforce certain new standards that will break older packages or older code. If we really wanted to build gcc-2.95 on this host, we would first have to install a compiler capable of building gcc-2.95. The backwards compatibility was, apparently, broken at some point after gcc version 3. So we'll proceed to build that compiler...

pkgsrc - building gcc34

Unlike gcc-2.95, our 4.x based compiler does not seem to have any issues building gcc-3.4.x. Note that in this case we are actually building a number of packages -- one for each language the compiler chain supports. The "gcc34" package itself does not actually install any files: it only depends on the other packages and thusly causes them to be built. This is what is known as a "meta-package".
[show code segment] [toggle all code segments]

pkgsrc - building perl

Phew, now lets move on and try to build perl...
[show code segment] [toggle all code segments]

Note here that we can give several "targets" in a single "make" invocation. In this case, we tell pkgsrc to not only install the package, but also to "clean" any of the dependencies that were built as well as to "clean" (ie remove any temporary object files) of the "perl5" package.

pkgsrc - building python

Well, since building perl was so easy, surely building python will be trivial as well! Let's give it a go...

[show code segment] [toggle all code segments]

Hmmm, so that didn't work out so well. Now let's consider that we did install a different compiler earlier, maybe the system compiler is making things difficult again for us? Let's try to tell pkgsrc to use the gcc-3.x compiler in favor of the system's gcc-4.x compiler:
[show code segment] [toggle all code segments]

Hmmm, so we did get a bit further. Our build failed in a different place, but obviously we still weren't successful. Now what?

In the process of installing the various tools used to build software from source, the "libtool" utility is used to invoke the compiler or linker with the appropriate flags. It installs a number of shell script wrappers around the compiler. But when we first started building packages, the "libtool" package was created using the system's compiler. Hence, it will continue to try to use that compiler in favor of what we instructed the system to use. Oy!

So... let's try to delete this magic package. If it's needed, it will be pulled in as a dependency and be rebuilt, this time using the correct compiler.
[show code segment] [toggle all code segments]

Now let's remember to clean up any partially built dependencies to ensure that the next time we attempt to build this package, we get the correct compiler and the correct libtool. Then, let's try again:
[show code segment] [toggle all code segments]

Hooray! Note that pkgsrc did rebuild "libtool", then rebuilt (successfully) "db4", and finally built and installed python. But was all this really necessary?

No, it was not. :-) Another way to get this to work would have been by adding the appropriate "gcc-c++" package using yum. Remember how we noticed that the gcc3 package installed numerous packages? In our very first step, when we first invoked yum to install the "gcc" package, that did not actually install the full compiler suite -- it only installed the C compiler (and libraries). The initial error generated by the "db4" package was:

configure: error: C++ preprocessor "/lib/cpp" fails sanity check
Notice that it says C++ preprocessor and not "C preprocessor". This was a sign that our C++ development environment was not complete. If we had additionally used yum to install the "gcc-c++" package at the very beginning (ie before bootstrapping pkgsrc), we would have never run into this error, as the provided C++ compiler chain would have caused the build of "db4" to simply succeed.

pkgsrc - installing the remaining packages

Almost all of the remaining packages worked out without a problem. Notice that in the code segment below we use a simple shell trick to allow us to find the correct location of the package we wish to install without having to know the sub directory: since every package in pkgsrc is named uniquely, we can just let the shell wildcard character "*" fill in the correct sub directory.
[show code segment] [toggle all code segments]

But hey, wait a second... didn't some of you run into issues building sipcalc? Some of you had to specify additional "package options" on the command-line to cause it to build. Why does it work out for me?

Well, after trying to build the packages myself, I noticed the problem you ran into. Considering that this is not particularly userfriendly and should just work out of the box, I reported the error to the pkgsrc maintainers, who fixed it. When I fetched the pkgsrc tarball, I got a version where this error was already no longer present.

This nicely illustrates that it's useful and desirable to report any problems one runs into to the software maintainers. These bug reports are what make any open source software better.

pkgsrc - building binary packages

In order to build binary packages of the software you installed using pkgsrc, you basically have two options. One way to do this is to use the 'bmake package' command in the directory from which you installed the package. The problem with that is, though, that this will only create a binary package of the software in question, not of all the required dependencies. If you then took this one package to install it on another host, you'd be missing the dependencies and would thus not be able to install it.

A way around this would be ensure that all dependencies also build binary packages would be to set the DEPENDS_TARGET in /etc/mk.conf to 'package' to ensure that all dependencies also build packages. However, you still have the disadvantage of having to actually build and install the whole package again if you want to 'make package' (if you did run 'make clean' after the installation, anyway).

The second approach is to create a binary package from the installed manifest. To do that, you would use the pkg_tarup tool:
[show code segment] [toggle all code segments]

After building the binary packages, you can scp(1) them to another host and add them via pkg_add(1).

Installing apache by hand

In this code segment you see the installation of apache "by hand". That is, we first fetch the code from the website (or the recommended mirror), extract it, run configure with the appropriate flags, then run make followed by make install. Since all pre-requisites or dependencies are already available on our system, we do not need to manually fetch and build anything else.
[show code segment] [toggle all code segments]

Package dependencies

It is sometimes nice to visualize the dependencies of all installed packages. The following code segment shows you how you could do this using tools provided by pkgsrc.
[show code segment] [toggle all code segments]

The pkgdepgraph package creates a "dot-language" description of the dependency graph. This graph can be visualized using the tools from the graphviz package. The resulting graph is available here. The dot-language graph description itself is available here.

I also did the same steps above on a new instance where I did not use the gcc3 package and instead used yum to install the gcc-c++ package. The resulting dependency graph is slightly less complex, and available here. The dot-language graph description itself is available here.


[Course Website]