<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Denie&#039;s Tech Blog &#187; Scripting</title>
	<atom:link href="http://blog.nataprawira.com/tech/category/scripting/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.nataprawira.com/tech</link>
	<description>Information Technology for Life!</description>
	<lastBuildDate>Tue, 13 Dec 2011 05:17:04 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.1</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Advanced MRTG Configurations</title>
		<link>http://blog.nataprawira.com/tech/2010/12/02/advanced-mrtg-configurations/</link>
		<comments>http://blog.nataprawira.com/tech/2010/12/02/advanced-mrtg-configurations/#comments</comments>
		<pubDate>Thu, 02 Dec 2010 16:40:30 +0000</pubDate>
		<dc:creator>Denie</dc:creator>
				<category><![CDATA[BASH]]></category>
		<category><![CDATA[CentOS]]></category>
		<category><![CDATA[MRTG]]></category>
		<category><![CDATA[Scripting]]></category>
		<category><![CDATA[Tutorials]]></category>

		<guid isPermaLink="false">http://blog.nataprawira.com/tech/?p=174</guid>
		<description><![CDATA[

Introduction
In many cases using MRTG in a basic configuration to monitor the volume of network traffic to your server isn&#8217;t enough. You may also want to see graphs of CPU, disk, and memory usage. This chapter explains how to find the values you want to monitor in the SNMP MIB files and then how to [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;"><a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fblog.nataprawira.com%2Ftech%2F2010%2F12%2F02%2Fadvanced-mrtg-configurations%2F"><img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fblog.nataprawira.com%2Ftech%2F2010%2F12%2F02%2Fadvanced-mrtg-configurations%2F" height="61" width="51" /></a></div>
<!-- ALL ADSENSE ADS DISABLED -->
<h1 style="color: green;background-color: initial;font-weight: normal;margin-top: 0px;margin-right: 0px;margin-bottom: 0.6em;margin-left: 0px;padding-top: 0.5em;padding-bottom: 0.17em;border-bottom-width: 2px;border-bottom-style: solid;border-bottom-color: #048444;font-size: 24px"><span>Introduction</span></h1>
<p style="margin-top: 0.4em;margin-right: 0px;margin-bottom: 0.5em;margin-left: 0px;line-height: 1.5em">In many cases using MRTG in a basic configuration to monitor the volume of network traffic to your server isn&#8217;t enough. You may also want to see graphs of CPU, disk, and memory usage. This chapter explains how to find the values you want to monitor in the SNMP MIB files and then how to use this information to configure MRTG.</p>
<p style="margin-top: 0.4em;margin-right: 0px;margin-bottom: 0.5em;margin-left: 0px;line-height: 1.5em">All the chapter&#8217;s examples assume that the SNMP Read Only string is craz33guy and that the net-snmp-utils RPM package is installed (see Chapter 22, &#8220;<a title="Quick HOWTO : Ch22 : Monitoring Server Performance" href="http://www.linuxhomenetworking.com/wiki/index.php/Quick_HOWTO_:_Ch22_:_Monitoring_Server_Performance"> Monitoring Server Performance</a>&#8220;).<span id="more-174"></span></p>
<h1 style="color: green;background-color: initial;font-weight: normal;margin-top: 0px;margin-right: 0px;margin-bottom: 0.6em;margin-left: 0px;padding-top: 0.5em;padding-bottom: 0.17em;border-bottom-width: 2px;border-bottom-style: solid;border-bottom-color: #048444;font-size: 24px"><span>Locating And Viewing The Contents Of Linux MIBs</span></h1>
<p style="margin-top: 0.4em;margin-right: 0px;margin-bottom: 0.5em;margin-left: 0px;line-height: 1.5em">Residing in memory, MIBs are data structures that are constantly updated via the SNMP daemon. The MIB configuration text files are located on your hard disk and loaded into memory each time SNMP restarts.</p>
<p style="margin-top: 0.4em;margin-right: 0px;margin-bottom: 0.5em;margin-left: 0px;line-height: 1.5em">You can easily find your Fedora Linux MIBs by using the locate command and filtering the output to include only values with the word &#8220;snmp&#8221; in them. As you can see in this case, the MIBs are located in the /usr/share/snmp/mibs directory:</p>
<pre style="color: black;background-color: #f9f9f9;line-height: 1.1em;padding: 1em;border: 1px dashed #2f6fab">[root@bigboy tmp]# locate mib | grep snmp
/usr/share/doc/net-snmp-5.0.6/README.mib2c
/usr/share/snmp/mibs
/usr/share/snmp/mibs/DISMAN-SCHEDULE-MIB.txt
...
...
[root@bigboy tmp]#</pre>
<p style="margin-top: 0.4em;margin-right: 0px;margin-bottom: 0.5em;margin-left: 0px;line-height: 1.5em">As the MIB configurations are text files you can search for keywords in them using the grep command. This examples searches for the MIBs that keep track of TCP connections and returns the RFC1213 and TCP MIBs as the result.</p>
<pre style="color: black;background-color: #f9f9f9;line-height: 1.1em;padding: 1em;border: 1px dashed #2f6fab">[root@silent mibs]# grep -i tcp /usr/share/snmp/mibs/*.txt | grep connections
...
RFC1213-MIB.txt: "The limit on the total number of TCP connections
RFC1213-MIB.txt: "The number of times TCP connections have made a
...
TCP-MIB.txt:     "The number of times TCP connections have made a
...
...
[root@silent mibs]#</pre>
<p style="margin-top: 0.4em;margin-right: 0px;margin-bottom: 0.5em;margin-left: 0px;line-height: 1.5em">You can use the vi editor to look at the MIBs. Don&#8217;t change them, because doing so could cause SNMP to fail. MIBs are very complicated, but fortunately the key sections are commented.</p>
<p style="margin-top: 0.4em;margin-right: 0px;margin-bottom: 0.5em;margin-left: 0px;line-height: 1.5em">Each value tracked in a MIB is called an object and is often referred to by its object ID or OID. In this snippet of the RFC1213-MIB.txt file, you can see that querying the tcpActiveOpens object returns the number of active open TCP connections to the server. The SYNTAX field shows that this is a counter value.</p>
<p style="margin-top: 0.4em;margin-right: 0px;margin-bottom: 0.5em;margin-left: 0px;line-height: 1.5em">MIBs usually track two types of values. Counter values are used for items that continuously increase as time passes, such as the amount of packets passing through a NIC or amount of time CPU been busy since boot time. Integer values change instant by instant and are useful for tracking such statistics as the amount of memory currently being used.</p>
<pre style="color: black;background-color: #f9f9f9;line-height: 1.1em;padding: 1em;border: 1px dashed #2f6fab">tcpActiveOpens OBJECT-TYPE
    SYNTAX  Counter
    ACCESS  read-only
    STATUS  mandatory
    DESCRIPTION
            "The number of times TCP connections have made a
            direct transition to the SYN-SENT state from the
            CLOSED state."
    ::= { tcp 5 }</pre>
<p style="margin-top: 0.4em;margin-right: 0px;margin-bottom: 0.5em;margin-left: 0px;line-height: 1.5em">You&#8217;ll explore the differences between SNMP and MRTG terminologies in more detail later. Understanding them will be important in understanding how to use MRTG to track MIB values.</p>
<h1 style="color: green;background-color: initial;font-weight: normal;margin-top: 0px;margin-right: 0px;margin-bottom: 0.6em;margin-left: 0px;padding-top: 0.5em;padding-bottom: 0.17em;border-bottom-width: 2px;border-bottom-style: solid;border-bottom-color: #048444;font-size: 24px"><span>Testing Your MIB Value</span></h1>
<p style="margin-top: 0.4em;margin-right: 0px;margin-bottom: 0.5em;margin-left: 0px;line-height: 1.5em">Once you have identified an interesting MIB value for your Linux system you can then use the snmpwalk command to poll it. Many times the text aliases in a MIB only reference the OID branch and not the OID the data located in a leaf ending in an additional number like a &#8220;.0&#8243; or &#8220;.1&#8243;. The snmpget command doesn&#8217;t work with branches giving an error stating that the MIB variable couldn&#8217;t be found.</p>
<p style="margin-top: 0.4em;margin-right: 0px;margin-bottom: 0.5em;margin-left: 0px;line-height: 1.5em">In the example below, the ssCpuRawUser OID alias was found to be interesting, but the snmpget command fails to get a value. Follow up with the snmpwalk command shows that the value is located in ssCpuRawUser.0 instead. The snmpget is then successful in retrieving the &#8220;counter32&#8243; type data with a current value of 396271.</p>
<pre style="color: black;background-color: #f9f9f9;line-height: 1.1em;padding: 1em;border: 1px dashed #2f6fab">[root@bigboy tmp]# snmpget -v1 -c craz33guy localhost ssCpuRawUser
Error in packet
Reason: (noSuchName) There is no such variable name in this MIB.
Failed object: UCD-SNMP-MIB::ssCpuRawUser
[root@bigboy tmp]#

[root@bigboy tmp]# snmpwalk -v1 -c craz33guy localhost ssCpuRawUser
UCD-SNMP-MIB::ssCpuRawUser.0 = Counter32: 396241
[root@bigboy tmp]# snmpget -v1 -c craz33guy localhost ssCpuRawUser.0
UCD-SNMP-MIB::ssCpuRawUser.0 = Counter32: 396271
[root@bigboy tmp]#</pre>
<p style="margin-top: 0.4em;margin-right: 0px;margin-bottom: 0.5em;margin-left: 0px;line-height: 1.5em">The MIB values that work successfully with snmpget are the ones you should use with MRTG.</p>
<h1 style="color: green;background-color: initial;font-weight: normal;margin-top: 0px;margin-right: 0px;margin-bottom: 0.6em;margin-left: 0px;padding-top: 0.5em;padding-bottom: 0.17em;border-bottom-width: 2px;border-bottom-style: solid;border-bottom-color: #048444;font-size: 24px"><span>Differences In MIB And MRTG Terminology</span></h1>
<p style="margin-top: 0.4em;margin-right: 0px;margin-bottom: 0.5em;margin-left: 0px;line-height: 1.5em">Always keep in mind that MRTG refers to MIB counter values as counter values. It refers to MIB integer and gauge values as gauge. By default, MRTG considers all values to be counters.</p>
<p style="margin-top: 0.4em;margin-right: 0px;margin-bottom: 0.5em;margin-left: 0px;line-height: 1.5em">MRTG doesn&#8217;t plot counter values as a constantly increasing graph, it plots only how much the value has changed since the last polling cycle. CPU usage is typically tracked by MIBs as a counter value; fortunately, you can edit your MRTG configuration file to make it graph this information in a percentage use format (more on this later).</p>
<p style="margin-top: 0.4em;margin-right: 0px;margin-bottom: 0.5em;margin-left: 0px;line-height: 1.5em">The syntax type, the MIB object name, and the description of what it does are the most important things you need to know when configuring MRTG; I&#8217;ll come back to these later.</p>
<h1 style="color: green;background-color: initial;font-weight: normal;margin-top: 0px;margin-right: 0px;margin-bottom: 0.6em;margin-left: 0px;padding-top: 0.5em;padding-bottom: 0.17em;border-bottom-width: 2px;border-bottom-style: solid;border-bottom-color: #048444;font-size: 24px"><span>The CPU And Memory Monitoring MIB</span></h1>
<p style="margin-top: 0.4em;margin-right: 0px;margin-bottom: 0.5em;margin-left: 0px;line-height: 1.5em">The UCD-SNMP-MIB MIB keeps track of a number of key performance MIB objects, including the commonly used ones in Table 23-1.</p>
<h2 style="color: teal;background-color: initial;font-weight: normal;margin-top: 0px;margin-right: 0px;margin-bottom: 0.6em;margin-left: 0px;padding-top: 0.5em;padding-bottom: 0.17em;border-bottom-width: 1px;border-bottom-style: solid;border-bottom-color: #aaaaaa;font-size: 19px"><span>Table 23-1 Important Objects In The UCD-SNMP-MIB MIB</span></h2>
<table style="font-size: 13px;color: black;background-color: white" border="1" cellspacing="0" cellpadding="5" align="center">
<tbody>
<tr>
<th>UCD-SNMP-MIB Object Variable</th>
<th>MIB Type</th>
<th>MRTG Type</th>
<th>Description</th>
</tr>
<tr valign="top">
<td>ssCpuRawUser</td>
<td>Counter</td>
<td>Counter</td>
<td>
<p style="margin-top: 0.4em;margin-right: 0px;margin-bottom: 0.5em;margin-left: 0px;line-height: 1.5em">Total CPU usage by applications run by nonprivileged users since the system booted. Adding the user, system, and nice values can give a good approximation of total CPU usage..</p>
</td>
</tr>
<tr valign="top">
<td>ssCpuRawSystem</td>
<td>Counter</td>
<td>Counter</td>
<td>Total CPU usage by applications run by privileged system processes since the system booted.</td>
</tr>
<tr valign="top">
<td>ssCpuRawNice</td>
<td>Counter</td>
<td>Counter</td>
<td>Total CPU usage by applications running at a nondefault priority level.</td>
</tr>
<tr valign="top">
<td>ssCpuRawIdle</td>
<td>Counter</td>
<td>Counter</td>
<td>
<p style="margin-top: 0.4em;margin-right: 0px;margin-bottom: 0.5em;margin-left: 0px;line-height: 1.5em">The percentage of the time the CPU is running idle. Subtracting this value from 100 can give a good approximation of total CPU usage.</p>
</td>
</tr>
<tr valign="top">
<td>memAvailReal</td>
<td>Integer</td>
<td>Gauge</td>
<td>Available Physical Memory Space On The Host</td>
</tr>
</tbody>
</table>
<h1 style="color: green;background-color: initial;font-weight: normal;margin-top: 0px;margin-right: 0px;margin-bottom: 0.6em;margin-left: 0px;padding-top: 0.5em;padding-bottom: 0.17em;border-bottom-width: 2px;border-bottom-style: solid;border-bottom-color: #048444;font-size: 24px"><span>The TCP/IP Monitoring MIB</span></h1>
<p style="margin-top: 0.4em;margin-right: 0px;margin-bottom: 0.5em;margin-left: 0px;line-height: 1.5em">The TCP-MIB MIB keeps track of data connection information and contains the very useful tcpActiveOpens and tcpCurrEstab objects. Table 23.2 details the most important objects in TCP-MIB.</p>
<h2 style="color: teal;background-color: initial;font-weight: normal;margin-top: 0px;margin-right: 0px;margin-bottom: 0.6em;margin-left: 0px;padding-top: 0.5em;padding-bottom: 0.17em;border-bottom-width: 1px;border-bottom-style: solid;border-bottom-color: #aaaaaa;font-size: 19px"><span>Table 23-2 Important Objects In The TCP-MIB MIB</span></h2>
<table style="font-size: 13px;color: black;background-color: white" border="1" cellspacing="0" cellpadding="5" align="center">
<tbody>
<tr>
<th>UCD-SNMP-MIB Object Variable</th>
<th>MIB Type</th>
<th>MRTG Type</th>
<th>Description</th>
</tr>
<tr valign="top">
<td>tcpActiveOpens</td>
<td>Counter</td>
<td>Counter</td>
<td>Measures the number of completed TCP connections.</td>
</tr>
<tr valign="top">
<td>tcpCurrEstab</td>
<td>Gauge</td>
<td>Gauge</td>
<td>Measures the number of TCP connections in the established state</td>
</tr>
<tr valign="top">
<td>tcpInErrs</td>
<td>Counter</td>
<td>Counter</td>
<td>Total number of TCP segments with bad checksum errors</td>
</tr>
</tbody>
</table>
<h1 style="color: green;background-color: initial;font-weight: normal;margin-top: 0px;margin-right: 0px;margin-bottom: 0.6em;margin-left: 0px;padding-top: 0.5em;padding-bottom: 0.17em;border-bottom-width: 2px;border-bottom-style: solid;border-bottom-color: #048444;font-size: 24px"><span>Manually Configuring Your MRTG File</span></h1>
<p style="margin-top: 0.4em;margin-right: 0px;margin-bottom: 0.5em;margin-left: 0px;line-height: 1.5em">The MRTG cfgmaker program creates configuration files for network interfaces only, simultaneously tracking two OIDs: the NIC&#8217;s input and output data statistics. The mrtg program then uses these configuration files to determine the type of data to record in its data directory. The indexmaker program also uses this information to create the overview, or Summary View Web page for the MIB OIDs you&#8217;re monitoring.</p>
<p style="margin-top: 0.4em;margin-right: 0px;margin-bottom: 0.5em;margin-left: 0px;line-height: 1.5em">This Summary View page shows daily statistics only. You have to click on the Summary View graphs to get the Detailed View page behind it with the daily, weekly, monthly, and annual graphs. Some of the parameters in the configuration file refer to the Detailed View, others refer to the Summary View.</p>
<p style="margin-top: 0.4em;margin-right: 0px;margin-bottom: 0.5em;margin-left: 0px;line-height: 1.5em">If you want to monitor any other pairs of OIDs, you have to manually create the configuration files, because cfgmaker isn&#8217;t aware of any OIDs other than those related to a NIC. The mrtg and indexmaker program can be fed individual OIDs from a customized configuration file and will function as expected if you edit the file correctly.</p>
<h2 style="color: teal;background-color: initial;font-weight: normal;margin-top: 0px;margin-right: 0px;margin-bottom: 0.6em;margin-left: 0px;padding-top: 0.5em;padding-bottom: 0.17em;border-bottom-width: 1px;border-bottom-style: solid;border-bottom-color: #aaaaaa;font-size: 19px"><span>Parameter Formats</span></h2>
<p style="margin-top: 0.4em;margin-right: 0px;margin-bottom: 0.5em;margin-left: 0px;line-height: 1.5em">MRTG configuration parameters are always followed by a graph name surrounded by square brackets and a colon. The format looks like this:</p>
<pre style="color: black;background-color: #f9f9f9;line-height: 1.1em;padding: 1em;border: 1px dashed #2f6fab">Parameter[graph name]: value</pre>
<p style="margin-top: 0.4em;margin-right: 0px;margin-bottom: 0.5em;margin-left: 0px;line-height: 1.5em">For ease of editing, the parameters for a particular graph are usually grouped together. Each graph can track two OIDS listed in the Target parameter, which is usually placed at the very top of the graph name list. The two OID values are separated by an &amp; symbol; the first one can be is the input OID, and the second one is the output OID.</p>
<h2 style="color: teal;background-color: initial;font-weight: normal;margin-top: 0px;margin-right: 0px;margin-bottom: 0.6em;margin-left: 0px;padding-top: 0.5em;padding-bottom: 0.17em;border-bottom-width: 1px;border-bottom-style: solid;border-bottom-color: #aaaaaa;font-size: 19px"><span>Legend Parameters</span></h2>
<p style="margin-top: 0.4em;margin-right: 0px;margin-bottom: 0.5em;margin-left: 0px;line-height: 1.5em">On the Detailed View Web page, each graph has a legend that shows the max, average, and current values of the graph&#8217;s OID statistics. You can use the legendI parameter for the description of the input graph (first graph OID) and the legendO for the output graph (second graph OID).</p>
<p style="margin-top: 0.4em;margin-right: 0px;margin-bottom: 0.5em;margin-left: 0px;line-height: 1.5em">The space available under each graph&#8217;s legend is tiny so MRTG also has legend1 and legend2 parameters that are placed at the very bottom of the page to provide more details. Parameter legend1 is the expansion of legendI, and legend2 is the expansion of legendO.</p>
<p style="margin-top: 0.4em;margin-right: 0px;margin-bottom: 0.5em;margin-left: 0px;line-height: 1.5em">The Ylegend is the legend for the Y axis, the value you are trying to compare. In the case of a default MRTG configuration this would be the data flow through the interface in bits or bytes per second. Here is an example of the legends of a default MRTG configuration:</p>
<pre style="color: black;background-color: #f9f9f9;line-height: 1.1em;padding: 1em;border: 1px dashed #2f6fab">YLegend[graph1]: Bits per second
Legend1[graph1]: Incoming Traffic in Bits per Second
Legend2[graph1]: Outgoing Traffic in Bits per Second
LegendI[graph1]: In
LegendO[graph1]: Out</pre>
<p style="margin-top: 0.4em;margin-right: 0px;margin-bottom: 0.5em;margin-left: 0px;line-height: 1.5em">You can prevent MRTG from printing the legend at the bottom of the graph by leaving the value of the legend blank like this:</p>
<pre style="color: black;background-color: #f9f9f9;line-height: 1.1em;padding: 1em;border: 1px dashed #2f6fab">LegendI[graph1]:</pre>
<p style="margin-top: 0.4em;margin-right: 0px;margin-bottom: 0.5em;margin-left: 0px;line-height: 1.5em">Later you&#8217;ll learn how to match the legends to the OIDs for a variety of situations.</p>
<h2 style="color: teal;background-color: initial;font-weight: normal;margin-top: 0px;margin-right: 0px;margin-bottom: 0.6em;margin-left: 0px;padding-top: 0.5em;padding-bottom: 0.17em;border-bottom-width: 1px;border-bottom-style: solid;border-bottom-color: #aaaaaa;font-size: 19px"><span>Options Parameters</span></h2>
<p style="margin-top: 0.4em;margin-right: 0px;margin-bottom: 0.5em;margin-left: 0px;line-height: 1.5em">Options parameters provide MRTG with graph formatting information. The growright option makes sure the data at the right of the screen is for the most current graph values. This usually makes the graphs more intuitively easy to read. MRTG defaults to growing from the left.</p>
<p style="margin-top: 0.4em;margin-right: 0px;margin-bottom: 0.5em;margin-left: 0px;line-height: 1.5em">The nopercent option prevents MRTG from printing percentage style statistics in the legends at the bottom of the graph. The gauge option alerts MRTG to the fact that the graphed values are of the gauge type. If the value you are monitoring is in bytes, then you can convert the output to bits using the bits option. Likewise, you can convert per second values to per minute graphs using the perminute option. Here are some examples for two different graphs:</p>
<pre style="color: black;background-color: #f9f9f9;line-height: 1.1em;padding: 1em;border: 1px dashed #2f6fab">options[graph1]: growright,nopercent,perminute

options[graph2]: gauge,bits</pre>
<p style="margin-top: 0.4em;margin-right: 0px;margin-bottom: 0.5em;margin-left: 0px;line-height: 1.5em">If you place this parameter at the top with a label of [_] it gets applied to all the graphs defined in the file. Here&#8217;s an example.</p>
<pre style="color: black;background-color: #f9f9f9;line-height: 1.1em;padding: 1em;border: 1px dashed #2f6fab">options[_]: growright</pre>
<p style="margin-top: 0.4em;margin-right: 0px;margin-bottom: 0.5em;margin-left: 0px;line-height: 1.5em">Title Parameters</p>
<p style="margin-top: 0.4em;margin-right: 0px;margin-bottom: 0.5em;margin-left: 0px;line-height: 1.5em">The title on the Summary Page is provided by the Title parameter, the PageTop parameter tells the title for the Detailed View page. The PageTop string must start with &lt; H1 &gt; and end with &lt; H1 &gt;.</p>
<pre style="color: black;background-color: #f9f9f9;line-height: 1.1em;padding: 1em;border: 1px dashed #2f6fab">Title[graph1]: Interface eth0

PageTop[graph1]: &lt; H1 &gt;Detailed Statistics For Interface eth0 &lt; H1 &gt;</pre>
<h2 style="color: teal;background-color: initial;font-weight: normal;margin-top: 0px;margin-right: 0px;margin-bottom: 0.6em;margin-left: 0px;padding-top: 0.5em;padding-bottom: 0.17em;border-bottom-width: 1px;border-bottom-style: solid;border-bottom-color: #aaaaaa;font-size: 19px"><span>Scaling Parameters</span></h2>
<p style="margin-top: 0.4em;margin-right: 0px;margin-bottom: 0.5em;margin-left: 0px;line-height: 1.5em">The MaxBytes parameter is the maximum amount of data MRTG will plot on a graph. Anything more than this seems to disappear over the edge of the graph.</p>
<p style="margin-top: 0.4em;margin-right: 0px;margin-bottom: 0.5em;margin-left: 0px;line-height: 1.5em">MRTG also tries to adjust its graphs so that the largest value plotted on the graph is always close to the top. This is so even if you set the MaxBytes parameter.</p>
<p style="margin-top: 0.4em;margin-right: 0px;margin-bottom: 0.5em;margin-left: 0px;line-height: 1.5em">When you are plotting a value that has a known maximum and you always want to have this value at the top of the vertical legend, you may want to turn off MRTG&#8217;s auto scaling. If you are plotting percentage CPU usage, and the server reaches a maximum of 60%, with scaling, MRTG will have a vertical plot of 0% to 60%, so that the vertical peak is near the top of the graph image.</p>
<p style="margin-top: 0.4em;margin-right: 0px;margin-bottom: 0.5em;margin-left: 0px;line-height: 1.5em">When scaling is off, and MaxBytes is set to 100, then the peak will be only 60% of the way up as the graph plots from 0% to 100%. The example removes scaling from the yearly, monthly, weekly, and daily views on the Detailed View page and gives them a maximum value of 100.</p>
<pre style="color: black;background-color: #f9f9f9;line-height: 1.1em;padding: 1em;border: 1px dashed #2f6fab">Unscaled[graph1]: ymwd
MaxBytes[graph1]: 100</pre>
<h2 style="color: teal;background-color: initial;font-weight: normal;margin-top: 0px;margin-right: 0px;margin-bottom: 0.6em;margin-left: 0px;padding-top: 0.5em;padding-bottom: 0.17em;border-bottom-width: 1px;border-bottom-style: solid;border-bottom-color: #aaaaaa;font-size: 19px"><span>Defining The MIB Target Parameters</span></h2>
<p style="margin-top: 0.4em;margin-right: 0px;margin-bottom: 0.5em;margin-left: 0px;line-height: 1.5em">As stated before, MRTG always tries to compare two MIB OID values that are defined by the Target parameter. You have to specify the two MIB OID objects, the SNMP password and the IP address of the device you are querying in this parameter, and separate them with an &amp; character:</p>
<pre style="color: black;background-color: #f9f9f9;line-height: 1.1em;padding: 1em;border: 1px dashed #2f6fab">Target[graph1]: mib-object-1.0&amp;mib-object-2.0:&lt;SNMP-password&gt;@&lt;IP-address&gt;</pre>
<p style="margin-top: 0.4em;margin-right: 0px;margin-bottom: 0.5em;margin-left: 0px;line-height: 1.5em">The numeric value, in this case .0, at the end of the MIB is required. The next example uses the SNMP command to return the user mode CPU utilization of a Linux server. Notice how the .0 is tagged onto the end of the output.</p>
<pre style="color: black;background-color: #f9f9f9;line-height: 1.1em;padding: 1em;border: 1px dashed #2f6fab">[root@silent mibs]# snmpwalk -v 1 -c craz33guy localhost ssCpuRawUser
UCD-SNMP-MIB::ssCpuRawUser.0 = Counter32: 926739
[root@silent mibs]#</pre>
<p style="margin-top: 0.4em;margin-right: 0px;margin-bottom: 0.5em;margin-left: 0px;line-height: 1.5em">The MRTG legends map to the MIBs listed in the target as shown in Table 23-3.</p>
<h3 style="color: black;background-color: initial;font-weight: bold;margin-top: 0px;margin-right: 0px;margin-bottom: 0.3em;margin-left: 0px;padding-top: 0.5em;padding-bottom: 0.17em;border-bottom-width: initial;border-bottom-style: none;border-bottom-color: initial;font-size: 17px"><span>Table 23-3 Mapping MIBs To The Graph Legends</span></h3>
<table style="font-size: 13px;color: black;background-color: white" border="1" cellspacing="0" cellpadding="5" align="center">
<tbody>
<tr>
<th>Legend</th>
<th>Maps To Target MIB</th>
</tr>
<tr valign="top">
<td>Legend1</td>
<td>#1</td>
</tr>
<tr valign="top">
<td>Legend2</td>
<td>#2</td>
</tr>
<tr valign="top">
<td>LegendI</td>
<td>#1</td>
</tr>
<tr valign="top">
<td>LegendO</td>
<td>#2</td>
</tr>
</tbody>
</table>
<p style="margin-top: 0.4em;margin-right: 0px;margin-bottom: 0.5em;margin-left: 0px;line-height: 1.5em">So in the example below, legend1 and legendI describe mib-object-1.0 and legend2 and legendO describe mib-object-2.0.</p>
<pre style="color: black;background-color: #f9f9f9;line-height: 1.1em;padding: 1em;border: 1px dashed #2f6fab">Target[graph1]: mib-object-1.0&amp;mib-object-2.0:&lt;SNMP-password&gt;@&lt;IP-address&gt;</pre>
<h3 style="color: black;background-color: initial;font-weight: bold;margin-top: 0px;margin-right: 0px;margin-bottom: 0.3em;margin-left: 0px;padding-top: 0.5em;padding-bottom: 0.17em;border-bottom-width: initial;border-bottom-style: none;border-bottom-color: initial;font-size: 17px"><span>Plotting Only One MIB Value</span></h3>
<p style="margin-top: 0.4em;margin-right: 0px;margin-bottom: 0.5em;margin-left: 0px;line-height: 1.5em">If you want to plot only one MIB value, you can just repeat the target MIB in the definition as in the next example, which plots only mib-object-1. The resulting MRTG graph actually superimposes the input and output graphs one on top of the other.</p>
<pre style="color: black;background-color: #f9f9f9;line-height: 1.1em;padding: 1em;border: 1px dashed #2f6fab">Target[graph1]: mib-object-1.0&amp;mib-object-1.0:&lt;SNMP-password&gt;@&lt;IP-address&gt;</pre>
<h3 style="color: black;background-color: initial;font-weight: bold;margin-top: 0px;margin-right: 0px;margin-bottom: 0.3em;margin-left: 0px;padding-top: 0.5em;padding-bottom: 0.17em;border-bottom-width: initial;border-bottom-style: none;border-bottom-color: initial;font-size: 17px"><span>Adding MIB Values Together For a Graph</span></h3>
<p style="margin-top: 0.4em;margin-right: 0px;margin-bottom: 0.5em;margin-left: 0px;line-height: 1.5em">You can use the plus sign between the pairs of MIB object values to add them together. The next example adds mib-object-1.0 and mib-object-3.0 for one graph and adds mib-object-2.0 and mib-object-4.0 for the other.</p>
<pre style="color: black;background-color: #f9f9f9;line-height: 1.1em;padding: 1em;border: 1px dashed #2f6fab">Target[graph1]: mib-object-1.0&amp;mib-object-2.0:&lt;SNMP-password&gt;@&lt;IP-address&gt; + mib-object-3.0&amp;mib-object-4.0:&lt;SNMP-password&gt;@&lt;IP-address&gt;</pre>
<p style="margin-top: 0.4em;margin-right: 0px;margin-bottom: 0.5em;margin-left: 0px;line-height: 1.5em">You can use other mathematical operators, such as subtract (-), multiply (*), and divide (%). Left and right parentheses are also valid. There must be white spaces before and after all these operators for MRTG to work correctly. If not, you&#8217;ll get oddly shaded graphs.</p>
<h3 style="color: black;background-color: initial;font-weight: bold;margin-top: 0px;margin-right: 0px;margin-bottom: 0.3em;margin-left: 0px;padding-top: 0.5em;padding-bottom: 0.17em;border-bottom-width: initial;border-bottom-style: none;border-bottom-color: initial;font-size: 17px"><span>Sample Target: Total CPU Usage</span></h3>
<p style="margin-top: 0.4em;margin-right: 0px;margin-bottom: 0.5em;margin-left: 0px;line-height: 1.5em">Linux CPU usage is occupied by system processes, user mode processes, and a few processes running in nice mode. This example adds them all together in a single plot.</p>
<pre style="color: black;background-color: #f9f9f9;line-height: 1.1em;padding: 1em;border: 1px dashed #2f6fab">Target[graph1]:ssCpuRawUser.0&amp;ssCpuRawUser.0:&lt;SNMP-password&gt;@&lt;IP-address&gt; + ssCpuRawSystem.0&amp;ssCpuRawSystem.0:&lt;SNMP-password&gt;@&lt;IP-address&gt; + ssCpuRawNice.0&amp;ssCpuRawNice.0:&lt;SNMP-password&gt;@&lt;IP-address&gt;</pre>
<p style="margin-top: 0.4em;margin-right: 0px;margin-bottom: 0.5em;margin-left: 0px;line-height: 1.5em">Be sure to place this command on a single line</p>
<h3 style="color: black;background-color: initial;font-weight: bold;margin-top: 0px;margin-right: 0px;margin-bottom: 0.3em;margin-left: 0px;padding-top: 0.5em;padding-bottom: 0.17em;border-bottom-width: initial;border-bottom-style: none;border-bottom-color: initial;font-size: 17px"><span>Sample Target: Memory Usage</span></h3>
<p style="margin-top: 0.4em;margin-right: 0px;margin-bottom: 0.5em;margin-left: 0px;line-height: 1.5em">Here is an example for the plotting the amount of free memory versus the total RAM installed in the server. Notice that this is a gauge type variable.</p>
<pre style="color: black;background-color: #f9f9f9;line-height: 1.1em;padding: 1em;border: 1px dashed #2f6fab">Target[graph1]: memAvailReal.0&amp;memTotalReal.0:&lt;SNMP-password&gt;@&lt;IP-address&gt;
options[graph1]: nopercent,growright,gauge</pre>
<p style="margin-top: 0.4em;margin-right: 0px;margin-bottom: 0.5em;margin-left: 0px;line-height: 1.5em">Next, plot the percentage of available memory. Notice how the mandatory white spaces separate the mathematical operators from the next target element.</p>
<pre style="color: black;background-color: #f9f9f9;line-height: 1.1em;padding: 1em;border: 1px dashed #2f6fab">Target[graph1]: ( memAvailReal.0&amp; memAvailReal.0:&lt;SNMP-password&gt;@&lt;IP-Address&gt; ) * 100 / ( memTotalReal.0&amp;memTotalReal.0:&lt;SNMP-password&gt;@&lt;IP-Address&gt; )
options[graph1]: nopercent,growright,gauge</pre>
<h3 style="color: black;background-color: initial;font-weight: bold;margin-top: 0px;margin-right: 0px;margin-bottom: 0.3em;margin-left: 0px;padding-top: 0.5em;padding-bottom: 0.17em;border-bottom-width: initial;border-bottom-style: none;border-bottom-color: initial;font-size: 17px"><span>Sample Target: Newly Created Connections</span></h3>
<p style="margin-top: 0.4em;margin-right: 0px;margin-bottom: 0.5em;margin-left: 0px;line-height: 1.5em">HTTP traffic caused by Web browsing usually consists of many very short lived connections. The tcpPassiveOpens MIB object tracks newly created connections and is suited for this type of data transfer. The tcpActiveOpens MIB object monitors new connections originating from the server. On smaller Web sites you may want to use the perminute option to make the graphs more meaningful.</p>
<pre style="color: black;background-color: #f9f9f9;line-height: 1.1em;padding: 1em;border: 1px dashed #2f6fab">Target[graph1]: tcpPassiveOpens.0&amp; tcpPassiveOpens.0:&lt;SNMP-password&gt;@&lt;IP-address&gt;
MaxBytes[graph1]: 1000000
Options[graph1]: perminute</pre>
<h3 style="color: black;background-color: initial;font-weight: bold;margin-top: 0px;margin-right: 0px;margin-bottom: 0.3em;margin-left: 0px;padding-top: 0.5em;padding-bottom: 0.17em;border-bottom-width: initial;border-bottom-style: none;border-bottom-color: initial;font-size: 17px"><span>Sample Target: Total TCP Established Connections</span></h3>
<p style="margin-top: 0.4em;margin-right: 0px;margin-bottom: 0.5em;margin-left: 0px;line-height: 1.5em">Other protocols such as FTP and SSH create longer established connections while people download large files or stay logged into the server. The tcpCurrEstab MIB object measures the total number of connections in the established state and is a gauge value.</p>
<pre style="color: black;background-color: #f9f9f9;line-height: 1.1em;padding: 1em;border: 1px dashed #2f6fab">Target[graph1]: tcpCurrEstab.0&amp;tcpCurrEstab.0:&lt;SNMP-password&gt;@&lt;IP-address&gt;
MaxBytes[graph1]: 1000000
Options[graph1]: gauge</pre>
<h3 style="color: black;background-color: initial;font-weight: bold;margin-top: 0px;margin-right: 0px;margin-bottom: 0.3em;margin-left: 0px;padding-top: 0.5em;padding-bottom: 0.17em;border-bottom-width: initial;border-bottom-style: none;border-bottom-color: initial;font-size: 17px"><span>Sample Target: Disk Partition Usage</span></h3>
<p style="margin-top: 0.4em;margin-right: 0px;margin-bottom: 0.5em;margin-left: 0px;line-height: 1.5em">In this example, you&#8217;ll monitor the /var and /home disk partitions on the system.</p>
<p style="margin-top: 0.4em;margin-right: 0px;margin-bottom: 0.5em;margin-left: 0px;line-height: 1.5em">1) First use the df -k command to get a list of the partitions in use.</p>
<pre style="color: black;background-color: #f9f9f9;line-height: 1.1em;padding: 1em;border: 1px dashed #2f6fab">[root@bigboy tmp]# df -k
Filesystem           1K-blocks      Used Available Use% Mounted on
/dev/hda8               505605    128199    351302  27% /
/dev/hda1               101089     19178     76692  21% /boot
/dev/hda5              1035660    122864    860188  13% /home
/dev/hda6               505605      8229    471272   2% /tmp
/dev/hda3              3921436    890092   2832140  24% /usr
/dev/hda2              1510060    171832   1261520  73% /var
[root@bigboy tmp]#</pre>
<p style="margin-top: 0.4em;margin-right: 0px;margin-bottom: 0.5em;margin-left: 0px;line-height: 1.5em">2) Add two entries to your snmpd.conf file.</p>
<pre style="color: black;background-color: #f9f9f9;line-height: 1.1em;padding: 1em;border: 1px dashed #2f6fab">disk  /home
disk  /var</pre>
<p style="margin-top: 0.4em;margin-right: 0px;margin-bottom: 0.5em;margin-left: 0px;line-height: 1.5em">3) Restart the SNMP daemon to reload the values.</p>
<pre style="color: black;background-color: #f9f9f9;line-height: 1.1em;padding: 1em;border: 1px dashed #2f6fab">[root@bigboy tmp]# service snmpd restart</pre>
<p style="margin-top: 0.4em;margin-right: 0px;margin-bottom: 0.5em;margin-left: 0px;line-height: 1.5em">4) Use the snmpwalk command to query the the dskPercent MIB. Object dskPercent.1 refers to the first disk entry in snmpd.conf (/home), and dskPercent.2 refers to the second (/var).</p>
<pre style="color: black;background-color: #f9f9f9;line-height: 1.1em;padding: 1em;border: 1px dashed #2f6fab">[root@bigboy tmp]# snmpwalk -v 1 -c craz33guy localhost dskPercent.1
UCD-SNMP-MIB::dskPercent.1 = INTEGER: 13
[root@bigboy tmp]# snmpwalk -v 1 -c craz33guy localhost dskPercent.2
UCD-SNMP-MIB::dskPercent.2 = INTEGER: 73
[root@bigboy tmp]#</pre>
<p style="margin-top: 0.4em;margin-right: 0px;margin-bottom: 0.5em;margin-left: 0px;line-height: 1.5em">Your MRTG target for these gauge MIB objects should look like this:</p>
<pre style="color: black;background-color: #f9f9f9;line-height: 1.1em;padding: 1em;border: 1px dashed #2f6fab">Target[graph1]: dskPercent.1&amp; dskPercent.1:&lt;SNMP-password&gt;@&lt;IP-address&gt;
options[graph1]: growright,gauge</pre>
<h3 style="color: black;background-color: initial;font-weight: bold;margin-top: 0px;margin-right: 0px;margin-bottom: 0.3em;margin-left: 0px;padding-top: 0.5em;padding-bottom: 0.17em;border-bottom-width: initial;border-bottom-style: none;border-bottom-color: initial;font-size: 17px"><span>Defining Global Variables</span></h3>
<p style="margin-top: 0.4em;margin-right: 0px;margin-bottom: 0.5em;margin-left: 0px;line-height: 1.5em">You have to make sure MRTG knows where the MIBs you&#8217;re using are located. The default location MRTG uses may not be valid. Specify their locations with the global LoadMIBs parameter. You must also define where the HTML files will be located; the example specifies the default Fedora MRTG HTML directory.</p>
<pre style="color: black;background-color: #f9f9f9;line-height: 1.1em;padding: 1em;border: 1px dashed #2f6fab">LoadMIBs: /usr/share/snmp/mibs/UCD-SNMP-MIB.txt, /usr/share/snmp/mibs/TCP-MIB.txt
workdir: /var/www/mrtg/</pre>
<h1 style="color: green;background-color: initial;font-weight: normal;margin-top: 0px;margin-right: 0px;margin-bottom: 0.6em;margin-left: 0px;padding-top: 0.5em;padding-bottom: 0.17em;border-bottom-width: 2px;border-bottom-style: solid;border-bottom-color: #048444;font-size: 24px"><span>Implementing Advanced Server Monitoring</span></h1>
<p style="margin-top: 0.4em;margin-right: 0px;margin-bottom: 0.5em;margin-left: 0px;line-height: 1.5em">You now can combine all you have learned to create a configuration file that monitors all these variables, and then you can integrate it into the existing MRTG configuration.</p>
<h2 style="color: teal;background-color: initial;font-weight: normal;margin-top: 0px;margin-right: 0px;margin-bottom: 0.6em;margin-left: 0px;padding-top: 0.5em;padding-bottom: 0.17em;border-bottom-width: 1px;border-bottom-style: solid;border-bottom-color: #aaaaaa;font-size: 19px"><span>A Complete Sample Configuration</span></h2>
<p style="margin-top: 0.4em;margin-right: 0px;margin-bottom: 0.5em;margin-left: 0px;line-height: 1.5em">Here is a sample configuration file that is used to query server localhost for CPU, memory, disk, and TCP connection information.</p>
<pre style="color: black;background-color: #f9f9f9;line-height: 1.1em;padding: 1em;border: 1px dashed #2f6fab">#
# File: /etc/mrtg/server-info.cfg
#
# Configuration file for non bandwidth server statistics
#

