Printing the contents of a static library

While debugging a static linking problem this weekend, I needed to see which files were included in a static library. This can be accomplished with the ar(1) utilities “-t” (print table of contents) option:

$ ar -vt /usr/lib/libnsl.a | head 5
rw-rw-r--     0/     1   1752 Aug 13 10:16 2004 common.o
rw-rw-r--     0/     1   4868 Aug 13 10:16 2004 nsl_stdio_prv.o
rw-rw-r--     0/     1   3304 Aug 13 10:16 2004 des_crypt.o
rw-rw-r--     0/     1  25852 Aug 13 10:16 2004 des_soft.o
rw-rw-r--     0/     1  49088 Aug 13 10:17 2004 dial.o

If you need to extract a specific object file from a static library, you can invoke ar(1) with the “-x” option:

$ ar -vx /usr/lib/libnsl.a dial.o

$ ls -la dial.o
-rw-r--r--   1 root     other      49088 Apr 25 16:17 dial.o

In case your interested, “-v” forces the archiver to produce verbose output. I am somewhat saddened that Solaris 10 will no longer support static libraries (though I understand why).

Siege web benchmarking utility

While I am waiting for Apache to build with the libtool –debug option, I thought I would share my thoughts on the siege utility. Siege is an open source HTTP regression and debugging utility. I have used curl and ab in the past to debug and benchmark websites, but prefer siege, since it allows me to debug and benchmark websites with a single well written utility. To debug the HTTP requests to a server, you can run run siege with the “-g” (Grab headers) and “-u” (URL to grab) option:

$ siege -g -v -u https://prefetch.net

