Cacti in Tiger Server

Install XCode

Install and configure darwinports

Download the newest version from macosforge.

Add the darwinports paths to your shell config file. e.g.


Update the ports collection

sudo port -d selfupdate

Install rrdtool from darwinports

Execute the following to install rrdtool and all of its dependencies for you.

sudo port install rrdtool

Local user setup

Create a local cacti user and a home directory for it. In your Terminal window, su to this new user and then move to the cacti home directory

andre@casa[~]su cacti 
casa:/Network/Servers/ cacti$ cd ~ 
casa:~ cacti$

Download cacti from and decompress the archive

casa:~ cacti$ curl -O 
% Total    % Received % Xferd  Average Speed   Time    Time     Time  Current 
                                Dload  Upload   Total   Spent    Left  Speed
100 1051k  100 1051k    0     0   184k      0  0:00:05  0:00:05 --:--:--  216k 
casa:~ cacti$ gunzip cacti-0.8.6g.tar.gz 
casa:~ cacti$ tar -xf cacti-0.8.6g.tar 
casa:~ cacti$ cd cacti-0.8.6g 
casa:~/cacti-0.8.6g cacti$

Create a symlink to the cacti directory from the web document root (do this as an admin user)

andre@casa[~]ln -s ~cacti/cacti-0.8.6g /Library/WebServer/Documents/cacti

Inititalize MySQL

Use the MySQL Manager application to install and enable mysql. You do not need to enable network connections. As an alternative to the MySQL Manager, do the following as an admin user:

sudo mysql_install_db 
sudo chown -R mysql /var/mysql 
sudo chmod +rx /var/mysql

Edit /etc/hostconfig, adding


Start MySQL

sudo SystemStarter start MySQL

Set the mysql root password

sudo mysqladmin -u root password 

Create the cacti database

mysqladmin --user=root -p create cacti

Import the cacti database (as the cacti user while inside the cacti source folder)

casa:~/cacti-0.8.6g cacti$ mysql -u root -p cacti < cacti.sql

Create the cacti mysql user

mysql -u root -p mysql 
GRANT ALL ON cacti.* TO cacti@localhost IDENTIFIED BY 'password';

Configure Apache and PHP

Enable the php module in Apache. This can be done either in the "Modules" portion of the Web settings in Server Admin, or by editing the /etc/httpd/httpd.conf file and uncommenting these two lines:

LoadModule php4_module           libexec/httpd/
AddModule mod_php4.c

Start the Web service using Server Admin

This will start Apache and configure it to start at system boot time. As an alternative to Server Admin for enabling Apache, start or restart apache using apachectl:

sudo apachectl graceful

Verify that apache will start at system boot time by editing /etc/hostconfig to include:


Cacti configuration

As your cacti user, while inside the cacti source directory, edit include/config.php to include the apporiate details for making mysql connections. e.g.

$database_type = "mysql"; 
$database_default = "cacti"; 
$database_hostname = "localhost"; 
$database_username = "cacti"; 
$database_password = "pass";

Configure the cacti user's crontab

Use a crontab configuration such as:

echo "*/5 * * * * php /Library/WebServer/Documents/cacti/poller.php > /dev/null 2>&1" | crontab

Cacti web-based setup

Hit the cacti page and proceed with the web-based setup, e.g. Advance through the first screen, and at the next, choose "new install". Change the binary location for rrdtool if necessary. It should be at /opt/local/bin/rrdtool. Once the setup is complete, log in as admin / admin and change password. Be sure to change the rrd tool version to 1.2.x in the Configuration --> Settings menu.

Extending Cacti

Once installed, you may wish to create custom scripts in order to monitor / graph things that are not accounted for by default templates.

Because netsnmp in darwin (edit: even still, as of tiger) doesn't report on cpu utilization in the . tree (basically I'm looking for user | system | idle), I had to write my own scripts to produce this data.

Here's one I'm calling ''; it's placed in ~/bin.