#
# Define global options
#

LoadMIBs: /usr/share/snmp/mibs/UCD-SNMP-MIB.txt,/usr/share/snmp/mibs/TCP-MIB.txt
workdir: /var/www/mrtg/

#
# CPU Monitoring
# (Scaled so that the sum of all three values doesn't exceed 100)
#

Target[server.cpu]:ssCpuRawUser.0&amp;ssCpuRawUser.0:craz33guy@localhost + ssCpuRawSystem.0&amp;ssCpuRawSystem.0:craz33guy@localhost + ssCpuRawNice.0&amp;ssCpuRawNice.0:craz33guy@localhost
Title[server.cpu]: Server CPU Load
PageTop[server.cpu]: &lt; H1 &gt;CPU Load - System, User and Nice Processes&lt; /H1 &gt;
MaxBytes[server.cpu]: 100
ShortLegend[server.cpu]: %
YLegend[server.cpu]: CPU Utilization
Legend1[server.cpu]: Current CPU percentage load
LegendI[server.cpu]: Used
LegendO[server.cpu]:
Options[server.cpu]: growright,nopercent
Unscaled[server.cpu]: ymwd

#
# Memory Monitoring (Total Versus Available Memory)
#

Target[server.memory]: memAvailReal.0&amp;memTotalReal.0:craz33guy@localhost
Title[server.memory]: Free Memory
PageTop[server.memory]: &lt; H1 &gt;Free Memory&lt; /H1 &gt;
MaxBytes[server.memory]: 100000000000
ShortLegend[server.memory]: B
YLegend[server.memory]: Bytes
LegendI[server.memory]: Free
LegendO[server.memory]: Total
Legend1[server.memory]: Free memory, not including swap, in bytes
Legend2[server.memory]: Total memory
Options[server.memory]: gauge,growright,nopercent
kMG[server.memory]: k,M,G,T,P,X