** siege 2.62
** Preparing 1 concurrent users for battle.
The server is now under siege...
GET / HTTP/1.0
Host: prefetch.net
Accept: */*
Accept-Encoding: *
User-Agent: JoeDog/1.00 [en] (X11; I; Siege 2.62)
Connection: close


HTTP/1.1 200 OK
Date: Thu, 14 Apr 2005 23:35:19 GMT
Server: Apache/2.0.52
Set-Cookie: Horde=b18606e131eb443ce6557c790ed17bdd; path=/; domain=prefetch.net
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Pragma: no-cache
Connection: close
Content-Type: text/html; charset=ISO-8859-1

This displays a summary of the request/entity headers for the entire HTTP transaction, and is super useful for debugging. To simulate 5-users hitting a website with a delay between successive page loads, siege can be run with the “-c” (user count), “-r” (number of times to run the test), and “-d” (add delay between 1 and the option passed to “-d”) options:

$ siege -b -v -c 5 -r 5 -d 10 -u https://prefetch.net

** siege 2.62
** Preparing 5 concurrent users for battle.
The server is now under siege...
HTTP/1.1 200   0.57 secs:     578 bytes ==> /
HTTP/1.1 200   0.66 secs:     578 bytes ==> /
HTTP/1.1 200   0.76 secs:     578 bytes ==> /
HTTP/1.1 200   0.76 secs:     578 bytes ==> /
HTTP/1.1 200   0.95 secs:     578 bytes ==> /
HTTP/1.1 200   0.74 secs:     500 bytes ==> /
HTTP/1.1 200   0.95 secs:     500 bytes ==> /
HTTP/1.1 200   0.90 secs:     500 bytes ==> /
HTTP/1.1 200   0.65 secs:     500 bytes ==> /
HTTP/1.1 200   0.95 secs:     500 bytes ==> /
HTTP/1.1 200   0.66 secs:     500 bytes ==> /
HTTP/1.1 200   0.67 secs:     500 bytes ==> /
HTTP/1.1 200   0.98 secs:     500 bytes ==> /
HTTP/1.1 200   0.98 secs:     500 bytes ==> /
HTTP/1.1 200   1.18 secs:     500 bytes ==> /
HTTP/1.1 200   0.68 secs:     500 bytes ==> /
HTTP/1.1 200   0.83 secs:     500 bytes ==> /
HTTP/1.1 200   0.80 secs:     500 bytes ==> /
HTTP/1.1 200   0.85 secs:     500 bytes ==> /
HTTP/1.1 200   0.73 secs:     500 bytes ==> /
HTTP/1.1 200   0.45 secs:     500 bytes ==> /
HTTP/1.1 200   0.78 secs:     500 bytes ==> /
HTTP/1.1 200   0.56 secs:     500 bytes ==> /
HTTP/1.1 200   0.62 secs:     500 bytes ==> /
HTTP/1.1 200   0.73 secs:     500 bytes ==> /
done.
Transactions:                     25 hits
Availability:                 100.00 %
Elapsed time:                   4.28 secs
Data transferred:               0.01 MB
Response time:                  0.78 secs
Transaction rate:               5.84 trans/sec
Throughput:                     0.00 MB/sec
Concurrency:                    4.53
Successful transactions:          25
Failed transactions:               0
Longest transaction:            1.18
Shortest transaction:           0.45

The Failed transactions, Response time, and Longest and Shortest transactions statistics can be used to profile a website, and to get an accurate picture of the time it takes to process a transaction. Siege also allows you to define a slew of URLs in a file called urls.txt, which will be processed during a connection from each user. I would like to thank Jeffrey Fulmer for writing the software! Make sure to check out his article in this month’s SysAdmin magazine.

Solaris B_FAILFAST messages

After patching my box a few months back, I noticed the following messages on the console after I rebooted:

Apr 15 15:23:15 winnie md_mirror: [ID 437521 kern.info] NOTICE: md: d1: B_FAILFAST I/O disabled
Apr 15 15:23:15 winnie md_mirror: [ID 437521 kern.info] NOTICE: md: d2: B_FAILFAST I/O disabled
Apr 15 15:23:15 winnie md_mirror: [ID 437521 kern.info] NOTICE: md: d1: B_FAILFAST I/O disabled
Apr 15 15:23:15 winnie md_mirror: [ID 437521 kern.info] NOTICE: md: d2: B_FAILFAST I/O disabled

Due to the nature of the message, I grew somewhat frantic, and began feverishly scouring the Internet for answers. It didn’t take long to stumble across the following Sunsolve article. According to sunsolve, these are not errors, and the metadevices are not faulted:

“These are not errors. These are informational (NOTICE) messages telling you that the driver underlying your metadevices does not support the B_FAILFAST option and, as a result, that capability will not be active for speedier recovery. There is no way to disable these messages.”

C pre processor

I am knee deep in debugging another SEGFAULT issue, and was given a cool tip by my friend Clay this weekend. When you see lots of #ifdef, #ifndef, and #endif’s in a source file, you can see what the C pre-processor will produce by running the source through the C pre-processor command (cpp):

$ cat ack.c

#include

#ifdef SOMETHING
typedef int blah;
#endif

#ifdef SOMETHING_ELSE
typedef long foo
#endif

int main(void) {

int m = 5;

printf(“%d\n”,m);
}

$ cpp -DSOMETHING ack.c

[ … ]

typedef int blah;

int main(void) {

int m = 5;

printf(“%d\n”,m);
}

I removed all the standard includes to simplify the example. This is super useful!

Solaris logfile rotation utilities

The logadm(1m) utility comes with the Solaris Operating System, and allows system and application logfiles to be rotated at configurable intervals. logadm(1m) is controlled through the logadm.conf configuration file, which contains the logfiles to rotate, and information to describe how to rotate the logfiles. When I need to add new entries to the logadm.conf configuration file, I usually invoke logadm(1m) with the following options:

-w  ENTRY    - Write an entry to logadm.conf
 -a           - Command to run after a logfile has been rotated
 -b           - Command to run before a logfile is rotated
 -C COUNT     - Number of logfiles to keep around
 -e EMAIL     - Send an email to EMAIL with the results
 -o OWNER     - Change the owner to OWNER after rotating the file
 -g GROUP     - Change the group to GROUP after rotate the file
 -m PERMS     - Set the permissions to PERMS after rotate the file

In addition to these flags, there are dozens of available options
to control where logfiles are stored after they are rotated, the format
logfiles will be stored in, and several directives to control when a
file is rotated (e.g., when a file is bigger than size, or after X
days/weeks/months). The following example can be used to rotate the IP
filter logfiles daily:

$ logadm -w ipflog -C 30 -o sys -g sys -m 600 /var/log/ipflog
-a ‘kill -HUP `cat /var/run/syslog.pid’

This will keep thirty copies of ipflog, set the owner and group to sys,
and restart syslogd after the logfiles are rotated. logadm(1m) will
run each day at 3:10am, and provides the “-p” option to rotate logfiles
at specific points in time. The following example will rotate the
IP filter logfiles now:

$ ls -al /var/log/ipf* | head -3

-rw-------   1 sys      sys        65316 Apr  5 10:05 /var/log/ipflog
-rw-------   1 sys      sys            0 Apr  5 09:47 /var/log/ipflog.0
-rw-r--r--   1 root     root     103495791 Apr  5 09:49 /var/log/ipflog.1

$ logadm -p now ipflog

$ ls -al /var/log/ipf* | head -3

-rw-------   1 sys      sys          149 Apr  5 10:05 /var/log/ipflog
-rw-------   1 sys      sys        65316 Apr  5 10:05 /var/log/ipflog.0
-rw-------   1 sys      sys            0 Apr  5 09:47 /var/log/ipflog.1

logadm(1m) also supports regular expressions, so entries similar to
the following are possible (this item came from the logadm man page):

/var/apache/logs/*{access,error}_log

This is a nifty little utility.

Automating Solaris patch installations

Solaris 10 now ships with the patchpro suite of utilities, which assist with analyzing and applying Operating System patches. Patchpro makes patch installation super easy, since you are not required to download recommended bundles, or dig through patchdiag information to find the “required” patches. The patchpro smpatch(1m) utility can be run with the analyze option to compare the current set of patches from updateserver.sun.com with what is installed on a server:

$ smpatch analyze

119145-01 SunOS 5.10: usr/snadm/lib Patch
119042-02 SunOS 5.10: patch usr/sbin/svccfg
117463-02 SunOS 5.10: passwdutil Patch
119143-02 SunOS 5.10: patch lib/libinetutil.so.1
118822-01 SunOS 5.10: kernel Patch

If you want decided to download and install each patch listed by the analyze option, you can run smpatch(1m) with the update option:

$ smpatch update

119145-01 has been validated.
119042-02 has been validated.
117463-02 has been validated.
119143-02 has been validated.
118822-01 has been validated.
Installing patches from /var/sadm/spool...
119145-01 has been applied.
119042-02 has been applied.
117463-02 has been applied.
119143-02 has been applied.
118822-01 has been applied.
/var/sadm/spool/patchpro_dnld_2005.04.07@12:25:28:EDT.txt has been moved to /var/sadm/spool/patchproSequester/patchpro_dnld_2005.04.07@12:25:28:EDT.txt

Each smpatch run produces a logfile with notes on required reboots, and additional instructions:

$ cat /var/sadm/spool/patchproSequester/patchpro_dnld_2005.04.07@12:25:28:EDT.txt

This patch bundle was generated by PatchPro.

Please refer to the README file within each patch for installation
instructions. To properly patch your system, the following patches
should be installed in the listed order:

1) 119145-01
2) 119042-02
3) 117463-02 !!! REBOOT !!!
4) 119143-02 !!! REBOOT !!!
5) 118822-01 !!! REBOOT !!!

If you want to view the smpatch(1m) configuration options, you can run smpatch(1m) with the get option:

$ smpatch get

patchpro.backout.directory - ""
patchpro.download.directory - /var/sadm/spool
patchpro.install.types - rebootafter:reconfigafter:standard
patchpro.patch.source - https://updateserver.sun.com/solaris/
patchpro.patchset - patchdb
patchpro.proxy.host - ""
patchpro.proxy.passwd **** ****
patchpro.proxy.port - 8080
patchpro.proxy.user - ""
patchpro.sun.passwd **** ****
patchpro.sun.user - ""

smpatch(1m) contains a several options in addition to “analyze,” “update” and “get.” The “add” option allows individual patches to be installed, “remove” backs out patches from a system, “download” grabs a patch from “patchpro.patch.source,” and “set and “unset” are used to configure smpatch(1m).