#!/usr/bin/perl -w 
# get iostat output 
chomp ($cpuinfo = `iostat -C -d -n 1 -c 2 | tail -n 1 | awk '{print \$4 " " \$5 " " \$6}'`); 
@cpuinfo = split(/\s/, $cpuinfo); 
#print "1 is $cpuinfo[0], 2 is $cpuinfo[1], 3 is $cpuinfo[2]\n"; 
$user = $cpuinfo[0]; 
$system = $cpuinfo[1]; 
$idle = $cpuinfo[2]; 
if ($system == "0100") { 
  print "0\n0\n100\n";
  } else {
  print "$user\n$system\n$idle\n";

Note the -c = 2 in the iostat invocation. If you only get one sample, iostat reports values that are averaged from boot time, which is not what we want. We're looking for more of a gauge style value, so the second sample is averaged over the last 1 second, which is fine. I'm also using -n 1 to restrict the number of monitored disks to exactly 1; we need this to be sure of the relative locations of the fields we actually do need (which are normally printed after the disk stats); if there were more disks, the fields we need would no longer be 4, 5 and 6. To complicate matters, if the system is 100% idle (don't ask me how that occurs while this script is running, but it does), iostat will report 0 0100 instead of 0 0 100, thus causing $system to contain 0100 and $idle to be undefined; hence the conditional at the end.

Also note that the scripts produce multi-line output, with one value per line.

Now that we have a functional "" sript, we can edit snmpd.conf to add:

exec cpumon /Users/andre/bin/

Because we are specifying an OID in the exec line, snmpd will put the resulting output into a 'table', rooted at the given OID. This basically means that each line of script output will be placed into an OID beneath the given one. ... and the resulting OIDs are:


... and if we query those OIDs:

andre@IP41-89[~]snmpget -c blah -v 1 
. . . 
UCD-SNMP-MIB::extOutput.101.1 = STRING: 2 
UCD-SNMP-MIB::extOutput.101.2 = STRING: 8 
UCD-SNMP-MIB::extOutput.101.3 = STRING: 90

... it does exactly what we want. .1 is user, .2 is system, and .3 is idle

Okay, getting closer. Now we have three OIDs to query for each of the three values related to CPU usage.

Now we have to create new data templates to point at our new OIDs. It's not all that easy to create new templates, it seems, so it's easier to duplicate an existing data template; makes sense to start with the ucd template for 'nice' cpu, for example. After duplicating that template with a new name (darwin-cpu-idle), we need to modify our new template to point at the OID for idle, which is . Also, feel free to change the 'internal data source name' to something unique, such as darwin_cpu_idle. Verify that the type is set to GAUGE and the query type is Get SNMP Data.

Duplicate your new template twice more for the 'system' and 'user' OIDs, changing the OID and names as appropriate.

Now we're ready to head into "Data Sources" and set up three new sources for each of the three new values we're monitoring. Create three new sources, set the "Selected Data Template" to one of the three new templates you created (they should appear in the popout menu), and change the names as necessary. Associate the source with one of your existing polling hosts for maximum ease.

Before we build the graph, we need to modify the existing CPU Usage graph template. The template expects system, user and nice, but we have system, user and idle. Duplicate the "ucd/net - CPU Usage " template, and then edit it. Rename the "nice" column to "idle", and delete the last 4 "Graph Template Items" - they correspond to "total cpu", which we don't have. (Actually I prefer to delete idle and total, so that only system and user are graphed). Modify all of the items in the graph template to use the appropriate data sources that we created earlier. Do this by clicking on "Item # 1" under the "Graph Item" column heading, and then choosing the appropriate data source from the popout menu.

Now, finally, we are ready to actually build the graph. The good news is that by this point, you should already have collected some data :) Head over to "Graph Management", click "Add", select your new graph template and choose a host from the list. Set the "graph item inputs" to each correspond to the appropriate data source. That should be it!

Finally, thanks to axon for his innane knowledge of the ascii characterset :)

I have uploaded the Mac OS X host template file which includes all the dependencies. This should give you all the cacti configuration you need to monitor mac os x hosts for cpu, # of TCP connections, and # of NetInfo connections (I'm sure that last one will be super useful for ya ;). This template represents the cacti side of the configuration; you still need to set up the snmpd.conf files and the scripts to gather the necessary date. Examine the new data templates to make sure that the output from the scripts you call from snmpd.conf goes to the right OIDs.

About dre

I like all kinds of food.
This entry was posted in OS X, OS X Server, tutorials. Bookmark the permalink.

3 Responses to Cacti in Tiger Server

  1. HouseCentipede says:

    I have found your to be exactly the thing I needed to get the Orion Network Performance Monitor to keep track of an OS X server. However, I’m wondering if you have any other scripts that would be useful, like a disk or memory monitor, since it doesn’t seem to be reporting them properly.


  2. dre says:

    HouseCentipede: glad it has been useful :)

    Here’s a script to get memory data. Output order is: free, active, inactive, wired, pageIns, pageOuts.

    Disk utilization data is reported in snmpd, at least on my system (mac pro). Look under HOST-RESOURCES-MIB. If you snmpwalk HOST-RESOURCES-MIB::hrStorageDescr you should see a list of storage devices. There are corresponding MIBs in that tree called hrStorageSize and hrStorageUsed. Index numbers (the last dot-separated component of a given OID) are used to relate multiple OIDs to the same device, e.g. if I found a disk at

    the corresponding capacity / utilization for that device would be at

  3. HouseCentipede says:

    You’re my hero. Thanks again!

Leave a Reply