#
# Memory Monitoring (Percentage usage)
#
Title[server.mempercent]: Percentage Free Memory
PageTop[server.mempercent]: &lt; H1 &gt;Percentage Free Memory&lt; /H1 &gt;
Target[server.mempercent]: ( memAvailReal.0&amp;memAvailReal.0:craz33guy@localhost ) * 100 / ( memTotalReal.0&amp;memTotalReal.0:craz33guy@localhost )
options[server.mempercent]: growright,gauge,transparent,nopercent
Unscaled[server.mempercent]: ymwd
MaxBytes[server.mempercent]: 100
YLegend[server.mempercent]: Memory %
ShortLegend[server.mempercent]: Percent
LegendI[server.mempercent]: Free
LegendO[server.mempercent]: Free
Legend1[server.mempercent]: Percentage Free Memory
Legend2[server.mempercent]: Percentage Free Memory

#
# New TCP Connection Monitoring (per minute)
#

Target[server.newconns]: tcpPassiveOpens.0&amp;tcpActiveOpens.0:craz33guy@localhost
Title[server.newconns]: Newly Created TCP Connections
PageTop[server.newconns]: &lt; H1 &gt;New TCP Connections&lt; /H1 &gt;
MaxBytes[server.newconns]: 10000000000
ShortLegend[server.newconns]: c/s
YLegend[server.newconns]: Conns / Min
LegendI[server.newconns]: In
LegendO[server.newconns]: Out
Legend1[server.newconns]: New inbound connections
Legend2[server.newconns]: New outbound connections
Options[server.newconns]: growright,nopercent,perminute

#
# Established TCP Connections
#

Target[server.estabcons]: tcpCurrEstab.0&amp;tcpCurrEstab.0:craz33guy@localhost
Title[server.estabcons]: Currently Established TCP Connections
PageTop[server.estabcons]: &lt; H1 &gt;Established TCP Connections&lt; /H1 &gt;
MaxBytes[server.estabcons]: 10000000000
ShortLegend[server.estabcons]:
YLegend[server.estabcons]: Connections
LegendI[server.estabcons]: In
LegendO[server.estabcons]:
Legend1[server.estabcons]: Established connections
Legend2[server.estabcons]:
Options[server.estabcons]: growright,nopercent,gauge

#
# Disk Usage Monitoring
#

Target[server.disk]: dskPercent.1&amp;dskPercent.2:craz33guy@localhost
Title[server.disk]: Disk Partition Usage
PageTop[server.disk]: &lt; H1 &gt;Disk Partition Usage /home and /var&lt; /H1 &gt;
MaxBytes[server.disk]: 100
ShortLegend[server.disk]: %
YLegend[server.disk]: Utilization
LegendI[server.disk]: /home
LegendO[server.disk]: /var
Options[server.disk]: gauge,growright,nopercent
Unscaled[server.disk]: ymwd</pre>
<h2 style="color: teal;background-color: initial;font-weight: normal;margin-top: 0px;margin-right: 0px;margin-bottom: 0.6em;margin-left: 0px;padding-top: 0.5em;padding-bottom: 0.17em;border-bottom-width: 1px;border-bottom-style: solid;border-bottom-color: #aaaaaa;font-size: 19px"><span>Testing The Configuration</span></h2>
<p style="margin-top: 0.4em;margin-right: 0px;margin-bottom: 0.5em;margin-left: 0px;line-height: 1.5em">The next step is to test that MRTG can load the configuration file correctly.</p>
<p style="margin-top: 0.4em;margin-right: 0px;margin-bottom: 0.5em;margin-left: 0px;line-height: 1.5em">Restart SNMP to make sure the disk monitoring commands in the snmpd.conf file are activated. Run the /usr/bin/mrtg command followed by the name of the configuration file three times. If all goes well, MRTG will complain only about the fact that certain database files don&#8217;t exist. MRTG then creates the files. By the third run, all the files are created and MRTG should operate smoothly.</p>
<pre style="color: black;background-color: #f9f9f9;line-height: 1.1em;padding: 1em;border: 1px dashed #2f6fab">[root@bigboy tmp]# service snmpd restart
[root@bigboy tmp]# env LANG=C /usr/bin/mrtg /etc/mrtg/server-stats.cfg</pre>
<h2 style="color: teal;background-color: initial;font-weight: normal;margin-top: 0px;margin-right: 0px;margin-bottom: 0.6em;margin-left: 0px;padding-top: 0.5em;padding-bottom: 0.17em;border-bottom-width: 1px;border-bottom-style: solid;border-bottom-color: #aaaaaa;font-size: 19px"><span>Creating A New MRTG Index Page To Include This File</span></h2>
<p style="margin-top: 0.4em;margin-right: 0px;margin-bottom: 0.5em;margin-left: 0px;line-height: 1.5em">Use the indexmaker command and include your original MRTG configuration file from Chapter 22, &#8220;<a title="Quick HOWTO : Ch22 : Monitoring Server Performance" href="http://www.linuxhomenetworking.com/wiki/index.php/Quick_HOWTO_:_Ch22_:_Monitoring_Server_Performance">Monitoring Server Performance</a>&#8220;, (/etc/mrtg/mrtg.cfg) plus the new one you created (/etc/mrtg/server-stats.cfg).</p>
<pre style="color: black;background-color: #f9f9f9;line-height: 1.1em;padding: 1em;border: 1px dashed #2f6fab">[root@bigboy tmp]# indexmaker --output=/var/www/mrtg/index.html \
/etc/mrtg/mrtg.cfg /etc/mrtg/server-stats.cfg</pre>
<h2 style="color: teal;background-color: initial;font-weight: normal;margin-top: 0px;margin-right: 0px;margin-bottom: 0.6em;margin-left: 0px;padding-top: 0.5em;padding-bottom: 0.17em;border-bottom-width: 1px;border-bottom-style: solid;border-bottom-color: #aaaaaa;font-size: 19px"><span>Configuring cron To Use The New MRTG File</span></h2>
<p style="margin-top: 0.4em;margin-right: 0px;margin-bottom: 0.5em;margin-left: 0px;line-height: 1.5em">The final step is to make sure that MRTG is configured to poll your server every five minutes using this new configuration file. To do so, add this line to your /etc/cron.d/mrtg file.</p>
<pre style="color: black;background-color: #f9f9f9;line-height: 1.1em;padding: 1em;border: 1px dashed #2f6fab">0-59/5 * * * * root env LANG=C /usr/bin/mrtg /etc/mrtg/server-stats.cfg</pre>
<p style="margin-top: 0.4em;margin-right: 0px;margin-bottom: 0.5em;margin-left: 0px;line-height: 1.5em">Some versions of Linux require you to edit your /etc/crontab file instead. See Chapter 22, &#8220;<a title="Quick HOWTO : Ch22 : Monitoring Server Performance" href="http://www.linuxhomenetworking.com/wiki/index.php/Quick_HOWTO_:_Ch22_:_Monitoring_Server_Performance"> Monitoring Server Performance</a>&#8220;, for more details. You will also have to restart cron with the service crond restart for it to read its new configuration file that tells it to additionally run MRTG every five minutes using the new MRTG configuration file.</p>
<pre style="color: black;background-color: #f9f9f9;line-height: 1.1em;padding: 1em;border: 1px dashed #2f6fab">[root@bigboy tmp]# service crond restart</pre>
<h1 style="color: green;background-color: initial;font-weight: normal;margin-top: 0px;margin-right: 0px;margin-bottom: 0.6em;margin-left: 0px;padding-top: 0.5em;padding-bottom: 0.17em;border-bottom-width: 2px;border-bottom-style: solid;border-bottom-color: #048444;font-size: 24px"><span>Monitoring Non Linux MIB Values</span></h1>
<p style="margin-top: 0.4em;margin-right: 0px;margin-bottom: 0.5em;margin-left: 0px;line-height: 1.5em">All the MIBs mentioned so far are for Linux systems; other types of systems will need additional MIBs whose correct installation may be unclear in user guides or just not available. In such cases, you&#8217;ll need to know the exact value of the OID.</p>
<h2 style="color: teal;background-color: initial;font-weight: normal;margin-top: 0px;margin-right: 0px;margin-bottom: 0.6em;margin-left: 0px;padding-top: 0.5em;padding-bottom: 0.17em;border-bottom-width: 1px;border-bottom-style: solid;border-bottom-color: #aaaaaa;font-size: 19px"><span>Scenario</span></h2>
<p style="margin-top: 0.4em;margin-right: 0px;margin-bottom: 0.5em;margin-left: 0px;line-height: 1.5em">Imagine that your small company has purchased a second-hand Cisco switch to connect its Web site servers to the Internet. The basic MRTG configuration shown in Chapter 22, &#8220;<a title="Quick HOWTO : Ch22 : Monitoring Server Performance" href="http://www.linuxhomenetworking.com/wiki/index.php/Quick_HOWTO_:_Ch22_:_Monitoring_Server_Performance"> Monitoring Server Performance</a>&#8220;, provides the data bandwidth statistics, but you want to measure the CPU load the traffic is having on the device, as well. Downloading MIBs from Cisco and using them with the snmpget command was not a success. You do not know what to do next. Find The OIDs</p>
<p style="margin-top: 0.4em;margin-right: 0px;margin-bottom: 0.5em;margin-left: 0px;line-height: 1.5em">When MIB values fail, it is best to try to find the exact OID value. Like most network equipment manufacturers, Cisco has an FTP site from which you can download both MIBs and OIDs. The SNMP files for Cisco&#8217;s devices can be found at ftp.cisco.com in the /pub/mibs directory; OIDs are in the oid directory beneath that.</p>
<p style="margin-top: 0.4em;margin-right: 0px;margin-bottom: 0.5em;margin-left: 0px;line-height: 1.5em">After looking at all the OID files, you decide that the file CISCO-PROCESS-MIB.oid will contain the necessary values and find these entries inside it.</p>
<pre style="color: black;background-color: #f9f9f9;line-height: 1.1em;padding: 1em;border: 1px dashed #2f6fab">"cpmCPUTotalPhysicalIndex"  "1.3.6.1.4.1.9.9.109.1.1.1.1.2"
"cpmCPUTotal5sec"           "1.3.6.1.4.1.9.9.109.1.1.1.1.3"
"cpmCPUTotal1min"           "1.3.6.1.4.1.9.9.109.1.1.1.1.4"
"cpmCPUTotal5min"           "1.3.6.1.4.1.9.9.109.1.1.1.1.5"
"cpmCPUTotal5secRev"        "1.3.6.1.4.1.9.9.109.1.1.1.1.6"
"cpmCPUTotal1minRev"        "1.3.6.1.4.1.9.9.109.1.1.1.1.7"
"cpmCPUTotal5minRev"        "1.3.6.1.4.1.9.9.109.1.1.1.1.8"</pre>
<h2 style="color: teal;background-color: initial;font-weight: normal;margin-top: 0px;margin-right: 0px;margin-bottom: 0.6em;margin-left: 0px;padding-top: 0.5em;padding-bottom: 0.17em;border-bottom-width: 1px;border-bottom-style: solid;border-bottom-color: #aaaaaa;font-size: 19px"><span>Testing The OIDs</span></h2>
<p style="margin-top: 0.4em;margin-right: 0px;margin-bottom: 0.5em;margin-left: 0px;line-height: 1.5em">As you can see, all the OIDs are a part of the same tree starting with 1.3.6.1.4.1.9.9.109.1.1.1.1. The OIDs provided may be incomplete, so it is best to use the snmpwalk command to try to get all the values below this root first.</p>
<pre style="color: black;background-color: #f9f9f9;line-height: 1.1em;padding: 1em;border: 1px dashed #2f6fab">[root@bigboy tmp]# snmpwalk -v1 -c craz33guy cisco-switch 1.3.6.1.4.1..9.9.109.1.1.1.1
SNMPv2-SMI::enterprises.9.9.109.1.1.1.1.2.1 = INTEGER: 0
SNMPv2-SMI::enterprises.9.9.109.1.1.1.1.3.1 = Gauge32: 32
SNMPv2-SMI::enterprises.9.9.109.1.1.1.1.4.1 = Gauge32: 32
SNMPv2-SMI::enterprises.9.9.109.1.1.1.1.5.1 = Gauge32: 32
[root@bigboy tmp]#</pre>
<p style="margin-top: 0.4em;margin-right: 0px;margin-bottom: 0.5em;margin-left: 0px;line-height: 1.5em">Although listed in the OID file, 1.1.1.1.6, 1.1.1.1.7, and 1.1.1.1.8 are not supported. Notice also how SNMP has determined that the first part of the OID value (1.3.6.1.4.1) in the original OID file maps to the word &#8220;enterprise&#8221;.</p>
<p style="margin-top: 0.4em;margin-right: 0px;margin-bottom: 0.5em;margin-left: 0px;line-height: 1.5em">Next, you can use one the snmpget command to set only one of the OID values returned by snmpwalk.</p>
<pre style="color: black;background-color: #f9f9f9;line-height: 1.1em;padding: 1em;border: 1px dashed #2f6fab">[root@bigboy tmp]# snmpget -v1 -c craz33guy cisco-switch \
enterprises.9.9.109.1.1.1.1.5.1
SNMPv2-SMI::enterprises.9.9.109.1.1.1.1.5.1 = Gauge32: 33
[root@bigboy tmp]#</pre>
<p style="margin-top: 0.4em;margin-right: 0px;margin-bottom: 0.5em;margin-left: 0px;line-height: 1.5em">Success! Now you can use this OID value, enterprises.9.9.109.1.1.1.1.5.1, for your MRTG queries.</p>
<h1 style="color: green;background-color: initial;font-weight: normal;margin-top: 0px;margin-right: 0px;margin-bottom: 0.6em;margin-left: 0px;padding-top: 0.5em;padding-bottom: 0.17em;border-bottom-width: 2px;border-bottom-style: solid;border-bottom-color: #048444;font-size: 24px"><span>Speeding up MRTG with RRDtool</span></h1>
<p style="margin-top: 0.4em;margin-right: 0px;margin-bottom: 0.5em;margin-left: 0px;line-height: 1.5em">MRTG is a very useful program but it has a limitation. All the graphs and web pages are recreated each time a device is polled. This can potentially overload your MRTG server especially if you have a large number of monitored devices and the graphs take more than five minutes to generate. RRDtool is an application written by the creator of MRTG that can store general purpose data, but generates graphs on demand. Integrating MRTG with RRDtool can have very noticeable performance benefits. The example that follows will show you how to quickly implement a general purpose solution.</p>
<h2 style="color: teal;background-color: initial;font-weight: normal;margin-top: 0px;margin-right: 0px;margin-bottom: 0.6em;margin-left: 0px;padding-top: 0.5em;padding-bottom: 0.17em;border-bottom-width: 1px;border-bottom-style: solid;border-bottom-color: #aaaaaa;font-size: 19px"><span>Scenario</span></h2>
<p style="margin-top: 0.4em;margin-right: 0px;margin-bottom: 0.5em;margin-left: 0px;line-height: 1.5em">The use of RRDtool is needed to reduce the load on a monitoring server that has been experiencing very sluggish performance due to the amount of MRTG graphs it has to regenerate every polling cycle.</p>
<ul>
<li>Due to space constraints, the RRD database needs to be located in the /var partition.</li>
<li>The server has a default Apache configuration with the CGI files needed for dynamically generated content being located in the /var/www/cgi-bin directory.</li>
<li>A CGI script is required that will read the new MRTG data in RRDtool format.</li>
<li>The MRTG configuration file is /etc/mrtg/mrtg.cfg.</li>
</ul>
<p style="margin-top: 0.4em;margin-right: 0px;margin-bottom: 0.5em;margin-left: 0px;line-height: 1.5em">Here&#8217;s how to proceed.</p>
<h2 style="color: teal;background-color: initial;font-weight: normal;margin-top: 0px;margin-right: 0px;margin-bottom: 0.6em;margin-left: 0px;padding-top: 0.5em;padding-bottom: 0.17em;border-bottom-width: 1px;border-bottom-style: solid;border-bottom-color: #aaaaaa;font-size: 19px"><span>Installing RRDtool</span></h2>
<p style="margin-top: 0.4em;margin-right: 0px;margin-bottom: 0.5em;margin-left: 0px;line-height: 1.5em">The RRDtool and RRDtool PERL module file can be downloaded from its website at<a href="http://people.ee.ethz.ch/~oetiker/webtools/rrdtool/">http://people.ee.ethz.ch/~oetiker/webtools/rrdtool/</a>, but installation can be tricky as the installation program may look for certain supporting libraries in the wrong directories.</p>
<p style="margin-top: 0.4em;margin-right: 0px;margin-bottom: 0.5em;margin-left: 0px;line-height: 1.5em">Fortunately the prerequisite rrdtool and rrdtool-perl packages now come as part of most Linux distributions. For more details on installing packages, see Chapter 6, &#8220;<a title="Quick HOWTO : Ch06 : Installing Linux Software" href="http://www.linuxhomenetworking.com/wiki/index.php/Quick_HOWTO_:_Ch06_:_Installing_Linux_Software">Installing Linux Software</a>&#8220;).</p>
<h2 style="color: teal;background-color: initial;font-weight: normal;margin-top: 0px;margin-right: 0px;margin-bottom: 0.6em;margin-left: 0px;padding-top: 0.5em;padding-bottom: 0.17em;border-bottom-width: 1px;border-bottom-style: solid;border-bottom-color: #aaaaaa;font-size: 19px"><span>Storing the MRTG Data in RRDtool Format</span></h2>
<p style="margin-top: 0.4em;margin-right: 0px;margin-bottom: 0.5em;margin-left: 0px;line-height: 1.5em">This phase of the integration process can be done in a few minutes, but the steps can be tricky:</p>
<ul>
<li>The first step is to add some new options to your cfgmaker command. The first indicates that MRTG should only store rrdtool formatted data, and the second defines the /var/mrtg directory in which it should be stored. For added security, the directory should be external to your web server&#8217;s document root.</li>
</ul>
<pre style="color: black;background-color: #f9f9f9;line-height: 1.1em;padding: 1em;border: 1px dashed #2f6fab">--global 'LogFormat: rrdtool' --global "workdir: /var/mrtg"  --global 'IconDir: /mrtg'</pre>
<dl>
<dd>Finally, you should also specify an icon directory which specifies the location of all miscellaneous MRTG web page icons. The RRD web interface script we&#8217;ll install later uses an incorrect location. The icon directory /mrtg is actually a partial URL location. In this Fedora scenario we are using the default Apache configuration which locates the MRTG icon files in the /var/www/mrtg directory. If you are using a non default Apache MRTG configuration or are using other Linux distributions or versions you may have to copy the icons to the custom directory in which the MRTG PNG format icon files are located.</dd>
</dl>
<dl>
<dd>The cfgmaker program is simple to use and is covered in in Chapter 22, &#8220;<a title="Quick HOWTO : Ch22 : Monitoring Server Performance" href="http://www.linuxhomenetworking.com/wiki/index.php/Quick_HOWTO_:_Ch22_:_Monitoring_Server_Performance">Monitoring Server Performance</a>&#8220;.</dd>
</dl>
<ul>
<li>The next step is to create the data repository directory /var/mrtg and make it be owned by the apache user and process that runs the default Linux web server application.</li>
</ul>
<pre style="color: black;background-color: #f9f9f9;line-height: 1.1em;padding: 1em;border: 1px dashed #2f6fab">[root@bigboy tmp]# mkdir /var/mrtg
[root@bigboy tmp]# chown apache /var/mrtg
[root@bigboy tmp]#</pre>
<dl>
<dd><strong>Note:</strong> If you are using SELinux you&#8217;ll have to change the context of this directory to match that of the /var/www/html directory so that the apache process will be able to read the database files when your CGI script needs them. These commands compare the contexts of the both directories and apply the correct set to /var/mrtg.</dd>
</dl>
<dl>
<dd>Please refer to Chapter 20, &#8220;<a title="Quick HOWTO : Ch20 : The Apache Web Server" href="http://www.linuxhomenetworking.com/wiki/index.php/Quick_HOWTO_:_Ch20_:_The_Apache_Web_Server"> The Apache Web Server</a>&#8221; for more details on file contexts with Apache.</dd>
</dl>
<pre style="color: black;background-color: #f9f9f9;line-height: 1.1em;padding: 1em;border: 1px dashed #2f6fab">[root@bigboy tmp]# ls -alZ /var/www | grep html
drwxr-xr-x  root     root     system_u:object_r:httpd_sys_content_t html
[root@bigboy tmp]# ls -alZ /var | grep mrtg
drwxr-xr-x  apache   root     root:object_r:var_t              mrtg
[root@bigboy tmp]# chcon -R -u system_u -r object_r -t httpd_sys_content_t /var/mrtg
[root@bigboy tmp]#</pre>
<ul>
<li>We now need to test that the RRD files are being created correctly. Run MRTG using the /etc/mrtg/mrtg.cfg file as the source configuration file then test to see if the contents of the /var/mrtg directory have changed. Success!</li>
</ul>
<pre style="color: black;background-color: #f9f9f9;line-height: 1.1em;padding: 1em;border: 1px dashed #2f6fab">[root@bigboy tmp]# ls /var/mrtg/
localhost_192.168.1.100.rrd
[root@bigboy tmp]#</pre>
<p style="margin-top: 0.4em;margin-right: 0px;margin-bottom: 0.5em;margin-left: 0px;line-height: 1.5em">The files are being created properly. Now we need to find a script to read the new data format and present it in a web format. This will be discussed next.</p>
<h2 style="color: teal;background-color: initial;font-weight: normal;margin-top: 0px;margin-right: 0px;margin-bottom: 0.6em;margin-left: 0px;padding-top: 0.5em;padding-bottom: 0.17em;border-bottom-width: 1px;border-bottom-style: solid;border-bottom-color: #aaaaaa;font-size: 19px"><span>The MRTG / RRDtool Integration Script</span></h2>
<p style="margin-top: 0.4em;margin-right: 0px;margin-bottom: 0.5em;margin-left: 0px;line-height: 1.5em">The MRTG website recommends the script located on the mrtg-rrd website (<a href="http://www.fi.muni.cz/~kas/mrtg-rrd/">http://www.fi.muni.cz/~kas/mrtg-rrd/</a>) as being a good one to use. Let&#8217;s go ahead and install it.</p>
<ul>
<li>Download the script using wget. The site lists several versions; make sure you get the latest one.</li>
</ul>
<pre style="color: black;background-color: #f9f9f9;line-height: 1.1em;padding: 1em;border: 1px dashed #2f6fab">[root@bigboy tmp]# wget <a href="ftp://ftp.linux.cz/pub/linux/people/jan_kasprzak/mrtg-rrd/mrtg-rrd-0.7.tar.gz">ftp://ftp.linux.cz/pub/linux/people/jan_kasprzak/mrtg-rrd/mrtg-rrd-0.7.tar.gz</a>
--12:42:12--  <a href="ftp://ftp.linux.cz/pub/linux/people/jan_kasprzak/mrtg-rrd/mrtg-rrd-0.7.tar.gz">ftp://ftp.linux.cz/pub/linux/people/jan_kasprzak/mrtg-rrd/mrtg-rrd-0.7.tar.gz</a>
           =&gt; `mrtg-rrd-0.7.tar.gz'
Resolving ftp.linux.cz... 147.251.48.205
Connecting to ftp.linux.cz|147.251.48.205|:21... connected.
Logging in as anonymous ... Logged in!
...
...
...
15:24:50 (53.53 KB/s) - `mrtg-rrd-0.7.tar.gz' saved [20863]
[root@bigboy tmp]# ls
mrtg-rrd-0.7.tar.gz
[root@bigboy tmp]#</pre>
<ul>
<li>Extract the contents of the tar file.</li>
</ul>
<pre style="color: black;background-color: #f9f9f9;line-height: 1.1em;padding: 1em;border: 1px dashed #2f6fab">[root@bigboy tmp]# tar -xzvf mrtg-rrd-0.7.tar.gz
mrtg-rrd-0.7/
mrtg-rrd-0.7/COPYING
mrtg-rrd-0.7/FAQ
mrtg-rrd-0.7/TODO
mrtg-rrd-0.7/Makefile
mrtg-rrd-0.7/mrtg-rrd.cgi
mrtg-rrd-0.7/ChangeLog
[root@bigboy tmp]#</pre>
<ul>
<li>Create the /var/www/cgi-bin/mrtg directory and copy the mrtg-rrd.cgi file to it.</li>
</ul>
<pre style="color: black;background-color: #f9f9f9;line-height: 1.1em;padding: 1em;border: 1px dashed #2f6fab">[root@bigboy tmp]# mkdir -p /var/www/cgi-bin/mrtg
[root@bigboy tmp]# cp mrtg-rrd-0.7/mrtg-rrd.cgi /var/www/cgi-bin/mrtg/
[root@bigboy tmp]#</pre>
<ul>
<li>Edit the mrtg-rrd.cgi file and make it refer to the /etc/mrtg/mrtg.cfg file for its configuration details, or you can specify all the .cfg files in your /etc/mrtg directory.</li>
</ul>
<pre style="color: black;background-color: #f9f9f9;line-height: 1.1em;padding: 1em;border: 1px dashed #2f6fab">#
# File: mrtg-rrd.cgi (Single File)
#

# EDIT THIS to reflect all your MRTG config files
BEGIN { @config_files = qw(/etc/mrtg/mrtg.cfg); }</pre>
<pre style="color: black;background-color: #f9f9f9;line-height: 1.1em;padding: 1em;border: 1px dashed #2f6fab">#
# File: mrtg-rrd.cgi (multipl .cfg files)
#

# EDIT THIS to reflect all your MRTG config files
BEGIN { @config_files = &lt;/etc/mrtg/*.cfg&gt;; }</pre>
<p style="margin-top: 0.4em;margin-right: 0px;margin-bottom: 0.5em;margin-left: 0px;line-height: 1.5em">
<ul>
<li>You should now be able to access your MRTG RRD graphs by visiting this URL:</li>
</ul>
<pre style="color: black;background-color: #f9f9f9;line-height: 1.1em;padding: 1em;border: 1px dashed #2f6fab"><a href="http://www.my-web-site.org/cgi-bin/mrtg/mrtg-rrd.cgi">http://www.my-web-site.org/cgi-bin/mrtg/mrtg-rrd.cgi</a></pre>
<p style="margin-top: 0.4em;margin-right: 0px;margin-bottom: 0.5em;margin-left: 0px;line-height: 1.5em">Once installed, RRDtool operates transparently with MRTG. You&#8217;ll have to remember to add the RRD statements to any new MRTG configurations and also add the configuration file to the CGI script. Our monitoring server can now breathe a little easier.</p>
<h1 style="color: green;background-color: initial;font-weight: normal;margin-top: 0px;margin-right: 0px;margin-bottom: 0.6em;margin-left: 0px;padding-top: 0.5em;padding-bottom: 0.17em;border-bottom-width: 2px;border-bottom-style: solid;border-bottom-color: #048444;font-size: 24px"><span>Troubleshooting</span></h1>
<p style="margin-top: 0.4em;margin-right: 0px;margin-bottom: 0.5em;margin-left: 0px;line-height: 1.5em">The troubleshooting techniques for advanced MRTG are similar to those mentioned in Chapter 22, &#8220;<a title="Quick HOWTO : Ch22 : Monitoring Server Performance" href="http://www.linuxhomenetworking.com/wiki/index.php/Quick_HOWTO_:_Ch22_:_Monitoring_Server_Performance">Monitoring Server Performance</a>&#8220;, but because you have done some customizations you&#8217;ll have to go the extra mile.</p>
<ul>
<li>Verify the IP address and community string of the target device you intend to poll.</li>
<li>Make sure you can do an SNMP walk of the target device. If not, revise your access controls on the target device and any firewall rules that may impede SNMP traffic.</li>
<li>Ensure you can do an SNMP get of the specific OID value listed in your MRTG configuration file.</li>
<li>Check your MRTG parameters to make sure they are correct. Gauge values defined as counter and vice versa will cause your graphs to have continuous zero values. Graph results that are eight times what you expect may have the bits parameter set.</li>
<li>There are a few errors common to initial RRDtool integration.</li>
</ul>
<dl>
<dd>Web messages like this where the reference to the MRTG configuration file in the CGI script was incorrect</dd>
</dl>
<pre style="color: black;background-color: #f9f9f9;line-height: 1.1em;padding: 1em;border: 1px dashed #2f6fab">Error: Cannot open config file: No such file or directory</pre>
<dl>
<dd>&#8220;Permission Denied&#8221; web messages are usually caused by incorrect file permissions and / or SELinux contexts</dd>
</dl>
<pre style="color: black;background-color: #f9f9f9;line-height: 1.1em;padding: 1em;border: 1px dashed #2f6fab">Error: RRDs::graph failed, opening '/var/mrtg/localhost_192.168.1.100.rrd': Permission denied</pre>
<dl>
<dd>Errors in the /var/log/httpd/errorlog file referring to files or directories that don&#8217;t exist can be caused by an incorrect IconDir statement in the MRTG configuration file.</dd>
</dl>
<pre style="color: black;background-color: #f9f9f9;line-height: 1.1em;padding: 1em;border: 1px dashed #2f6fab">[Wed Jan 04 15:42:13 2006] [error] [client 192.168.1.102] File does not exist: /var/www/html/var,
referer: <a href="http://bigboy/cgi-bin/mrtg/mrtg-rrd.cgi/">http://bigboy/cgi-bin/mrtg/mrtg-rrd.cgi/</a> 

[Wed Jan 04 15:45:46 2006] [error] [client 192.168.1.102] script not found or unable to stat:
 /var/www/cgi-bin/mrtg/mrtg-l.png, referer: <a href="http://bigboy/cgi-bin/mrtg/mrtg-rrd.cgi/">http://bigboy/cgi-bin/mrtg/mrtg-rrd.cgi/</a></pre>
<dl>
<dd>Errors caused by not installing the pre-requisite RRD RPM modules rrdtool, perl-RRD-Simple and rrdtool-perl.</dd>
</dl>
<pre style="color: black;background-color: #f9f9f9;line-height: 1.1em;padding: 1em;border: 1px dashed #2f6fab">ERROR: could not find RRDs.pm. Use LibAdd: in mrtg.cfg to help mrtg find RRDs.pm</pre>
<p style="margin-top: 0.4em;margin-right: 0px;margin-bottom: 0.5em;margin-left: 0px;line-height: 1.5em">These quick steps should be sufficient in most cases and will reward you with a more manageable network.</p>
<h1 style="color: green;background-color: initial;font-weight: normal;margin-top: 0px;margin-right: 0px;margin-bottom: 0.6em;margin-left: 0px;padding-top: 0.5em;padding-bottom: 0.17em;border-bottom-width: 2px;border-bottom-style: solid;border-bottom-color: #048444;font-size: 24px"><span>Conclusion</span></h1>
<p style="margin-top: 0.4em;margin-right: 0px;margin-bottom: 0.5em;margin-left: 0px;line-height: 1.5em">Using the guidelines in this chapter you should be able to graph most SNMP MIB values available on any type of device. MRTG is an excellent, flexible monitoring tool and should be considered as a part of any systems administrator&#8217;s server management plans.</p>
<p style="margin-top: 0.4em;margin-right: 0px;margin-bottom: 0.5em;margin-left: 0px;line-height: 1.5em">
<p style="margin-top: 0.4em;margin-right: 0px;margin-bottom: 0.5em;margin-left: 0px;line-height: 1.5em">
<p style="margin-top: 0.4em;margin-right: 0px;margin-bottom: 0.5em;margin-left: 0px;line-height: 1.5em">SOURCE: <a href="http://www.linuxhomenetworking.com/wiki/index.php/Quick_HOWTO_:_Ch23_:_Advanced_MRTG_for_Linux">http://www.linuxhomenetworking.com/wiki/index.php/Quick_HOWTO_:_Ch23_:_Advanced_MRTG_for_Linux</a></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.nataprawira.com/tech/2010/12/02/advanced-mrtg-configurations/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Simple Web/Linux IP Address Lookup</title>
		<link>http://blog.nataprawira.com/tech/2009/10/22/ip-address-lookup/</link>
		<comments>http://blog.nataprawira.com/tech/2009/10/22/ip-address-lookup/#comments</comments>
		<pubDate>Wed, 21 Oct 2009 17:58:01 +0000</pubDate>
		<dc:creator>Denie</dc:creator>
				<category><![CDATA[BASH]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Scripting]]></category>
		<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[IP Address]]></category>
		<category><![CDATA[Lookup]]></category>

		<guid isPermaLink="false">http://blog.nataprawira.com/tech/?p=106</guid>
		<description><![CDATA[

If you&#8217;re going to be doing a lot of Geotargeting or IP Address  Lookups, please take a feed instead which will preserve both our bandwidth and  your bandwidth.
Simple GET
That said, there is an easy HTTP oriented API to locate IP  addresses and Geocode them. If you don&#8217;t supply the &#8220;?ip=aa.bb.cc.dd&#8221;  bit, [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;"><a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fblog.nataprawira.com%2Ftech%2F2009%2F10%2F22%2Fip-address-lookup%2F"><img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fblog.nataprawira.com%2Ftech%2F2009%2F10%2F22%2Fip-address-lookup%2F" height="61" width="51" /></a></div>
<!-- ALL ADSENSE ADS DISABLED -->
<p>If you&#8217;re going to be doing a lot of Geotargeting or IP Address  Lookups, please take a feed instead which will preserve both our bandwidth and  your bandwidth.</p>
<h1>Simple GET</h1>
<p>That said, there is an easy HTTP oriented API to locate <strong>IP  addresses</strong> and <strong>Geocode</strong> them. If you don&#8217;t supply the &#8220;?ip=aa.bb.cc.dd&#8221;  bit, then the ip address lookup of the calling machine will be located instead  (here, the aa,bb,cc,dd are decimal digits). If you add &amp;position=true to the  end of the URL then latitude and longitude will be returned also. Both HTML and  XML formats are supplied for your convenience.</p>
<blockquote><p><strong>http://api.hostip.info/country.php</strong><br />
US</p>
<p><strong>http://api.hostip.info/get_html.php?ip=12.215.42.19</strong><br />
Country: UNITED STATES (US)<br />
City: Sugar Grove, IL</p>
<p><strong>http://api.hostip.info/get_html.php?ip=12.215.42.19&amp;position=true</strong><br />
Country: UNITED STATES (US)<br />
City: Sugar Grove, IL<br />
Latitude: 41.7696<br />
Longitude: -88.4588</p>
<p><strong>http://api.hostip.info/?ip=12.215.42.19</strong><br />
[use the URL above for an example - XML too long to paste below]</p></blockquote>
<h1><span id="more-106"></span>Country Flag</h1>
<p>Paste the following code into your HTML to get a country  flag of the ip address. The database is significantly more accurate (it ought to  be 100%) for countries than for cities. It would be nice if y&#8217;all would make the  flag a link to the www.hostip.info home page (http://www.hostip.info/) so they  can come by if they&#8217;re interested &#8211; it&#8217;ll only benefit you in the long run.  After all, the results get more accurate as more visitors submit their IP  addresses!<br />
Flag of visitor&#8217;s location:</p>
<blockquote><p><strong>&lt;A HREF=&#8221;http://www.hostip.info&#8221;&gt;<br />
&lt;IMG SRC=&#8221;http://api.hostip.info/flag.php&#8221; BORDER=&#8221;0&#8243; ALT=&#8221;IP Address Lookup&#8221;&gt;<br />
&lt;/A&gt;</strong></p></blockquote>
<p>Flag of any IP address:</p>
<blockquote><p><strong>&lt;A HREF=&#8221;http://www.hostip.info&#8221;&gt;<br />
&lt;IMG SRC=&#8221;http://api.hostip.info/flag.php?ip=12.215.42.19&#8243; ALT=&#8221;IP Address Lookup&#8221;&gt;<br />
&lt;/A&gt;</strong></p></blockquote>
<h1>Embedded Applet</h1>
<p>The following is designed to be embedded within another HTML page using the OBJECT tag. This will reproduce the zoom-in applet, (or an explanatory message with a link to fix, if the IP address lookup is unknown). Which means you can embed the applet in your own site without needing to have the local database and map data (which runs to a few gigabytes&#8230;)</p>
<p>All you need do is include the OBJECT block below in your HTML.  Note, you can also add &#8220;?ip=aaa.bbb.ccc.ddd&#8221; to the frame.html url below to map a specific IP address.</p>
<blockquote>
<pre>&lt;OBJECT DATA='http://www.hostip.info/map/frame.html'

  TYPE='text/html' BORDER=0

  WIDTH=610 HEIGHT=330 HSPACE=0 VSPACE=0&gt;

&lt;/OBJECT&gt;</pre>
</blockquote>
<h1>*NIX Shell Script</h1>
<p>You can use the following shell script to call in your  favorite *NIX environment.</p>
<blockquote><p><strong>#!/bin/bash<br />
lynx -dump &#8220;http://api.hostip.info/get_html.php?ip=$1&#8243;</strong></p></blockquote>
]]></content:encoded>
			<wfw:commentRss>http://blog.nataprawira.com/tech/2009/10/22/ip-address-lookup/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Simple Check IP with PHP</title>
		<link>http://blog.nataprawira.com/tech/2009/06/16/simple-check-ip-with-php/</link>
		<comments>http://blog.nataprawira.com/tech/2009/06/16/simple-check-ip-with-php/#comments</comments>
		<pubDate>Mon, 15 Jun 2009 18:37:27 +0000</pubDate>
		<dc:creator>Denie</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Scripting]]></category>
		<category><![CDATA[Internet Protocol]]></category>
		<category><![CDATA[IP]]></category>

		<guid isPermaLink="false">http://blog.nataprawira.com/tech/?p=56</guid>
		<description><![CDATA[

You can use below simple PHP scripting to check IP address
&#60;?php
if(!empty($_SERVER["HTTP_X_FORWARDED_FOR"])){
echo &#8220;&#60;title&#62;&#8221;.$_SERVER["HTTP_X_FORWARDED_FOR"].&#8221; via &#8220;.$_SERVER["REMOTE_ADDR"].&#8221;&#60;/title&#62;\n\n&#8221;;
echo &#8220;Your IP: &#8220;.$_SERVER["HTTP_X_FORWARDED_FOR"] . &#8220;&#60;br /&#62;\n&#8221;;
echo &#8220;Proxy IP: &#8220;.$_SERVER["REMOTE_ADDR"] . &#8220;&#60;br /&#62;\n&#8221;;
$ip = $_SERVER["HTTP_X_FORWARDED_FOR"];
}else{
echo &#8220;&#60;title&#62;&#8221;.$_SERVER["REMOTE_ADDR"].&#8221;&#60;/title&#62;\n\n&#8221;;
echo &#8220;Your IP: &#8220;.$_SERVER["REMOTE_ADDR"] . &#8220;&#60;br /&#62;\n&#8221;;
$ip = $_SERVER["REMOTE_ADDR"];
}
echo &#8220;Date Time: &#8221; . date(&#8221;Y-m-d H:i:s&#8221;) . &#8220;&#60;br /&#62;\n&#8221;;
?&#62;
]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;"><a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fblog.nataprawira.com%2Ftech%2F2009%2F06%2F16%2Fsimple-check-ip-with-php%2F"><img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fblog.nataprawira.com%2Ftech%2F2009%2F06%2F16%2Fsimple-check-ip-with-php%2F" height="61" width="51" /></a></div>
<!-- ALL ADSENSE ADS DISABLED -->
<p><strong>You can use below simple PHP scripting to check IP address</strong></p>
<p>&lt;?php<br />
if(!empty($_SERVER["HTTP_X_FORWARDED_FOR"])){<br />
echo &#8220;&lt;title&gt;&#8221;.$_SERVER["HTTP_X_FORWARDED_FOR"].&#8221; via &#8220;.$_SERVER["REMOTE_ADDR"].&#8221;&lt;/title&gt;\n\n&#8221;;<br />
echo &#8220;Your IP: &#8220;.$_SERVER["HTTP_X_FORWARDED_FOR"] . &#8220;&lt;br /&gt;\n&#8221;;<br />
echo &#8220;Proxy IP: &#8220;.$_SERVER["REMOTE_ADDR"] . &#8220;&lt;br /&gt;\n&#8221;;<br />
$ip = $_SERVER["HTTP_X_FORWARDED_FOR"];<br />
}else{<br />
echo &#8220;&lt;title&gt;&#8221;.$_SERVER["REMOTE_ADDR"].&#8221;&lt;/title&gt;\n\n&#8221;;<br />
echo &#8220;Your IP: &#8220;.$_SERVER["REMOTE_ADDR"] . &#8220;&lt;br /&gt;\n&#8221;;<br />
$ip = $_SERVER["REMOTE_ADDR"];<br />
}<br />
echo &#8220;Date Time: &#8221; . date(&#8221;Y-m-d H:i:s&#8221;) . &#8220;&lt;br /&gt;\n&#8221;;<br />
?&gt;</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.nataprawira.com/tech/2009/06/16/simple-check-ip-with-php/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Linux Firewalls with IPTABLES (Good Tutorials)</title>
		<link>http://blog.nataprawira.com/tech/2009/02/23/linux-firewalls-with-iptables-good-tutorials/</link>
		<comments>http://blog.nataprawira.com/tech/2009/02/23/linux-firewalls-with-iptables-good-tutorials/#comments</comments>
		<pubDate>Mon, 23 Feb 2009 14:39:06 +0000</pubDate>
		<dc:creator>Denie</dc:creator>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[Scripting]]></category>
		<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[Firewall]]></category>
		<category><![CDATA[IPTables]]></category>

		<guid isPermaLink="false">http://blog.nataprawira.com/tech/?p=38</guid>
		<description><![CDATA[

I found good examples for this.
- Quick HOWTO (from LinuxHomeNetworking.com) &#8211; download
- Sample IPTABLES Configuration (RedHat/CentOS) &#8211; download
]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;"><a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fblog.nataprawira.com%2Ftech%2F2009%2F02%2F23%2Flinux-firewalls-with-iptables-good-tutorials%2F"><img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fblog.nataprawira.com%2Ftech%2F2009%2F02%2F23%2Flinux-firewalls-with-iptables-good-tutorials%2F" height="61" width="51" /></a></div>
<!-- ALL ADSENSE ADS DISABLED -->
<p>I found good examples for this.</p>
<p>- <strong><a title="Quick HOWTO" href="http://www.linuxhomenetworking.com/wiki/index.php/Quick_HOWTO_:_Ch14_:_Linux_Firewalls_Using_iptables" target="_blank">Quick HOWTO</a></strong> (from LinuxHomeNetworking.com) &#8211; <a title="DOWNLOAD" href="http://blog.nataprawira.com/tech/files/2009/02/linux-firewalls-using-iptables.pdf" target="_blank">download</a></p>
<p>- <strong><a title="Sample IPTables Configuration" href="http://www.liniac.upenn.edu/sysadmin/security/iptables.html" target="_blank">Sample IPTABLES Configuration</a></strong> (RedHat/CentOS) &#8211; <a title="DOWNLOAD" href="http://blog.nataprawira.com/tech/files/2009/02/sample-iptables-configuration-redhat.pdf" target="_blank">download</a></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.nataprawira.com/tech/2009/02/23/linux-firewalls-with-iptables-good-tutorials/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>How to protect your website using simple PHP scripts</title>
		<link>http://blog.nataprawira.com/tech/2009/02/20/how-to-protect-your-website-using-simple-php-scripts/</link>
		<comments>http://blog.nataprawira.com/tech/2009/02/20/how-to-protect-your-website-using-simple-php-scripts/#comments</comments>
		<pubDate>Fri, 20 Feb 2009 04:51:10 +0000</pubDate>
		<dc:creator>Denie</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Scripting]]></category>
		<category><![CDATA[Protection]]></category>

		<guid isPermaLink="false">http://blog.nataprawira.com/tech/?p=36</guid>
		<description><![CDATA[

Just put below on your top line of the scripts :
$ips = array(&#8221;127.0.0.1&#8243;,&#8221;aaa.bbb.ccc&#8221;,&#8221;xxx.yyy.zzz&#8221;);
$userip = $_SERVER['REMOTE_ADDR'];
foreach ($ips as $ip) {
if (!preg_match(&#8221;/$ip/i&#8221;, $userip)) {
echo &#8220;Access Denied!&#8221;;
exit;
}
}
Notes:
$ips is the allowed IP address range
Other way, you can use .htaccess to protect directories/files.
]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;"><a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fblog.nataprawira.com%2Ftech%2F2009%2F02%2F20%2Fhow-to-protect-your-website-using-simple-php-scripts%2F"><img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fblog.nataprawira.com%2Ftech%2F2009%2F02%2F20%2Fhow-to-protect-your-website-using-simple-php-scripts%2F" height="61" width="51" /></a></div>
<!-- ALL ADSENSE ADS DISABLED -->
<p>Just put below on your top line of the scripts :</p>
<p><strong>$ips = array(&#8221;127.0.0.1&#8243;,&#8221;aaa.bbb.ccc&#8221;,&#8221;xxx.yyy.zzz&#8221;);<br />
$userip = $_SERVER['REMOTE_ADDR'];<br />
foreach ($ips as $ip) {<br />
if (!preg_match(&#8221;/$ip/i&#8221;, $userip)) {<br />
echo &#8220;Access Denied!&#8221;;<br />
exit;<br />
}<br />
}</strong></p>
<p><span style="text-decoration: underline">Notes</span>:<br />
$ips is the allowed IP address range</p>
<p>Other way, you can use .htaccess to protect directories/files.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.nataprawira.com/tech/2009/02/20/how-to-protect-your-website-using-simple-php-scripts/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Install APC for PHP on Linux</title>
		<link>http://blog.nataprawira.com/tech/2009/01/19/install-apc-for-php-on-linux/</link>
		<comments>http://blog.nataprawira.com/tech/2009/01/19/install-apc-for-php-on-linux/#comments</comments>
		<pubDate>Mon, 19 Jan 2009 08:46:59 +0000</pubDate>
		<dc:creator>Denie</dc:creator>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[Scripting]]></category>
		<category><![CDATA[Alternative PHP Cache]]></category>
		<category><![CDATA[APC]]></category>

		<guid isPermaLink="false">http://blog.nataprawira.com/tech/?p=28</guid>
		<description><![CDATA[

APC is the Alternative PHP Cache, which is a free, open, and robust framework for caching and optimizing PHP intermediate code. What this means is that APC reads your PHP files, parses them into a more efficient binary format and then caches them in memory so that each request for your PHP files and PHP [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;"><a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fblog.nataprawira.com%2Ftech%2F2009%2F01%2F19%2Finstall-apc-for-php-on-linux%2F"><img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fblog.nataprawira.com%2Ftech%2F2009%2F01%2F19%2Finstall-apc-for-php-on-linux%2F" height="61" width="51" /></a></div>
<!-- ALL ADSENSE ADS DISABLED -->
<p><strong>APC </strong>is the Alternative PHP Cache, which is a free, open, and robust framework for caching and optimizing PHP intermediate code. What this means is that APC reads your PHP files, parses them into a more efficient binary format and then caches them in memory so that each request for your PHP files and PHP library files can be fed from the parsed cache. This will generally lead to a speed increase when serving a PHP site, especially one with a lot of library files. This post looks at how to install APC for PHP on Linux. The Linux distribution I used was CentOS 5, but it should be fairly similar for most distros.</p>
<p><span id="more-28"></span></p>
<p>First of all you need to download the APC code from the PHP PECL library.  Change directory to somewhere like <strong>/usr/local/src</strong> and then get the latest version:<strong></strong></p>
<blockquote><p><strong>$ wget http://pecl.php.net/get/APC</strong></p></blockquote>
<blockquote><p>&#8211;22:58:41&#8211;  http://pecl.php.net/get/APC<br />
Resolving pecl.php.net&#8230; 216.92.131.66<br />
Connecting to pecl.php.net|216.92.131.66|:80&#8230; connected.<br />
HTTP request sent, awaiting response&#8230; 200 OK<br />
Length: 114298 (112K) [application/octet-stream]<br />
Saving to: `APC-3.0.16.tgz&#8217;</p>
<p>100%[=====================&gt;] 114,298     97.1K/s   in 1.1s</p>
<p>22:58:43 (97.1 KB/s) &#8211; `APC-3.0.16.tgz&#8217; saved [114298/114298]</p></blockquote>
<p>So then you need to extract the files:</p>
<blockquote><p><strong>$ tar -zxf APC-3.0.16.tgz</strong></p></blockquote>
<p>and change into the APC directory:<strong></strong></p>
<blockquote><p><strong>$ cd APC-3.0.16</strong></p></blockquote>
<p>The next step is to run the &#8220;phpize&#8221; command. This requires that you have PHP development package installed. On CentOS this is php-devel (installed by running &#8220;yum install php-devel&#8221;) and it should have a similar name on other Linux distros.<strong></strong></p>
<blockquote><p><strong>$ phpize</strong></p>
<p>Configuring for:<br />
PHP Api Version:         20041225<br />
Zend Module Api No:      20050922<br />
Zend Extension Api No:   220051025</p></blockquote>
<p>You then configure APC, telling it where the executable file php-config is. If you don&#8217;t know where this is, then do this:</p>
<blockquote><p><strong>$ whereis php-config</strong></p></blockquote>
<p>which will return something like:</p>
<blockquote><p>php-config: /usr/bin/php-config /usr/share/man/man1/php-config.1.gz</p></blockquote>
<p>and then run the configure command like so:</p>
<blockquote><p><strong>./configure &#8211;enable-apc &#8211;enable-apc-mmap &#8211;with-apxs &#8211;with-php-config=/usr/bin/php-config</strong></p></blockquote>
<p>This will go ahead and do some configuring stuff which will look something like this:</p>
<blockquote><p>checking for egrep&#8230; grep -E<br />
checking for a sed that does not truncate output&#8230; /bin/sed<br />
&#8230;<br />
checking dynamic linker characteristics&#8230; GNU/Linux ld.so<br />
checking how to hardcode library paths into programs&#8230; immediate<br />
configure: creating ./config.status<br />
config.status: creating config.h</p></blockquote>
<p>Now that configure is done, it&#8217;s just a matter of running make :</p>
<blockquote><p><strong>$ make</strong></p></blockquote>
<blockquote><p>&#8230;<br />
Libraries have been installed in:<br />
/tmp/APC-3.0.16/modules</p>
<p>If you ever happen to want to link against installed libraries<br />
in a given directory, LIBDIR, you must either use libtool, and<br />
specify the full pathname of the library, or use the `-LLIBDIR&#8217;<br />
flag during linking and do at least one of the following:<br />
- add LIBDIR to the `LD_LIBRARY_PATH&#8217; environment variable<br />
during execution<br />
- add LIBDIR to the `LD_RUN_PATH&#8217; environment variable<br />
during linking<br />
- use the `-Wl,&#8211;rpath -Wl,LIBDIR&#8217; linker flag<br />
- have your system administrator add LIBDIR to `/etc/ld.so.conf&#8217;</p>
<p>See any operating system documentation about shared libraries for<br />
more information, such as the ld(1) and ld.so(8) manual pages.<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-</p>
<p>Build complete.<br />
(It is safe to ignore warnings about tempnam and tmpnam).</p></blockquote>
<p>and then make install:</p>
<blockquote><p><strong>$ make install</strong></p></blockquote>
<blockquote><p>Installing shared extensions:     /usr/lib64/php/modules/</p></blockquote>
<p>and restarting the Apache web server:</p>
<blockquote><p><strong>/etc/init.d/httpd restart</strong></p></blockquote>
<p>The APC cache will now be enabled. You can confirm this by creating a script which calls the phpinfo() command and looking for the APC section. It will have been switched on by default by adding a <strong>&#8220;extension=apc.so&#8221;</strong> line to your <strong>/etc/php.ini</strong> file, but you may want to add more settings to configure it more.</p>
<p>The INSTALL file suggests this (I have put the default values at the end of each line which is what is set if you don&#8217;t set anything in the php.ini file):</p>
<blockquote><p>apc.enabled=1                       # default = 1<br />
apc.shm_segments=1                  # default = 1<br />
apc.shm_size=128                    # default = 30<br />
apc.ttl=7200                        # default = 0<br />
apc.user_ttl=7200                   # default = 0<br />
apc.num_files_hint=1024             # default = 1000<br />
apc.mmap_file_mask=/tmp/apc.XXXXXX  # default = no value<br />
apc.enable_cli=1                    # default = 0</p></blockquote>
<p>And that&#8217;s all there is to it. There is also a monitoring script available so you can see what&#8217;s being cached and how much memory is being used etc. You can read about this in my &#8220;Displaying PHP APC Cache Information&#8221; post.</p>
<blockquote><p><em>Update November 5th 2008: I just installed this on another server and I didn&#8217;t have any issues installing it but it didn&#8217;t add the extension=apc.so line to the /etc/php.ini file automatically. So if it doesn&#8217;t appear to be working, check the php.ini to ensure the line is there and add it if not.</em></p></blockquote>
<p><a href="http://www.electrictoolbox.com/install-apc-php-linux/" target="_blank"><em><strong>Source</strong></em></a></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.nataprawira.com/tech/2009/01/19/install-apc-for-php-on-linux/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>IE ignores custom error pages</title>
		<link>http://blog.nataprawira.com/tech/2008/12/18/ie-ignores-custom-error-pages/</link>
		<comments>http://blog.nataprawira.com/tech/2008/12/18/ie-ignores-custom-error-pages/#comments</comments>
		<pubDate>Thu, 18 Dec 2008 04:10:45 +0000</pubDate>
		<dc:creator>Denie</dc:creator>
				<category><![CDATA[Internet]]></category>
		<category><![CDATA[Scripting]]></category>
		<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[Windows]]></category>
		<category><![CDATA[IE]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Tutorial]]></category>

		<guid isPermaLink="false">http://blog.nataprawira.com/tech/?p=20</guid>
		<description><![CDATA[

if you use php to create custom error  pages (such as header('HTTP/1.1 500 Internal Server Error');) Internet Explorer  ignores you custom page unless it is at least 512 (or sometimes 1024 bytes)
IE ignores custom error pages that are less than 512 (or from what i've  read 1024) bytes.
just place this before any [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;"><a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fblog.nataprawira.com%2Ftech%2F2008%2F12%2F18%2Fie-ignores-custom-error-pages%2F"><img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fblog.nataprawira.com%2Ftech%2F2008%2F12%2F18%2Fie-ignores-custom-error-pages%2F" height="61" width="51" /></a></div>
<!-- ALL ADSENSE ADS DISABLED -->
<div class="phpcode"><code><span class="html">if you use php to create custom error  pages (such as header('HTTP/1.1 500 Internal Server Error');) Internet Explorer  ignores you custom page unless it is at least 512 (or sometimes 1024 bytes)</p>
<p>IE ignores custom error pages that are less than 512 (or from what i've  read 1024) bytes.</p>
<p>just place this before any output on your custom error  page--- and be sure that your custom error page includes proper html tags (it  must have a &lt;/body&gt; for this specific example to work)</p>
<p><span class="default">&lt;?php<br />
</span><span class="comment">// set your custom error  header --- example --- header('HTTP/1.1 503 Service Unavailable');</p>
<p></span><span class="keyword">function </span><span class="default">padding</span><span class="keyword">(</span><span class="default">$html</span><span class="keyword">){<br />
return (</span><span class="default">$padding</span><span class="keyword">=</span><span class="default">1024</span><span class="keyword">-</span><span class="default">ob_get_length</span><span class="keyword">()) &gt; </span><span class="default">0 </span><span class="keyword">? </span><span class="default">str_replace</span><span class="keyword">(</span><span class="string">'&lt;/body&gt;'</span><span class="keyword">,</span><span class="string">'&lt;!--'</span><span class="keyword">. (</span><span class="default">$padding</span><span class="keyword">&gt;</span><span class="default">8</span><span class="keyword">?</span><span class="default">str_repeat</span><span class="keyword">(</span><span class="string">'  '</span><span class="keyword">,</span><span class="default">$padding</span><span class="keyword">-</span><span class="default">8</span><span class="keyword">)  :</span><span class="default">null </span><span class="keyword">).</span><span class="string">'--&gt;'</span><span class="keyword">.</span><span class="string">"\n"</span><span class="keyword">.</span><span class="string">'&lt;/body&gt;'</span><span class="keyword">,</span><span class="default">$html</span><span class="keyword">) : </span><span class="default">$html</span><span class="keyword">;<br />
}</p>
<p></span><span class="default">ob_start</span><span class="keyword">(</span><span class="string">'padding'</span><span class="keyword">);<br />
</span><span class="default">?&gt;<br />
</span><br />
and then place this somewhere within the html  error page output</p>
<p>&lt;!-- ---- --&gt;</p>
<p>that will auto-adjust to  pad the file to 1024 bytes to override the default Internet Explorer error  pages.</span> </code></div>
]]></content:encoded>
			<wfw:commentRss>http://blog.nataprawira.com/tech/2008/12/18/ie-ignores-custom-error-pages/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>How to show image file that&#8217;s not accessible to public ?</title>
		<link>http://blog.nataprawira.com/tech/2008/12/17/how-to-show-image-file-thats-not-accessible-to-public/</link>
		<comments>http://blog.nataprawira.com/tech/2008/12/17/how-to-show-image-file-thats-not-accessible-to-public/#comments</comments>
		<pubDate>Wed, 17 Dec 2008 07:03:40 +0000</pubDate>
		<dc:creator>Denie</dc:creator>
				<category><![CDATA[Scripting]]></category>
		<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Tutorial]]></category>

		<guid isPermaLink="false">http://blog.nataprawira.com/tech/?p=19</guid>
		<description><![CDATA[

You can use below script to show the image file for public access, but public don&#8217;t have direct access to the file itself. Because its located outside of the public folder.
&#60;?php
/* Read local file from /home/bar */
$localfile = file_get_contents("/home/userX/foo.jpg");
echo $localfile;
?&#62;
]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;"><a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fblog.nataprawira.com%2Ftech%2F2008%2F12%2F17%2Fhow-to-show-image-file-thats-not-accessible-to-public%2F"><img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fblog.nataprawira.com%2Ftech%2F2008%2F12%2F17%2Fhow-to-show-image-file-thats-not-accessible-to-public%2F" height="61" width="51" /></a></div>
<!-- ALL ADSENSE ADS DISABLED -->
<p>You can use below script to show the image file for public access, but public don&#8217;t have direct access to the file itself. Because its located outside of the public folder.</p>
<p><code><span style="color: #000000"><span style="color: #0000bb">&lt;?php<br />
</span><span style="color: #ff8000">/* Read local file from /home/bar */<br />
</span><span style="color: #0000bb">$localfile </span><span style="color: #007700">= </span><span style="color: #0000bb"><span style="color: #ffffff">file_get_contents</span></span><span style="color: #007700">(</span><span style="color: #dd0000">"/home/userX/foo.jpg"</span><span style="color: #007700">);</span></span></code></p>
<p><code><span style="color: #000000"><span style="color: #0000bb">echo $localfile;</span></span></code><br />
<span style="color: #0000bb">?&gt;</span></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.nataprawira.com/tech/2008/12/17/how-to-show-image-file-thats-not-accessible-to-public/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>How to know ID number that inserted by the mysql insert query ?</title>
		<link>http://blog.nataprawira.com/tech/2008/12/17/mysql_insert_id-example/</link>
		<comments>http://blog.nataprawira.com/tech/2008/12/17/mysql_insert_id-example/#comments</comments>
		<pubDate>Wed, 17 Dec 2008 06:52:44 +0000</pubDate>
		<dc:creator>Denie</dc:creator>
				<category><![CDATA[Scripting]]></category>
		<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Tutorial]]></category>

		<guid isPermaLink="false">http://blog.nataprawira.com/tech/?p=18</guid>
		<description><![CDATA[

Use below scripts :
mysql_insert_id() example
&#60;?php
$link = mysql_connect('localhost', 'mysql_user', 'mysql_password');
if (!$link) {
die('Could not connect: ' . mysql_error());
}
mysql_select_db('mydb');
mysql_query("INSERT INTO mytable (product) values ('kossu')");
printf("Last inserted record has id %d\n", mysql_insert_id());
?&#62; 
]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;"><a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fblog.nataprawira.com%2Ftech%2F2008%2F12%2F17%2Fmysql_insert_id-example%2F"><img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fblog.nataprawira.com%2Ftech%2F2008%2F12%2F17%2Fmysql_insert_id-example%2F" height="61" width="51" /></a></div>
<!-- ALL ADSENSE ADS DISABLED -->
<p>Use below scripts :</p>
<p><strong><strong>mysql_insert_id()</strong> example</strong></p>
<div class="example-contents"><code><span style="color: #000000"><span style="color: #0000bb">&lt;?php<br />
$link </span><span style="color: #007700">= </span><span style="color: #0000bb">mysql_connect</span><span style="color: #007700">(</span><span style="color: #dd0000">'localhost'</span><span style="color: #007700">, </span><span style="color: #dd0000">'mysql_user'</span><span style="color: #007700">, </span><span style="color: #dd0000">'mysql_password'</span><span style="color: #007700">);<br />
if (!</span><span style="color: #0000bb">$link</span><span style="color: #007700">) {<br />
die(</span><span style="color: #dd0000">'Could not connect: ' </span><span style="color: #007700">. </span><span style="color: #0000bb">mysql_error</span><span style="color: #007700">());<br />
}<br />
</span><span style="color: #0000bb">mysql_select_db</span><span style="color: #007700">(</span><span style="color: #dd0000">'mydb'</span><span style="color: #007700">);</p>
<p></span><span style="color: #0000bb">mysql_query</span><span style="color: #007700">(</span><span style="color: #dd0000">"INSERT INTO mytable (product) values ('kossu')"</span><span style="color: #007700">);<br />
</span><span style="color: #0000bb">printf</span><span style="color: #007700">(</span><span style="color: #dd0000">"Last inserted record has id %d\n"</span><span style="color: #007700">, </span><span style="color: #0000bb">mysql_insert_id</span><span style="color: #007700">());<br />
</span><span style="color: #0000bb">?&gt;</span> </span></code></div>
]]></content:encoded>
			<wfw:commentRss>http://blog.nataprawira.com/tech/2008/12/17/mysql_insert_id-example/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>How to fetch data(s) using mysql_fetch_assoc ?</title>
		<link>http://blog.nataprawira.com/tech/2008/12/17/an-expanded-mysql_fetch_assoc-example/</link>
		<comments>http://blog.nataprawira.com/tech/2008/12/17/an-expanded-mysql_fetch_assoc-example/#comments</comments>
		<pubDate>Wed, 17 Dec 2008 06:50:46 +0000</pubDate>
		<dc:creator>Denie</dc:creator>
				<category><![CDATA[Scripting]]></category>
		<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Tutorial]]></category>

		<guid isPermaLink="false">http://blog.nataprawira.com/tech/?p=17</guid>
		<description><![CDATA[


mysql_fetch_assoc — Fetch a result row as an associative array


&#60;?php
$conn
= mysql_connect("localhost", "mysql_user", "mysql_password");
if (!
$conn) {
echo "Unable to connect to DB: " . mysql_error();
exit;
}
if (!
mysql_select_db("mydbname")) {
echo "Unable to select mydbname: " . mysql_error();
exit;
}
$sql = "SELECT id as userid, fullname, userstatus
FROM   sometable
WHERE  userstatus = 1";
$result = mysql_query($sql);
if (!
$result) {
echo "Could not successfully run query ($sql) from DB: " . mysql_error();
exit;
}
if (
mysql_num_rows($result) == 0) {
echo "No rows found, nothing to print so am exiting";
exit;
}
// While a row of data exists, put that row in $row as an associative array
// Note: If you're expecting just one row, no need to use a loop
// Note: If you put extract($row); inside the following loop, you'll
//       then create $userid, $fullname, and $userstatus

while ($row = mysql_fetch_assoc($result)) {
echo $row["userid"];
echo $row["fullname"];
echo $row["userstatus"];
}
mysql_free_result($result);
?&#62; 
]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;"><a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fblog.nataprawira.com%2Ftech%2F2008%2F12%2F17%2Fan-expanded-mysql_fetch_assoc-example%2F"><img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fblog.nataprawira.com%2Ftech%2F2008%2F12%2F17%2Fan-expanded-mysql_fetch_assoc-example%2F" height="61" width="51" /></a></div>
<!-- ALL ADSENSE ADS DISABLED -->
<div class="example-contents">
<p><strong>mysql_fetch_assoc</strong> — Fetch a result row as an associative array</p>
</div>
<div class="example-contents"></div>
<div class="example-contents"><code><span style="color: #000000"><span style="color: #0000bb">&lt;?php</p>
<p>$conn</p>
<p></span><span style="color: #007700">= </span><span style="color: #0000bb">mysql_connect</span><span style="color: #007700">(</span><span style="color: #dd0000">"localhost"</span><span style="color: #007700">, </span><span style="color: #dd0000">"mysql_user"</span><span style="color: #007700">, </span><span style="color: #dd0000">"mysql_password"</span><span style="color: #007700">);</p>
<p>if (!</p>
<p></span><span style="color: #0000bb">$conn</span><span style="color: #007700">) {<br />
echo </span><span style="color: #dd0000">"Unable to connect to DB: " </span><span style="color: #007700">. </span><span style="color: #0000bb">mysql_error</span><span style="color: #007700">();<br />
exit;<br />
}</p>
<p>if (!</p>
<p></span><span style="color: #0000bb">mysql_select_db</span><span style="color: #007700">(</span><span style="color: #dd0000">"mydbname"</span><span style="color: #007700">)) {<br />
echo </span><span style="color: #dd0000">"Unable to select mydbname: " </span><span style="color: #007700">. </span><span style="color: #0000bb">mysql_error</span><span style="color: #007700">();<br />
exit;<br />
}</p>
<p></span><span style="color: #0000bb">$sql </span><span style="color: #007700">= </span><span style="color: #dd0000">"SELECT id as userid, fullname, userstatus<br />
FROM   sometable<br />
WHERE  userstatus = 1"</span><span style="color: #007700">;</p>
<p></span><span style="color: #0000bb">$result </span><span style="color: #007700">= </span><span style="color: #0000bb">mysql_query</span><span style="color: #007700">(</span><span style="color: #0000bb">$sql</span><span style="color: #007700">);</p>
<p>if (!</p>
<p></span><span style="color: #0000bb">$result</span><span style="color: #007700">) {<br />
echo </span><span style="color: #dd0000">"Could not successfully run query ($sql) from DB: " </span><span style="color: #007700">. </span><span style="color: #0000bb">mysql_error</span><span style="color: #007700">();<br />
exit;<br />
}</p>
<p>if (</p>
<p></span><span style="color: #0000bb">mysql_num_rows</span><span style="color: #007700">(</span><span style="color: #0000bb">$result</span><span style="color: #007700">) == </span><span style="color: #0000bb">0</span><span style="color: #007700">) {<br />
echo </span><span style="color: #dd0000">"No rows found, nothing to print so am exiting"</span><span style="color: #007700">;<br />
exit;<br />
}</p>
<p></span><span style="color: #ff8000">// While a row of data exists, put that row in $row as an associative array<br />
// Note: If you're expecting just one row, no need to use a loop<br />
// Note: If you put extract($row); inside the following loop, you'll<br />
//       then create $userid, $fullname, and $userstatus</span></span></code></div>
<div class="example-contents"><code><span style="color: #000000"><span style="color: #ff8000"><br />
</span><span style="color: #007700">while (</span><span style="color: #0000bb">$row </span><span style="color: #007700">= </span><span style="color: #0000bb">mysql_fetch_assoc</span><span style="color: #007700">(</span><span style="color: #0000bb">$result</span><span style="color: #007700">)) {<br />
echo </span><span style="color: #0000bb">$row</span><span style="color: #007700">[</span><span style="color: #dd0000">"userid"</span><span style="color: #007700">];<br />
echo </span><span style="color: #0000bb">$row</span><span style="color: #007700">[</span><span style="color: #dd0000">"fullname"</span><span style="color: #007700">];<br />
echo </span><span style="color: #0000bb">$row</span><span style="color: #007700">[</span><span style="color: #dd0000">"userstatus"</span><span style="color: #007700">];<br />
}</p>
<p></span><span style="color: #0000bb">mysql_free_result</span><span style="color: #007700">(</span><span style="color: #0000bb">$result</span><span style="color: #007700">);</p>
<p></span><span style="color: #0000bb">?&gt;</span> </span></code></div>
]]></content:encoded>
			<wfw:commentRss>http://blog.nataprawira.com/tech/2008/12/17/an-expanded-mysql_fetch_assoc-example/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>More about urlencode and urldecode</title>
		<link>http://blog.nataprawira.com/tech/2008/11/14/more-about-urlencode-and-urldecode/</link>
		<comments>http://blog.nataprawira.com/tech/2008/11/14/more-about-urlencode-and-urldecode/#comments</comments>
		<pubDate>Fri, 14 Nov 2008 03:14:30 +0000</pubDate>
		<dc:creator>Denie</dc:creator>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[Scripting]]></category>
		<category><![CDATA[urldecode]]></category>
		<category><![CDATA[urlencode]]></category>

		<guid isPermaLink="false">http://blog.nataprawira.com/tech/?p=14</guid>
		<description><![CDATA[

What you want is possible but it is considerably more work that it is practical to put in. Just say decode and let PHP do the calculations  
Anyway, thanks for an interesting question. Researching it taught me about both how UTF-8 works and about URL encoding in general.
First, link to an explanation of URL [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;"><a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fblog.nataprawira.com%2Ftech%2F2008%2F11%2F14%2Fmore-about-urlencode-and-urldecode%2F"><img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fblog.nataprawira.com%2Ftech%2F2008%2F11%2F14%2Fmore-about-urlencode-and-urldecode%2F" height="61" width="51" /></a></div>
<!-- ALL ADSENSE ADS DISABLED -->
<p>What you want is possible but it is considerably more work that it is practical to put in. Just say decode and let <span class="searchTerm">PHP</span> do the calculations <img src='http://blog.nataprawira.com/tech/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>Anyway, thanks for an interesting question. Researching it taught me about both how UTF-8 works and about URL encoding in general.</p>
<p>First, link to an explanation of URL encoding:<br />
<a rel="nofollow" href="http://www.blooberry.com/indexdot/html/topics/urlencoding.htm" target="_blank">http://www.blooberry.com/indexdot/html/topics/urlencoding.htm</a><br />
(disclosure: it&#8217;s written by someone I know <img src='http://blog.nataprawira.com/tech/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
<p>Secondly, here is how to find the <span class="searchTerm">character</span> from a URL encoding &#8211; manually!</p>
<p>Your <span class="searchTerm">character</span> above &#8211; &#8220;我&#8221; (according to babelfish.altavista.com it means &#8220;I&#8221; in <span class="searchTerm">Chinese</span>, if you can&#8217;t see it in your browser try to copy this and paste in your address bar: javascript:&#8217;&lt;html&gt;我</p>
<div id="EchoTopic" class="answerBody quoted">&lt;/html&gt;&#8217; ) is actually encoded as %E6%88%91.</p>
<p>First tool we use is the Windows calculator: open it and change to Scientific mode in the View menu. Then choose &#8220;Hex&#8221; format and type the hex value from above (simply strip out the % -signs): e68891.</p>
<p>Now click the &#8220;Bin&#8221; option to get the binary value of this hexadecimal number. Copy it and paste it in Notepad.</p>
<p>111001101000100010010001</p>
<p>This is the binary, UTF-8 encoded string. We want to un-UTF-8 it to find the Unicode value. Here is a technical documentation for UTF-8:<br />
<a rel="nofollow" href="ftp://ftp.isi.edu/in-notes/rfc2279.txt" target="_blank">ftp://ftp.isi.edu/in-notes/rfc2279.txt</a></p>
<p>First, start at the end of the string add linebreaks for each 8 digits.</p>
<p>11100110<br />
10001000<br />
10010001</p>
<p>From the first line, remove all the initial 1 &#8211; digits. From each of the next lines, remove the inital &#8220;10&#8243; &#8211; it will now look like this:</p>
<p>00110<br />
001000<br />
010001</p>
<p>Remove the line breaks and put it all on one line again:</p>
<p>00110001000010001</p>
<p>Copy that whole string and go back to the calculator. It should still be on &#8220;Binary&#8221; format, so just paste this new string.</p>
<p>If you now click &#8220;Dec&#8221; (for decimal or &#8220;normal&#8221; format), this is the exact number given in your first post because your browser translated a <span class="searchTerm">character</span> not supported in the POST encoding to a HTML entity &#8211; 25105.</p>
<p>Next, click &#8220;Hex&#8221;. The calculator will say &#8220;6211&#8243;. Now open the Windows &#8220;<span class="searchTerm">character</span> map&#8221; utility. Activate &#8220;Advanced view&#8221; if it doesn&#8217;t show the &#8220;Go to Unicode&#8221; box. Then, in the &#8220;Go to Unicode&#8221; box type 6211. Voila, it shows the <span class="searchTerm">character</span> you are looking for.</p>
<p>I&#8217;m sure you agree it is simpler to just type &lt;? urldecode(&#8217;%E6%88%91&#8242;) ?&gt; <img src='http://blog.nataprawira.com/tech/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
<p><em><strong><a href="http://www.experts-exchange.com/Web_Development/Web_Languages-Standards/PHP/PHP_Windows/Q_21190448.html" target="_self">source</a><br />
</strong></em></p>
</div>
]]></content:encoded>
			<wfw:commentRss>http://blog.nataprawira.com/tech/2008/11/14/more-about-urlencode-and-urldecode/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Nasty TinyMCE Error</title>
		<link>http://blog.nataprawira.com/tech/2008/11/13/nasty-tinymce-error/</link>
		<comments>http://blog.nataprawira.com/tech/2008/11/13/nasty-tinymce-error/#comments</comments>
		<pubDate>Thu, 13 Nov 2008 03:01:10 +0000</pubDate>
		<dc:creator>Denie</dc:creator>
				<category><![CDATA[HTML]]></category>
		<category><![CDATA[Scripting]]></category>
		<category><![CDATA[Error]]></category>
		<category><![CDATA[Nasty]]></category>
		<category><![CDATA[TinyMCE]]></category>

		<guid isPermaLink="false">http://blog.nataprawira.com/tech/?p=13</guid>
		<description><![CDATA[

There is a nasty tinyMCE error in Firefox that made my life a living hell.
First it was hard to track when it happened. Mostly when using tinyMCE in tabbed displays. I thought the two JavaScript libraries did not &#8220;support&#8221; each other. or maybe some weird variable they use together.
the error was visible in firebug (or [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;"><a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fblog.nataprawira.com%2Ftech%2F2008%2F11%2F13%2Fnasty-tinymce-error%2F"><img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fblog.nataprawira.com%2Ftech%2F2008%2F11%2F13%2Fnasty-tinymce-error%2F" height="61" width="51" /></a></div>
<!-- ALL ADSENSE ADS DISABLED -->
<p>There is a nasty tinyMCE error in Firefox that made my life a living hell.</p>
<p>First it was hard to track when it happened. Mostly when using tinyMCE in tabbed displays. I thought the two JavaScript libraries did not &#8220;support&#8221; each other. or maybe some weird variable they use together.</p>
<p>the error was visible in firebug (or error console):</p>
<blockquote><p><strong>uncaught exception: [Exception... "Component returned failure code: 0x80070057 (NS_ERROR_ILLEGAL_VALUE) [nsISelection.getRangeAt]&#8221;  nsresult: &#8220;0&#215;80070057 (NS_ERROR_ILLEGAL_VALUE)&#8221;  location: &#8220;JS frame :: http://xxx/mambots/editors/tinymce/jscripts/tiny_mce/tiny_mce_src.js :: anonymous :: line 6465&#8243;  data: no]</strong></p></blockquote>
<p>Then it happened also in a script that made the editor invisible and then back visible.</p>
<p>And it dawed me .. TinyMCE has some unexplained problem on submit when turning visible. you have to click on it first (give him focus), then it&#8217;s ok.</p>
<p>So i added in submit button (admin side &#8211; Joomla programmers know what i mean):</p>
<blockquote><p><strong>if (tinyMCE) tinyMCE.execCommand(&#8217;mceFocus&#8217;, false,&#8217;mailbody&#8217;);</strong></p></blockquote>
<p>as the first line. and all was fine&#8230;</p>
<p>Hope it helps other</p>
<p><a href="http://softmarket.ro/joomla-tips/nasty-tinymce-error.html">Source</a></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.nataprawira.com/tech/2008/11/13/nasty-tinymce-error/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Wordpress: Using a Cron job to keep things safe</title>
		<link>http://blog.nataprawira.com/tech/2008/08/13/wordpress-using-a-cron-job-to-keep-things-safe/</link>
		<comments>http://blog.nataprawira.com/tech/2008/08/13/wordpress-using-a-cron-job-to-keep-things-safe/#comments</comments>
		<pubDate>Wed, 13 Aug 2008 17:06:26 +0000</pubDate>
		<dc:creator>Denie</dc:creator>
				<category><![CDATA[Scripting]]></category>
		<category><![CDATA[Wordpress]]></category>

		<guid isPermaLink="false">http://blog.nataprawira.com/tech/?p=10</guid>
		<description><![CDATA[

NOTE:
This is maybe not suitable for WPMU


DOWNLOAD:
WordPress Backup with Cron.pdf

Original Links

Using a Cron job to keep things safe

What it does:

At midnight every night, the core WordPress tables are backed up, compressed and emailed to you. The backed up file is then deleted from the server.

For the script to work, you must have MUTT installed on [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;"><a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fblog.nataprawira.com%2Ftech%2F2008%2F08%2F13%2Fwordpress-using-a-cron-job-to-keep-things-safe%2F"><img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fblog.nataprawira.com%2Ftech%2F2008%2F08%2F13%2Fwordpress-using-a-cron-job-to-keep-things-safe%2F" height="61" width="51" /></a></div>
<!-- ALL ADSENSE ADS DISABLED -->
<blockquote><p><strong>NOTE:<br />
This is maybe not suitable for WPMU<br />
</strong></p>
</blockquote>
<p><em>DOWNLOAD:</em><br />
<a href='http://blog.efusionteam.com/denie/files/2008/03/wordpress-backup-with-cron.pdf' title='WordPress Backup with Cron.pdf'>WordPress Backup with Cron.pdf</a></p>
</p>
<p><a href="http://www.tamba2.org.uk/wordpress/cron/">Original Links</a></p>
</p>
<p><strong>Using a Cron job to keep things safe</strong></p>
</p>
<p><em>What it does:</em></p>
</p>
<p>At midnight every night, the core WordPress tables are backed up, compressed and emailed to you. The backed up file is then deleted from the server.</p>
</p>
<p>For the script to work, you must have MUTT installed on your server. Ask your host about this.<br />
Known hosts on which this works: A Small Orange, EMax hosting and Site5. If you know of any others, please let me know ?</p>
</p>
<p><em>Why it does this:</em></p>
</p>
<p>The only backup script I could find that did what I wanted was automysql. Problem was that this backed up the entire database and I wanted to exclude tables involved with stats and spam. There may well be a way to modify automysql but I could not find it. So I put this together.</p>
</p>
<p><em>License:</p>
</p>
<p>This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.<br />
(See the download).</em></p>
</p>
<p><em>Disclaimer:</p>
</p>
<p>I am not responsible if this does anything wrong. Before you install code you should be either familiar with what it does and how, or you should ask someone you trust &#8211; with a cron job asking your host is a &#8220;Good Thing&#8221;.</em></p>
</p>
<p><strong>Cron Job ?</strong></p>
</p>
<p>http://en.wikipedia.org/wiki/Cron explains. If you are unsure about Cron, or you need to know if you can run Cron jobs, talk to your host &#8211; only they can answer.</p>
</p>
<blockquote><p>NOTE</p>
</p>
<p>This ONLY backs up those tables which were created when you installed WP. If keeping all your stats, all your anti-spam settings, your user-online tables, your mostaccessed tables etc etc etc is important, just go use automysql &#8211; it is more fully featured. I&#8217;m working on the principle that if something catastrophic did happen then all you really want is your posts, comments and links.</p>
</blockquote>
<p><strong>The script</strong></p>
</p>
<p>In a nutshell it says this: &#8220;Get this database, save a copy, compress it, mail it, delete the copy.&#8221;</p>
</p>
<blockquote><p>
    #Set the 4 variables<br />
    #Replace what is AFTER the = with the information from your wp-config.php file<br />
    #That&#8217;s your information on the right okay ?</p>
</p>
<p>    DBNAME=DB_NAME</p>
</p>
<p>    DBPASS=DB_PASSWORD</p>
</p>
<p>    DBUSER=DB_USER</p>
</p>
<p>    #Keep the &#8221; around your address<br />
    EMAIL=&#8221;you@your_email.com&#8221;</p>
</p>
<p>    mysqldump &#8211;opt -u $DBUSER -p$DBPASS $DBNAME &gt; backup.sql<br />
    gzip backup.sql<br />
    DATE=`date +%Y%m%d` ; mv backup.sql.gz $DBNAME-backup-$DATE.sql.gz<br />
    echo &#8216;Blog Name:Your mySQL Backup is attached&#8217; | mutt -a $DBNAME-backup-$DATE.sql.gz $EMAIL -s &#8220;MySQL Backup&#8221;<br />
    rm $DBNAME-backup-$DATE.sql.gz
</p>
</blockquote>
</p>
<p>All you need to do is tell it which database and where to send it. Easy <img src='http://blog.nataprawira.com/tech/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
</p>
<p>See the &#8216;Blog Name:&#8217; bit ? Put something there to identify it for you. Useful if you have multiple cron running.</p>
</p>
<p>You can download the 2.0 script here: <a href="http://www.tamba2.org.uk/wordpress/cron/cronjob2.sh">http://www.tamba2.org.uk/wordpress/cron/cronjob2.sh</a></p>
</p>
<p><strong>Setting up the script</strong></p>
</p>
<p><em>Complete the details</em></p>
</p>
<p>The script is configured for the default &#8216;table_prefix&#8217; of wp_<br />
If you changed that prefix at the time of installation, you will need to change it in the script.</p>
</p>
<p>Then complete your email details. Remember that you could be getting emails that are over 1MB in size and increasing, and that these will arrive frequently. Be sure that your email account can accommodate these. (Finally ! A use for GMail !)</p>
</p>
<p><strong>Uploading the file</strong></p>
</p>
<p>You could put this cronjob file in any directory on your website BUT DO NOT.<br />
If you put this in your main directory or a sub-directory (which could be www / htdocs / public_html / mainwebsite_html) it is readable in a browser. Which means I can download it and find out how to access your database. So unless you want to take that risk, DO NOT UPLOAD THIS INTO YOUR MAIN DIRECTORY.</p>
</p>
<p>You need to upload the file above your main directory. That way it is not accessible from a browser.</p>
</p>
<p>The &#8216;etc&#8217; directory is one place for this to go. I&#8217;ll use my site as an example:<br />
When I login by ftp, I see these:</p>
</p>
<p>Click the indicated directory and upload your cron file into it.</p>
</p>
<p>Change the file permissions to 711</p>
</p>
<p>Now you need to get the PATH for your file.<br />
Login to your blog, click Options, then Miscellaneous. Look at what is in the box for this Destination directory:. It should look something like this</p>
</p>
<p>    <b>/home/name/public_html/blog/wp-images/ </b></p>
</p>
<p>The information you need is everything before the public_html.<br />
Remember &#8211; on your host it might be www or htdocs or mainwebsite_html or something very similar.</p>
</p>
<p>Your path will therefore be <b>/home/name/etc/cronjob.sh</b><br />
If you unsure at all, ask your host for the PATH to the directory where you uploaded the file.</p>
</p>
<p><strong>Setting the cron job</strong></p>
</p>
<p>Your host should offer a way of accessing and setting cron jobs. The screenshots here are for CPanel.</p>
</p>
<p>That line of information you just copied ? Paste that where shown.</p>
</p>
<p>Now check the other boxes &#8211; I get a backup every night at midnight so if you want the same, make the same options highlighted. (If you are considering running the cron job more frequently than once every 24 hours, you must read the Q &amp; A section at the bottom of this page).</p>
</p>
<p>Click the button beneath that says &#8220;Save Crontab&#8221;</p>
</p>
<p><strong>That&#8217;s it &#8211; all done !</strong></p>
</p>
<p><strong>Q &amp; A</strong></p>
</p>
<p>    * I&#8217;m still not sure about cron jobs. Will you do it for me ?<br />
          o No. Talk to your host, post in their support forums.<br />
    * How often can I run this ?<br />
          o Ask your host. I can&#8217;t see why you would want to run it more than once a day&#8230;..<br />
    * I&#8217;ve stayed up til midnight and nothing has happened !!<br />
          o Heh, I did this too. The script kicks in when it gets to midnight on the server. Look in your WordPress options for the Times in the weblog should differ by: and work out when it should arrive<br />
    * Can I test it sooner ?<br />
          o Yes &#8211; just alter it to work &#8220;Every 15 minutes&#8221; and &#8220;Every hour&#8221;. It will then send one fairly quickly. Remember to change it back !<br />
    * Can I leave the copy on the server too ?<br />
          o Yes. Remove the line rm backup-$DATE.sql.gz<br />
            Be sure to delete old ones regularly &#8211; this is a very fast way to fill server space !<br />
    * How do I backup more than one database ?<br />
          o You would need to run one cron job per database BUT the script would also need to take account of this and name the saved files appropriately. If you need this, I suggest you look at automysql for your needs.<br />
    * It does not work.<br />
          o The script tries 2 methods to send the email. If you do not get a backup file, and instead you get an error message, ask your host for advice. I am unable to advise on error messages. I have tested this script many times on my database and have had no untoward effects. Before looking for any help anywhere, check that you have done everything here.<br />
    * My backups are massive!<br />
          o The script backs up everything &#8211; including any stats / spam tables that have the same table prefix.<br />
            To reduce the size of the backup so it only gets what is essential then change this</p>
</p>
<p>                <b>mysqldump &#8211;opt -u $DBUSER -p$DBPASS $DBNAME &gt; backup.sql </b></p>
</p>
<p>            to</p>
</p>
<p>                <b>mysqldump &#8211;opt -u $DBUSER -p$DBPASS $DBNAME wp_users wp_posts [and all the other table names] &gt; backup.sql </b></p>
</p>
<p><em></p>
</p>
<p>These pages are independent of http://wordpress.org<br />
All design, content &amp; images © Mark 2004/2005/2006/2007. All rights reserved.</p>
</p>
<p>subnoto<br />
</em></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.nataprawira.com/tech/2008/08/13/wordpress-using-a-cron-job-to-keep-things-safe/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Wordpress: Upgrading (Not MU Version)</title>
		<link>http://blog.nataprawira.com/tech/2008/08/13/wordpress-upgrading-not-mu-version/</link>
		<comments>http://blog.nataprawira.com/tech/2008/08/13/wordpress-upgrading-not-mu-version/#comments</comments>
		<pubDate>Wed, 13 Aug 2008 17:05:44 +0000</pubDate>
		<dc:creator>Denie</dc:creator>
				<category><![CDATA[Scripting]]></category>
		<category><![CDATA[Wordpress]]></category>

		<guid isPermaLink="false">http://blog.nataprawira.com/tech/?p=9</guid>
		<description><![CDATA[

Original Page

DOWNLOAD:
Upgrading WordPress.pdf

Before you get started, make sure you meet the minimum requirements.

Three Step Upgrade

These are the short instructions, if you want more check out the extended upgrade instructions. If you experience problems with the Three Step Upgrade, you may want to review the more detailed upgrade instructions.

For these instructions, it is assumed that your [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;"><a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fblog.nataprawira.com%2Ftech%2F2008%2F08%2F13%2Fwordpress-upgrading-not-mu-version%2F"><img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fblog.nataprawira.com%2Ftech%2F2008%2F08%2F13%2Fwordpress-upgrading-not-mu-version%2F" height="61" width="51" /></a></div>
<!-- ALL ADSENSE ADS DISABLED -->
<p><strong><a href="http://codex.wordpress.org/Upgrading_WordPress">Original Page</a></strong></p>
</p>
<p><b>DOWNLOAD:</b><br />
<a href='http://blog.efusionteam.com/denie/files/2008/03/upgrading-wordpress.pdf' title='Upgrading WordPress.pdf'>Upgrading WordPress.pdf</a></p>
</p>
<p><em>Before you get started, make sure you meet the <a href="http://wordpress.org/about/requirements/">minimum requirements</a>.</em></p>
</p>
<p><strong>Three Step Upgrade</strong></p>
</p>
<p>These are the short instructions, if you want more check out the <a href="http://codex.wordpress.org/Upgrading_WordPress_Extended">extended upgrade instructions</a>. If you experience problems with the Three Step Upgrade, you may want to review the <a href="http://codex.wordpress.org/Upgrading_WordPress_Extended">more detailed upgrade instructions</a>.</p>
</p>
<p>For these instructions, it is assumed that your blog&#8217;s URL is http://example.com/wordpress/. Note that during the upgrade process access to your blog may not work for your visitors. You may consider a plugin like <a href="http://wordpress.org/extend/plugins/maintenance-mode/">Maintenance Mode</a>.</p>
</p>
<p><strong>Step 0: Before You Get Started</strong></p>
</p>
<p>    * Just in case something goes wrong, make sure you have a backup. <a href="http://codex.wordpress.org/WordPress_Backups">WordPress_Backups</a> is a comprehensive guide.</p>
</p>
<p>    * Deactivate your plugins. A plugin might not be compatible with the new version, so it&#8217;s nice to check for new versions of them and deactivate any that may cause problems. You can reactivate plugins one-by-one after the upgrade. </p>
</p>
<p><strong>Step 1: Replace WordPress files</strong></p>
</p>
<p>   1. Get the <a href="http://wordpress.org/download/">latest WordPress</a>. Either download and extract it to your computer or download it directly to the server.</p>
</p>
<p>   2. Copy the new files to your server, overwriting old files. You may use FTP or shell commands to do so. </p>
</p>
<blockquote><p><strong>NOTE</strong><br />
The wp-content folder requires special handling, as do the plugins and themes folders. You must copy over the contents of these folders, not the entire folder. Copying the entire folder overwrites all your customizations and added content.</p>
</p>
<p>Also take care to preserve the wp-config.php file in the root directory, as it contains your database sign-in information. Do note though that usually this will not be a problem since in a new installation the config file will be named wp-config-sample.php.</p>
</blockquote>
<p><strong>Step 2: Upgrade your installation</strong></p>
</p>
<p>   1. Visit the upgrade page. It will be at a URL like http://example.com/wordpress/wp-admin/upgrade.php. This updates your database to be compatible with the latest code, and before you do this your blog might look funny. </p>
</p>
<p><strong>Step 3: Do something nice for yourself</strong></p>
</p>
<p>If you have caching enabled, your changes will appear to users more immediately if you clear the cache at this point (and if you don&#8217;t, you may get confused when you see the old version number in page footers when you check to see if the upgrade worked).</p>
</p>
<p>Your WordPress installation is successfully upgraded. That&#8217;s as simple as we can make it without <a href="http://codex.wordpress.org/Installing/Updating_WordPress_with_Subversion">Updating WordPress Using Subversion</a>.</p>
</p>
<p>Consider rewarding yourself with a blog post about the upgrade, reading that book or article you&#8217;ve been putting off, or simply sitting back for a few moments and let the world pass you by.<br />
Troubleshooting</p>
</p>
<p>If anything has gone wrong the first thing to do is go through all the steps in our extended upgrade instructions. That page also has information about some of the most common problems we see.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.nataprawira.com/tech/2008/08/13/wordpress-upgrading-not-mu-version/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>PHP: Create ZIP file with PASSWORD</title>
		<link>http://blog.nataprawira.com/tech/2008/08/13/php-create-zip-file-with-password/</link>
		<comments>http://blog.nataprawira.com/tech/2008/08/13/php-create-zip-file-with-password/#comments</comments>
		<pubDate>Wed, 13 Aug 2008 17:04:50 +0000</pubDate>
		<dc:creator>Denie</dc:creator>
				<category><![CDATA[Scripting]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[ZIP]]></category>

		<guid isPermaLink="false">http://blog.nataprawira.com/tech/?p=8</guid>
		<description><![CDATA[


function zipme ($SOURCE, $PWD) {
    $software = &#8220;/usr/bin/zip&#8221;;
    $parameter = &#8220;-P&#8221;;
    $blank = &#8221; &#8220;;
    $dozip = $software . $blank . $parameter . $blank . $PWD . $blank . $SOURCE . &#8220;.zip&#8221; . $blank . $SOURCE;
    $output = `$dozip`;
  [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;"><a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fblog.nataprawira.com%2Ftech%2F2008%2F08%2F13%2Fphp-create-zip-file-with-password%2F"><img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fblog.nataprawira.com%2Ftech%2F2008%2F08%2F13%2Fphp-create-zip-file-with-password%2F" height="61" width="51" /></a></div>
<!-- ALL ADSENSE ADS DISABLED -->
<blockquote><p>
<strong>function zipme ($SOURCE, $PWD) {</strong><br />
    $software = &#8220;/usr/bin/zip&#8221;;<br />
    $parameter = &#8220;-P&#8221;;<br />
    $blank = &#8221; &#8220;;<br />
    $dozip = $software . $blank . $parameter . $blank . $PWD . $blank . $SOURCE . &#8220;.zip&#8221; . $blank . $SOURCE;<br />
    $output = `$dozip`;<br />
    return $output;<br />
<strong>}</strong>
</p>
</blockquote>
]]></content:encoded>
			<wfw:commentRss>http://blog.nataprawira.com/tech/2008/08/13/php-create-zip-file-with-password/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Creating ZIP Files on the Spot</title>
		<link>http://blog.nataprawira.com/tech/2008/08/13/creating-zip-files-on-the-spot/</link>
		<comments>http://blog.nataprawira.com/tech/2008/08/13/creating-zip-files-on-the-spot/#comments</comments>
		<pubDate>Wed, 13 Aug 2008 17:02:50 +0000</pubDate>
		<dc:creator>Denie</dc:creator>
				<category><![CDATA[Scripting]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://blog.nataprawira.com/tech/?p=6</guid>
		<description><![CDATA[

This interesting article found on Zend.com will explain to you how to create ZIP files on the fly using PHP.
Terms of Agreement:
By using this article, you agree to the following terms&#8230;
1) You may use this article in your own programs (and may compile it into a program and distribute it in compiled format for languages [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;"><a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fblog.nataprawira.com%2Ftech%2F2008%2F08%2F13%2Fcreating-zip-files-on-the-spot%2F"><img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fblog.nataprawira.com%2Ftech%2F2008%2F08%2F13%2Fcreating-zip-files-on-the-spot%2F" height="61" width="51" /></a></div>
<!-- ALL ADSENSE ADS DISABLED -->
<p>This interesting article found on Zend.com will explain to you how to create ZIP files on the fly using PHP.</p>
<p>Terms of Agreement:<br />
By using this article, you agree to the following terms&#8230;<br />
1) You may use this article in your own programs (and may compile it into a program and distribute it in compiled format for languages that allow it) freely and with no charge.<br />
2) You MAY NOT redistribute this article (for example to a web site) without written permission from the original author. Failure to do so is a violation of copyright laws.<br />
3) You may link to this article from another website, but ONLY if it is not wrapped in a frame.<br />
4) You will abide by any additional copyright restrictions which the author may have placed in the article or article&#8217;s description.<br />
Ever wondered how you could create ZIP files on the fly<b>?</b> In this article, which I found on Zend.com, you&#8217;ll be able to. The original version can be found here: http://www.zend.com/zend/spotlight/creating-zip-files2.php</p>
<p>     <b>?</b> php</p>
<p>    /*</p>
<p>    Zip file creation class<br />
    makes zip files on the fly&#8230;</p>
<p>    use the functions add_dir() and add_file() to build the zip file;<br />
    see example code below</p>
<p>    by Eric Mueller<br />
    http://www.themepark.com</p>
<p>    v1.1 9-20-01<br />
      &#8211; added comments to example</p>
<p>    v1.0 2-5-01</p>
<p>    initial version with:<br />
      &#8211; class appearance<br />
      &#8211; add_file() and file() methods<br />
      &#8211; gzcompress() output hacking<br />
    by Denis O.Philippov, webmaster@atlant.ru, http://www.atlant.ru</p>
<p>    */</p>
<p>    // official ZIP file format: http://www. // pkware.com/appnote.txt</p>
<p>    class zipfile<br />
    {  </p>
<p>        var $datasec = array(); // array to store compressed data<br />
        var $ctrl_dir = array(); // central directory<br />
        var $eof_ctrl_dir = &#8220;\x50\x4b\x05\x06\x00\x00\x00\x00&#8243;; //end of Central directory record<br />
        var $old_offset = 0;</p>
<p>        function add_dir($name)   </p>
<p>        // adds &#8220;directory&#8221; to archive &#8211; do this before putting any files in directory!<br />
        // $name &#8211; name of directory&#8230; like this: &#8220;path/&#8221;<br />
        // &#8230;then you can add files using add_file with names like &#8220;path/file.txt&#8221;<br />
        {<br />
            $name = str_replace(&#8221;\\&#8221;, &#8220;/&#8221;, $name);  </p>
<p>            $fr = &#8220;\x50\x4b\x03\x04&#8243;;<br />
            $fr .= &#8220;\x0a\x00&#8243;;    // ver needed to extract<br />
            $fr .= &#8220;\x00\x00&#8243;;    // gen purpose bit flag<br />
            $fr .= &#8220;\x00\x00&#8243;;    // compression method<br />
            $fr .= &#8220;\x00\x00\x00\x00&#8243;; // last mod time and date</p>
<p>            $fr .= pack(&#8221;V&#8221;,0); // crc32<br />
            $fr .= pack(&#8221;V&#8221;,0); //compressed filesize<br />
            $fr .= pack(&#8221;V&#8221;,0); //uncompressed filesize<br />
            $fr .= pack(&#8221;v&#8221;, strlen($name) ); //length of pathname<br />
            $fr .= pack(&#8221;v&#8221;, 0 ); //extra field length<br />
            $fr .= $name;<br />
            // end of &#8220;local file header&#8221; segment</p>
<p>            // no &#8220;file data&#8221; segment for path</p>
<p>            // &#8220;data descriptor&#8221; segment (optional but necessary if archive is not served as file)<br />
            $fr .= pack(&#8221;V&#8221;,$crc); //crc32<br />
            $fr .= pack(&#8221;V&#8221;,$c_len); //compressed filesize<br />
            $fr .= pack(&#8221;V&#8221;,$unc_len); //uncompressed filesize</p>
<p>            // add this entry to array<br />
            $this -&gt; datasec[] = $fr;</p>
<p>            $new_offset = strlen(implode(&#8221;", $this-&gt;datasec));</p>
<p>            // ext. file attributes mirrors MS-DOS directory attr byte, detailed<br />
            // at http://support.microsoft.com/support/kb/articles/Q125/0/19.asp</p>
<p>            // now add to central record<br />
            $cdrec = &#8220;\x50\x4b\x01\x02&#8243;;<br />
            $cdrec .=&#8221;\x00\x00&#8243;;    // version made by<br />
            $cdrec .=&#8221;\x0a\x00&#8243;;    // version needed to extract<br />
            $cdrec .=&#8221;\x00\x00&#8243;;    // gen purpose bit flag<br />
            $cdrec .=&#8221;\x00\x00&#8243;;    // compression method<br />
            $cdrec .=&#8221;\x00\x00\x00\x00&#8243;; // last mod time &amp; date<br />
            $cdrec .= pack(&#8221;V&#8221;,0); // crc32<br />
            $cdrec .= pack(&#8221;V&#8221;,0); //compressed filesize<br />
            $cdrec .= pack(&#8221;V&#8221;,0); //uncompressed filesize<br />
            $cdrec .= pack(&#8221;v&#8221;, strlen($name) ); //length of filename<br />
            $cdrec .= pack(&#8221;v&#8221;, 0 ); //extra field length<br />
            $cdrec .= pack(&#8221;v&#8221;, 0 ); //file comment length<br />
            $cdrec .= pack(&#8221;v&#8221;, 0 ); //disk number start<br />
            $cdrec .= pack(&#8221;v&#8221;, 0 ); //internal file attributes<br />
            $ext = &#8220;\x00\x00\x10\x00&#8243;;<br />
            $ext = &#8220;\xff\xff\xff\xff&#8221;;<br />
            $cdrec .= pack(&#8221;V&#8221;, 16 ); //external file attributes  &#8211; &#8216;directory&#8217; bit set</p>
<p>            $cdrec .= pack(&#8221;V&#8221;, $this -&gt; old_offset ); //relative offset of local header<br />
            $this -&gt; old_offset = $new_offset;</p>
<p>            $cdrec .= $name;<br />
            // optional extra field, file comment goes here<br />
            // save to array<br />
            $this -&gt; ctrl_dir[] = $cdrec;  </p>
<p>        }</p>
<p>        function add_file($data, $name)   </p>
<p>        // adds &#8220;file&#8221; to archive<br />
        // $data &#8211; file contents<br />
        // $name &#8211; name of file in archive. Add path if your want</p>
<p>        {<br />
            $name = str_replace(&#8221;\\&#8221;, &#8220;/&#8221;, $name);<br />
            //$name = str_replace(&#8221;\\&#8221;, &#8220;\\\\&#8221;, $name);</p>
<p>            $fr = &#8220;\x50\x4b\x03\x04&#8243;;<br />
            $fr .= &#8220;\x14\x00&#8243;;    // ver needed to extract<br />
            $fr .= &#8220;\x00\x00&#8243;;    // gen purpose bit flag<br />
            $fr .= &#8220;\x08\x00&#8243;;    // compression method<br />
            $fr .= &#8220;\x00\x00\x00\x00&#8243;; // last mod time and date</p>
<p>            $unc_len = strlen($data);<br />
            $crc = crc32($data);<br />
            $zdata = gzcompress($data);<br />
            $zdata = substr( substr($zdata, 0, strlen($zdata) &#8211; 4), 2); // fix crc bug<br />
            $c_len = strlen($zdata);<br />
            $fr .= pack(&#8221;V&#8221;,$crc); // crc32<br />
            $fr .= pack(&#8221;V&#8221;,$c_len); //compressed filesize<br />
            $fr .= pack(&#8221;V&#8221;,$unc_len); //uncompressed filesize<br />
            $fr .= pack(&#8221;v&#8221;, strlen($name) ); //length of filename<br />
            $fr .= pack(&#8221;v&#8221;, 0 ); //extra field length<br />
            $fr .= $name;<br />
            // end of &#8220;local file header&#8221; segment</p>
<p>            // &#8220;file data&#8221; segment<br />
            $fr .= $zdata;  </p>
<p>            // &#8220;data descriptor&#8221; segment (optional but necessary if archive is not served as file)<br />
            $fr .= pack(&#8221;V&#8221;,$crc); //crc32<br />
            $fr .= pack(&#8221;V&#8221;,$c_len); //compressed filesize<br />
            $fr .= pack(&#8221;V&#8221;,$unc_len); //uncompressed filesize</p>
<p>            // add this entry to array<br />
            $this -&gt; datasec[] = $fr;</p>
<p>            $new_offset = strlen(implode(&#8221;", $this-&gt;datasec));</p>
<p>            // now add to central directory record<br />
            $cdrec = &#8220;\x50\x4b\x01\x02&#8243;;<br />
            $cdrec .=&#8221;\x00\x00&#8243;;    // version made by<br />
            $cdrec .=&#8221;\x14\x00&#8243;;    // version needed to extract<br />
            $cdrec .=&#8221;\x00\x00&#8243;;    // gen purpose bit flag<br />
            $cdrec .=&#8221;\x08\x00&#8243;;    // compression method<br />
            $cdrec .=&#8221;\x00\x00\x00\x00&#8243;; // last mod time &amp; date<br />
            $cdrec .= pack(&#8221;V&#8221;,$crc); // crc32<br />
            $cdrec .= pack(&#8221;V&#8221;,$c_len); //compressed filesize<br />
            $cdrec .= pack(&#8221;V&#8221;,$unc_len); //uncompressed filesize<br />
            $cdrec .= pack(&#8221;v&#8221;, strlen($name) ); //length of filename<br />
            $cdrec .= pack(&#8221;v&#8221;, 0 ); //extra field length<br />
            $cdrec .= pack(&#8221;v&#8221;, 0 ); //file comment length<br />
            $cdrec .= pack(&#8221;v&#8221;, 0 ); //disk number start<br />
            $cdrec .= pack(&#8221;v&#8221;, 0 ); //internal file attributes<br />
            $cdrec .= pack(&#8221;V&#8221;, 32 ); //external file attributes &#8211; &#8216;archive&#8217; bit set</p>
<p>            $cdrec .= pack(&#8221;V&#8221;, $this -&gt; old_offset ); //relative offset of local header<br />
    //      &amp;n // bsp; echo &#8220;old offset is &#8220;.$this-&gt;old_offset.&#8221;, new offset is $new_offset<br />&#8220;;<br />
            $this -&gt; old_offset = $new_offset;</p>
<p>            $cdrec .= $name;<br />
            // optional extra field, file comment goes here<br />
            // save to central directory<br />
            $this -&gt; ctrl_dir[] = $cdrec;<br />
        }</p>
<p>        function file() { // dump out file<br />
            $data = implode(&#8221;", $this -&gt; datasec);<br />
            $ctrldir = implode(&#8221;", $this -&gt; ctrl_dir);  </p>
<p>            return<br />
                $data.<br />
                $ctrldir.<br />
                $this -&gt; eof_ctrl_dir.<br />
                pack(&#8221;v&#8221;, sizeof($this -&gt; ctrl_dir)).     // total # of entries &#8220;on this disk&#8221;<br />
                pack(&#8221;v&#8221;, sizeof($this -&gt; ctrl_dir)).     // total # of entries overall<br />
                pack(&#8221;V&#8221;, strlen($ctrldir)).             // size of central dir<br />
                pack(&#8221;V&#8221;, strlen($data)).                 // offset to start of central dir<br />
                &#8220;\x00\x00&#8243;;                             // .zip file comment length<br />
        }<br />
    }  </p>
<p>    <b>?</b></p>
<p>Example Usage of the Class</p>
<p>     <b>?</b> php</p>
<p>    $zipfile = new zipfile();  </p>
<p>    // add the subdirectory &#8230; important!<br />
    $zipfile -&gt; add_dir(&#8221;dir/&#8221;);</p>
<p>    // add the binary data stored in the string &#8216;filedata&#8217;<br />
    $filedata = &#8220;(read your file into $filedata)&#8221;;<br />
    $zipfile -&gt; add_file($filedata, &#8220;dir/file.txt&#8221;);  </p>
<p>    // the next three lines force an immediate download of the zip file:<br />
    header(&#8221;Content-type: application/octet-stream&#8221;);<br />
    header(&#8221;Content-disposition: attachment; filename=test.zip&#8221;);<br />
    echo $zipfile -&gt; file();  </p>
<p>    // OR instead of doing that, you can write out the file to the loca disk like this:<br />
    $filename = &#8220;output.zip&#8221;;<br />
    $fd = fopen ($filename, &#8220;wb&#8221;);<br />
    $out = fwrite ($fd, $zipfile -&gt; file());<br />
    fclose ($fd);</p>
<p>    // then offer it to the user to download:<br />
    <a href="output.zip">Click here to download the new zip file.</a></p>
<p>    <b>?</b></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.nataprawira.com/tech/2008/08/13/creating-zip-files-on-the-spot/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

