<?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>v-nessa.net &#187; tutorials</title>
	<atom:link href="http://www.v-nessa.net/tag/tutorials/feed" rel="self" type="application/rss+xml" />
	<link>http://www.v-nessa.net</link>
	<description>pink is the new black</description>
	<lastBuildDate>Mon, 06 Feb 2012 17:38:31 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
		<item>
		<title>phpacademy.org Offers FREE PHP Tutorials</title>
		<link>http://www.v-nessa.net/2011/03/31/phpacademy-org-offers-free-php-tutorials</link>
		<comments>http://www.v-nessa.net/2011/03/31/phpacademy-org-offers-free-php-tutorials#comments</comments>
		<pubDate>Thu, 31 Mar 2011 21:13:58 +0000</pubDate>
		<dc:creator>Nessa</dc:creator>
				<category><![CDATA[uncategorized]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[tutorials]]></category>

		<guid isPermaLink="false">http://www.v-nessa.net/?p=404</guid>
		<description><![CDATA[There&#8217;s a new site out there that&#8217;s offering high quality PHP video tutorials &#8211; for FREE!  All you PHP gurus, check out phpacademy.org.  They currently have over 200 PHP and MySQL tutorials for both beginner and intermediate users.  Unlike other PHP tutorial sites, phpacademy is unique because the tutorials are all on video, so there&#8217;s [...]]]></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%2Fwww.v-nessa.net%2F2011%2F03%2F31%2Fphpacademy-org-offers-free-php-tutorials"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fwww.v-nessa.net%2F2011%2F03%2F31%2Fphpacademy-org-offers-free-php-tutorials&amp;source=nessa421&amp;style=normal&amp;service=bit.ly&amp;b=2" height="61" width="50" /><br />
			</a>
		</div>
<p>There&#8217;s a new site out there that&#8217;s offering high quality PHP video tutorials &#8211; for FREE!  All you PHP gurus, check out <a href="http://phpacademy.org/" target="_blank">phpacademy.org</a>.  They currently have over 200 PHP and MySQL tutorials for both beginner and intermediate users.  Unlike other PHP tutorial sites, phpacademy is unique because the tutorials are all on video, so there&#8217;s less boring reading.  Did I also mention that it&#8217;s free?</p>
<p>Head on over and check them out, feel free to post comments and reviews here!</p>
<p><map name='google_ad_map_404_7fa65e237551a74a'>
<area shape='rect' href='http://imageads.googleadservices.com/pagead/imgclick/404?pos=0' coords='1,2,367,28' />
<area shape='rect' href='http://services.google.com/feedback/abg' coords='384,10,453,23'/></map>
<img usemap='#google_ad_map_404_7fa65e237551a74a' border='0' src='http://imageads.googleadservices.com/pagead/ads?format=468x30_aff_img&amp;client=&amp;channel=&amp;output=png&amp;cuid=404&amp;url= http%3A%2F%2Fwww.v-nessa.net%2F2011%2F03%2F31%2Fphpacademy-org-offers-free-php-tutorials' /></p><img src="http://www.v-nessa.net/?ak_action=api_record_view&id=404&type=feed" alt="" />]]></content:encoded>
			<wfw:commentRss>http://www.v-nessa.net/2011/03/31/phpacademy-org-offers-free-php-tutorials/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Command Line PHP: Part 3</title>
		<link>http://www.v-nessa.net/2010/05/25/command-line-php-part-3</link>
		<comments>http://www.v-nessa.net/2010/05/25/command-line-php-part-3#comments</comments>
		<pubDate>Tue, 25 May 2010 14:38:49 +0000</pubDate>
		<dc:creator>Nessa</dc:creator>
				<category><![CDATA[uncategorized]]></category>
		<category><![CDATA[code]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[tutorials]]></category>

		<guid isPermaLink="false">http://www.v-nessa.net/?p=331</guid>
		<description><![CDATA[This is part third and final part in my PHP command line tutorial series. If you didn&#8217;t see parts 1 and 2: Command Line PHP: Part 1 Command Line PHP: Part 2 More File and Disk Functions Getting Disk Space and Usage The disk_total_size and disk_free_space functions can tell you how much disk space you [...]]]></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%2Fwww.v-nessa.net%2F2010%2F05%2F25%2Fcommand-line-php-part-3"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fwww.v-nessa.net%2F2010%2F05%2F25%2Fcommand-line-php-part-3&amp;source=nessa421&amp;style=normal&amp;service=bit.ly&amp;b=2" height="61" width="50" /><br />
			</a>
		</div>
<p>This is part third and final part in my PHP command line tutorial series. If you didn&#8217;t see parts 1 and 2:</p>
<p><a href="http://www.v-nessa.net/2010/05/18/command-line-php-part-1" target="_blank">Command Line PHP: Part 1</a></p>
<p><a href="http://www.v-nessa.net/2010/05/21/command-line-php-part-2" target="_blank">Command Line PHP: Part 2</a></p>
<p><span id="more-331"></span></p>
<h2>More File and Disk Functions</h2>
<h3>Getting Disk Space and Usage</h3>
<p>The <a href="http://us2.php.net/manual/en/function.disk-total-space.php" target="_blank">disk_total_size</a> and <a href="http://us2.php.net/manual/en/function.disk-free-space.php" target="_blank">disk_free_space</a> functions can tell you how much disk space you have and how much is available, respectively:</p>
<p><code>$disksize = disk_total_space("/");<br />
$size = round(number_format($disksize / 1024 / 1024 / 1024, 2));</code></p>
<p><code>$diskfree = disk_free_space("/");<br />
$freesize = round(number_format($diskfree / 1024 / 1024 / 1024, 2));</code></p>
<p><code>echo "Total Disk Size: $size GB\n";<br />
echo "Free Disk Space: $freesize GB";</code></p>
<h3>Finding Files</h3>
<p>A little-known function called glob works sort of like the locate command, in that it will find files that match a certain string, but it only looks in the current folder and is not recursive. For example, the below code will search for all files in the current folder that end with .txt:</p>
<p><code>foreach (glob("*.txt") as $file) {<br />
echo "$file size " . filesize($file) . "\n";<br />
}</code></p>
<p>You can also use something like <a href="http://snippets.dzone.com/posts/show/4147" target="_blank">this example</a> to run as a loop and recursively search through folders.</p>
<h3>Getting File Path Information</h3>
<p>The famous <a href="http://php.net/pathinfo" target="_blank">pathinfo</a> function can give you information about a file on your system:</p>
<p><code>$file = "/etc/php5/cli/php.ini";<br />
if(file_exists($file)){<br />
$info = pathinfo($file);<br />
print_r($info);<br />
}</code></p>
<p>This will print out an array like below:</p>
<p><code>Array<br />
(<br />
[dirname] =&gt; /etc/php5/cli<br />
[basename] =&gt; php.ini<br />
[extension] =&gt; ini<br />
[filename] =&gt; php<br />
)</code></p>
<p>Which you can echo out values to and use in your scripts, for example:</p>
<p><code>$file = "/etc/php5/cli/php.ini";<br />
if(file_exists($file)){<br />
$info = pathinfo($file);<br />
$dir = $info[dirname];<br />
chdir($dir);<br />
echo "Changed directory to" . getcwd();<br />
}</code></p>
<p>There are also similar functions that will provide the same information, individually:</p>
<p><code>$file = "/etc/php5/cli/php.ini";</code><br />
<code><br />
echo "Absolute File Name: " . <strong>realpath</strong>($file) . "\n";<br />
echo "File Name: " . <strong>basename</strong>($file) . "\n";<br />
echo "File path: " . <strong>dirname</strong>($file) . "\n";</code></p>
<p>This will return:</p>
<p><code>Absolute File Name: /etc/php5/cli/php.ini<br />
File Name: php.ini<br />
File path: /etc/php5/cli</code></p>
<h2>Some Random Script Fragments and Functions</h2>
<p><strong>Prompt a user for input:</strong></p>
<p><code><strong>fwrite</strong>(<strong>STDOUT</strong>, "Hello...\nWhat is your name? ");<br />
$name = trim(<strong>fgets</strong>(<strong>STDIN</strong>));<br />
fwrite(STDOUT, "Hello, $name!\n");</code></p>
<p><strong>Print out your username and date:</strong></p>
<p><code>$me = exec('whoami');<br />
echo "Hello, " . $me . " The time is currently " .date("r") . "\n";</code></p>
<p><strong>Generate random strings and passwords:</strong></p>
<p><code>echo <strong>crypt</strong>("mypassword","randomsalt");<br />
echo <strong>md5</strong>("mypassword");</code></p>
<p><strong>Random password, variable length:</strong></p>
<p><code>function randomPass($length) {</code></p>
<p><code>$chars = "abcdefghijkmnopqrstuvwxyz023456789";<br />
srand((double)microtime()*1000000);<br />
$i = 0;<br />
$pass = '' ;</code></p>
<p><code>while ($i &lt;= $length) {<br />
$num = rand() % 33;<br />
$tmp = substr($chars, $num, 1);<br />
$pass = $pass . $tmp;<br />
$i++;<br />
}</code></p>
<p><code>return $pass;<br />
}</code></p>
<p><code>$password = randomPass(10);</code></p>
<p><code>echo "Your random password is: $password";</code></p>
<p><strong>List loaded PHP extensions, check is specific extension is loaded:</strong></p>
<p><code>$extensions = <strong>get_loaded_extensions</strong>();<br />
foreach ($extensions as &amp;$value) {<br />
echo $value . "\n";<br />
}</code></p>
<p><code>if (!<strong>extension_loaded</strong>('gd')) {<br />
echo "GD extension is not loaded";<br />
exit;<br />
}</code></p>
<p><strong>Get Server&#8217;s CPU Load:</strong></p>
<p><code>$load = <strong>sys_getloadavg</strong>();<br />
echo "Current: " . $load[0] . "\n";<br />
echo "5-min: " . $load[1] . "\n";<br />
echo "15-min: " . $load[2] . "\n";</code></p>
<p><strong>Get PHP memory limit and convert to human-readable format:</strong><br />
<code><br />
function convert($size)<br />
{<br />
$unit=array('b','kb','mb','gb','tb','pb');<br />
return @round($size/pow(1024,($i=floor(log($size,1024)))),2).' '.$unit[$i];<br />
}<br />
echo convert(memory_get_usage(true));</code></p>
<h2>Some Useful Links/Tutorials</h2>
<p><a href="http://articles.sitepoint.com/article/php-command-line-1" target="_blank">Command Line PHP Tutorial</a><br />
<a title="Simple System Maintenance with PHP-CLI" href="http://www.developertutorials.com/tutorials/php/simple-system-maintenance-with-php-cli-8-01-17/" target="_blank">Simple System Maintenance with PHP-CLI &#8211; Simple System Maintenance with PHP-CLI</a><br />
<a href="http://www.ibm.com/developerworks/opensource/library/os-php-command/index.html" target="_blank">Command Line PHP (IBM)</a><br />
<a href="http://kevin.vanzonneveld.net/techblog/article/create_daemons_in_php/" target="_blank">Running Daemons in PHP</a><br />
<a href="http://www.if-not-true-then-false.com/2010/php-class-for-coloring-php-command-line-cli-scripts-output-php-output-colorizing-using-bash-shell-colors/" target="_blank">PHP Class for Coloring Command Line Output</a><br />
<a href="http://brian.moonspot.net/php-progress-bar" target="_blank">PHP Command Line Progress Bar</a></p>
<p><map name='google_ad_map_331_7fa65e237551a74a'>
<area shape='rect' href='http://imageads.googleadservices.com/pagead/imgclick/331?pos=0' coords='1,2,367,28' />
<area shape='rect' href='http://services.google.com/feedback/abg' coords='384,10,453,23'/></map>
<img usemap='#google_ad_map_331_7fa65e237551a74a' border='0' src='http://imageads.googleadservices.com/pagead/ads?format=468x30_aff_img&amp;client=&amp;channel=&amp;output=png&amp;cuid=331&amp;url= http%3A%2F%2Fwww.v-nessa.net%2F2010%2F05%2F25%2Fcommand-line-php-part-3' /></p><img src="http://www.v-nessa.net/?ak_action=api_record_view&id=331&type=feed" alt="" />]]></content:encoded>
			<wfw:commentRss>http://www.v-nessa.net/2010/05/25/command-line-php-part-3/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Command Line PHP: Part 2</title>
		<link>http://www.v-nessa.net/2010/05/21/command-line-php-part-2</link>
		<comments>http://www.v-nessa.net/2010/05/21/command-line-php-part-2#comments</comments>
		<pubDate>Fri, 21 May 2010 19:51:25 +0000</pubDate>
		<dc:creator>Nessa</dc:creator>
				<category><![CDATA[uncategorized]]></category>
		<category><![CDATA[code]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[tutorials]]></category>

		<guid isPermaLink="false">http://www.v-nessa.net/?p=315</guid>
		<description><![CDATA[This post is continuing on my three-part series on command line PHP programming. Missed part one? It&#8217;s right behind you. This part will go over command execution and processes. Command Execution Let&#8217;s start with the basics &#8211; you need to execute an arbitrary command from your PHP script. The exec, shell_exec, passthru, and system functions [...]]]></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%2Fwww.v-nessa.net%2F2010%2F05%2F21%2Fcommand-line-php-part-2"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fwww.v-nessa.net%2F2010%2F05%2F21%2Fcommand-line-php-part-2&amp;source=nessa421&amp;style=normal&amp;service=bit.ly&amp;b=2" height="61" width="50" /><br />
			</a>
		</div>
<p>This post is continuing on my three-part series on command line PHP programming. Missed part one? <a href="http://www.v-nessa.net/2010/05/18/command-line-php-part-1" target="_blank">It&#8217;s right behind you</a>. This part will go over command execution and processes.</p>
<p><span id="more-315"></span></p>
<h2>Command Execution</h2>
<p>Let&#8217;s start with the basics &#8211; you need to execute an arbitrary command from your PHP script. The <a href="http://php.net/exec" target="_blank">exec</a>, <a href="http://php.net/shell_exec" target="_blank">shell_exec</a>, <a href="http://php.net/passthru" target="_blank">passthru</a>, and <a href="http://php.net/system" target="_blank">system</a> functions will take care of this for you:</p>
<p><code>exec("/usr/bin/perl /scripts/myscript.pl");</code></p>
<p>will do about the same thing as:</p>
<p><code>system("/usr/bin/perl /scripts/myscript.pl");</code></p>
<p>and</p>
<p><code>shell_exec("/usr/bin/perl /scripts/myscript.pl");</code></p>
<p>So what&#8217;s the difference between the three? A little, but not much. The <a href="http://php.net/system" target="_blank">system</a> function will place the output of the command in an output stream, and display the results whether you tell it to or not. However, it&#8217;s mostly useful to return a yes or no output (in the form of 1, 0, or -1) based on the exit code of the command it was executing. For example, the below script views the /proc/cpuinfo file and outputs a boolean value on whether the command executed:</p>
<p><code>$cpuinfo = system("cat /proc/cpuinfo",$exitcode);<br />
echo $exitcode;<br />
</code><br />
I could then use the boolean value to write an if statement, which is more accurate because I&#8217;m basing the condition on the output of the command itself rather than PHP returning output based on the fact that the command ran, ignoring errors the command may have posted:</p>
<p><code>if($exitcode == 1){<br />
echo "Command executed, but finished with errors";<br />
}</code></p>
<p>The annoying part with the system function though is that it doesn&#8217;t suppress the output of the command itself, but rather sends it directly to the output stream. What if you want to format the output of the command? Then you would use <a href="http://php.net/exec" target="_blank">exec</a>. Below is an example of using the exec command to list the contents of a folder and only output .tar files (using <a href="http://us3.php.net/substr" target="_blank">substr</a> to split the string)</p>
<p><code>$dir = exec("ls .",$output);<br />
foreach ($output as $file)<br />
{<br />
if (strtolower(substr($file, -4)) == '.tar')<br />
echo "$file\n";<br />
}</code></p>
<p>The <a href="http://php.net/shell_exec" target="_blank">shell_exec</a> function allows you to emulate a shell environment. For example, in Linux you have a choice of shells like sh, bash, and ksh that, allow you to do things such as while loops. Using shell_exec is about the same as using the backtick operator, which is generally how you&#8217;re run commands within a Perl script:</p>
<p><code> $output = shell_exec('ls nonexistentfile  2&gt;&amp;1 1&gt; /dev/null');</code></p>
<p>// Does the same as</p>
<p><code>$output = `ls nonexistent file 2&gt;&amp;1 1&gt; /dev/null`l</code></p>
<p>Finally, there&#8217;s the <a href="http://php.net/passthru" target="_blank">passthru</a> function which, when invoked, immediately displays raw ouput of the command being executed. This is intended for browsers, to display binary data such as images, and not necessarily something you&#8217;re use on the command line:</p>
<p><code>header('Content-Type: image/jpg');<br />
passthru('cat /home/user/public_html/images/image.png');<br />
</code></p>
<h3>A Word on Security</h3>
<p>A lot of hosts block command execution functions with the disable_functions setting in php.ini or by using safe mode, and for good reason. A lot of malicious scripts contain code with executable functions, and especially when the value of command or argument is passed as a variable, the results can be destructive. Here&#8217;s an example of a simple script that lists files, that accepts a folder name as a argument:</p>
<p><code>$folder = $argv[1];<br />
exec("ls $folder");</code></p>
<p>We&#8217;d have a security problem if someone passed this as the first argument for $folder:</p>
<p><code>myfolder &amp;&amp; cat /etc/shadow</code></p>
<p>To prevent this, PHP has built-in functions to escape shell arguments and commands, in order to prevent things that could be dangerous:</p>
<p><a href="http://us3.php.net/manual/en/function.escapeshellarg.php" target="_blank">escapeshellarg</a>: Encloses command arguments in single quotes so the argument is passed as one string:</p>
<p><code>exec('ls '.escapeshellarg($folder));</code></p>
<p><a href="http://us3.php.net/manual/en/function.escapeshellcmd.php" target="_blank">escapeshellcmd</a>: Escapes characters that can be used to trick a shell command (like the &amp;&amp; I used to execute cat)</p>
<h2>Process Management &amp; POSIX</h2>
<p>PHP has internal  functions that allow you to manage processes, such as proc_open, proc_close, etc. However, I admit that these tend to be difficult to learn an understand, while posix functions tend to do the job with less hassle.  <a href="http://theserverpages.com/php/manual/en/ref.posix.php" target="_blank">Posix</a> functions are basically system-level functions. In the below script, I&#8217;m going to change the user that the script runs as, view simple information about the process, then start a counter to 1 million but kill it when it reaches 50:</p>
<p><code>$user = posix_getpwnam($vnessa5);<br />
<strong>posix_setuid</strong>($user['uid']);<br />
<strong>posix_setgid</strong>($user['gid']);<br />
$pid = getmypid();</code></p>
<p><code>print_r(<strong>posix_times</strong>());<br />
echo "Script owner: ". <strong>get_current_user</strong>() . "(" . <strong>getmyuid</strong>() . ")\n";<br />
$i=0;<br />
while( $i &lt; 10000000 ){<br />
$i++;<br />
if($i == 50){<br />
echo "Reached 50 - killing!";<br />
<strong>posix_kill</strong>($pid,1);<br />
}<br />
}</code></p>
<p>Similarly, <a href="http://php.net/posix_getpid" target="_blank">posix_getpid</a> and <a href="http://php.net/getmypid" target="_blank">getmypid</a> do the same thing. If the script is a child of another process, you can get the parent process&#8217;s ID with <a href="http://php.net/posix_getppid" target="_blank">posix_getppid</a>. The <a href="http://www.php.net/manual/en/function.getrusage.php" target="_blank">getrusage</a> function can also be used to get more informative information than <a href="http://php.net/posix_times" target="_blank">posix_times</a>. To kill a process, you can see I used <a href="http://php.net/posix_kill" target="_blank">posix_kill</a>, with the process ID and exit code as arguments. This is what happened when I ran the script:</p>
<p><code>Array<br />
(<br />
[ticks] =&gt; 1279790432<br />
[utime] =&gt; 0<br />
[stime] =&gt; 0<br />
[cutime] =&gt; 0<br />
[cstime] =&gt; 0<br />
)<br />
Script owner: root(0)<br />
Reached 50 - killing!Hangup</code></p>
<p>Keep in mind that in most situations, using die() to bail out of a script is more appropriate that using kill. I could rewrite that part of the code to say this instead:</p>
<p><code>die("Reached 50 - Bailing out!);</code></p>
<p>I also found a nice post on running background processes, that you might want to check out <a href="http://nsaunders.wordpress.com/2007/01/12/running-a-background-process-in-php/" target="_blank">here</a>.</p>
<h2>Environmental Variables</h2>
<p>Environmental variables tend to be a major part of command line scripting, and is something that is part of PHP as well. Let&#8217;s start with defining an environmental variable with <a href="http://www.php.net/manual/en/function.putenv.php" target="_blank">putenv</a> and retrieving it with <a href="http://php.net/getenv" target="_blank">getenv</a>:</p>
<p><code>putenv("PATH=/fakebin");</code></p>
<p><code>if(!exec("test testdir")){<br />
echo "Could not execute test - path is " . getenv('PATH') ;<br />
}</code></p>
<p>In the above script, I set the $PATH environmental variable to /fakebin, so when I went to execute the &#8216;test&#8217; command (which is a valid Linux command located in /usr/bin/test), the scirpt could not find it since the command was not in /fakebin. This is about the same as setting the $PATH environment in a user&#8217;s .bashrc file. Keep in mind that the variable change lasts as long as the script does &#8211; after the script exits, the environmental variable is returned to its normal state. You can use getenv to pull any environmental variable, similar to the <a href="http://us.php.net/manual/en/reserved.variables.server.php" target="_blank">$_SERVER</a> superglobal.</p>
<p>A nice function for getting information about the current server is <a href="http://php.net/php_uname" target="_blank">php_uname</a>. You use it about the same way as the uname command in Linux:</p>
<p><code>echo php_uname();</code></p>
<p>Will return:</p>
<p><code>Linux server.v-nessa.net 2.6.18-028stab064.7 #1 SMP Wed Aug 26 13:11:07 MSD 2009 x86_64</code></p>
<p>You can further filter the output using the same arguments as uname, for instance, if I only need the server name:</p>
<p><code>echo php_uname(n);</code></p>
<p>PHP 5.3 also introduces a void function called <a href="http://php.net/gethostname" target="_blank">gethostname</a> which will get the hostname of your machine as well.</p>
<h3>The Server Superglobal</h3>
<p>The <a href="http://us.php.net/manual/en/reserved.variables.server.php" target="_blank">$_SERVER superglobal</a> is used to get environmental variables pursuant to the server and environment for the script you are running.  While it&#8217;s normally used in web applications, some of the values can be used for command line scripts as well:</p>
<p><code>echo "This file's name is " . $_SERVER['PHP_SELF'];</code></p>
<p>So you&#8217;ve made it part two of the series. Stay tuned for part three, which will go over specific system-level tasks and functions, with useful code snippets.</p>
<p>Next: <a href="http://www.v-nessa.net/2010/05/25/command-line-php-part-3" target="_blank">Command Line PHP: Part 3</a></p>
<p><map name='google_ad_map_315_7fa65e237551a74a'>
<area shape='rect' href='http://imageads.googleadservices.com/pagead/imgclick/315?pos=0' coords='1,2,367,28' />
<area shape='rect' href='http://services.google.com/feedback/abg' coords='384,10,453,23'/></map>
<img usemap='#google_ad_map_315_7fa65e237551a74a' border='0' src='http://imageads.googleadservices.com/pagead/ads?format=468x30_aff_img&amp;client=&amp;channel=&amp;output=png&amp;cuid=315&amp;url= http%3A%2F%2Fwww.v-nessa.net%2F2010%2F05%2F21%2Fcommand-line-php-part-2' /></p><img src="http://www.v-nessa.net/?ak_action=api_record_view&id=315&type=feed" alt="" />]]></content:encoded>
			<wfw:commentRss>http://www.v-nessa.net/2010/05/21/command-line-php-part-2/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Command Line PHP &#8211; Part 1</title>
		<link>http://www.v-nessa.net/2010/05/18/command-line-php-part-1</link>
		<comments>http://www.v-nessa.net/2010/05/18/command-line-php-part-1#comments</comments>
		<pubDate>Tue, 18 May 2010 18:10:26 +0000</pubDate>
		<dc:creator>Nessa</dc:creator>
				<category><![CDATA[uncategorized]]></category>
		<category><![CDATA[code]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[tutorials]]></category>

		<guid isPermaLink="false">http://www.v-nessa.net/?p=310</guid>
		<description><![CDATA[PHP isn&#8217;t just for websites anymore. In fact, almost every script I&#8217;ve written to perform server-side functions is either written in bash or PHP, rather than Perl or Python as preferred by my colleagues. It&#8217;s a common belief that PHP isn&#8217;t suited for CLI programming since it&#8217;s mainly used in web applications, but PHP has [...]]]></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%2Fwww.v-nessa.net%2F2010%2F05%2F18%2Fcommand-line-php-part-1"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fwww.v-nessa.net%2F2010%2F05%2F18%2Fcommand-line-php-part-1&amp;source=nessa421&amp;style=normal&amp;service=bit.ly&amp;b=2" height="61" width="50" /><br />
			</a>
		</div>
<p>PHP isn&#8217;t just for websites anymore. In fact, almost every script I&#8217;ve written to perform server-side functions is either written in bash or PHP, rather than Perl or Python as preferred by my colleagues. It&#8217;s a common belief that PHP isn&#8217;t suited for CLI programming since it&#8217;s mainly used in web applications, but PHP has over a hundred functions specifically intended for system management.</p>
<p>These kinds of posts can be rather lengthy, so I&#8217;m making this into a series with three parts.  Part 1 will go over the basic filesystem functions. You can find a complete listing <a href="http://us.php.net/manual/en/ref.filesystem.php" target="_blank">here</a>, but I&#8217;ll just go over a few of the more important and common ones.</p>
<p><span id="more-310"></span></p>
<h2><strong>The hashbang</strong></h2>
<p>As with any CLI script, the first line of your PHP script should contain the executable binary for PHP. You can usually find this by running:</p>
<blockquote><p>which php</p></blockquote>
<p>On my server the location is /usr/bin/php, so here&#8217;s the first line of my script:</p>
<p><code>#!/usr/bin/php</code></p>
<p>If you installed PHP in a custom location, you&#8217;ll need to specify that binary instead. You can also specify <a href="http://www.php-cli.com/" target="_blank">command line options</a> like -f, -c, etc.  Then set the permissions of your script to 755 to allow it to execute.</p>
<h2><strong>Accepting arguments with PHP<br />
</strong></h2>
<p>A major part of CLI scripting is the ability to accept arguments. For this, we&#8217;ll write a simple script called asl.php which will parse my name, sex, and location as arguments:</p>
<blockquote><p>[nessa@server] ./test.php 23 female virginia</p></blockquote>
<p>Here&#8217;s the script:</p>
<p><code>#!/usr/bin/php<br />
&lt;?php</code></p>
<p><code>print_r($argv);</code></p>
<p><code>?&gt;</code></p>
<p>The $argv variable is native, and parses as an array. So running this script will produce the following output:</p>
<p><code>Array<br />
(<br />
[0] =&gt; ./asl.php<br />
[1] =&gt; 23<br />
[2] =&gt; female<br />
[3] =&gt; virginia<br />
)</code></p>
<p>So if I only wanted to echo out my age, I can use the following code:</p>
<p><code>echo $argv[1];</code></p>
<p>If you notice, there are four values instead of the three that I passed. As with most scripting languages, PHP considers the filename as the first (0) variable. To remove the first variable, use the <a href="http://us.php.net/array_shift" target="_blank">array_shift</a> function:</p>
<p><code>array_shift($argv);</code></p>
<p>This means now that using value #1 as shown in the example above will output &#8220;female&#8221; instead of 23, making the command line order more correct, but this tends to be confusing for some people since it makes the first value 0 instead of 1. I usually prefer NOT to shift the array unless having the file name in there is going to adversely affect the intended functionality of the script.</p>
<p>From here ( keeping in mind that I&#8217;m not shifting the array anymore), I can assign the arguments to variables and access them from the script:</p>
<p><code>$age = $argv[1];</code><br />
<code>$gender = $argv[2];</code><br />
<code>$location = $argv[3];</code><br />
<code>// echo out the values</code><br />
<code>echo "Hello, I am $age-year-old $gender from $location";</code></p>
<p>In some cases you may want to validate the number of arguments passed, or what they contain. For instance, the below example is requiring that all three variables are passed (however, the code says four, since you have to include the script name as the first &#8220;argument&#8221;, as mentioned before):</p>
<p><code>if ($argc != 4) {<br />
die("Usage: asl.php &lt;age&gt; &lt;gender&gt; &lt;location&gt;\n");<br />
}</code></p>
<p>You can of course specify <em>less than</em> (&lt;) or <em>greater than</em> (&gt;) values operators.  In the next example, I want to make sure that the &#8220;age&#8221; argument is a number:</p>
<p><code>if (!is_numeric($age)){<br />
die("$age is not a number");<br />
}</code></p>
<p>I&#8217;m sure by now you get the idea =)</p>
<h2><strong>PHP File and Folder Management</strong></h2>
<h3>Creating files and folders, and checking their accessibility</h3>
<p>Continuing my above example, I want to end up with a file in /opt/app/users called &#8220;users.txt&#8221; that contains a list of all the output of asl.php. I first need to see if  /opt/app/users exists using the <a href="http://us3.php.net/manual/en/function.is-dir.php" target="_blank">is_dir </a>function, and if it doesn&#8217;t, create it with <a href="http://us3.php.net/manual/en/function.mkdir.php" target="_blank">mkdir</a>, then enter into that directory with <a href="http://us.php.net/manual/en/function.chdir.php" target="_blank">chdir</a>:</p>
<p><code>$dirname = "/opt/app/users;<br />
if(!<strong>is_dir</strong>($dirname)){<br />
<strong>mkdir</strong>($dirname, 0755);<br />
}<br />
<strong>chdir</strong>($dirname);</code></p>
<p>What if /opt/app doesn&#8217;t exist and I need to create the entire structure? The mkdir function has a recursive flag that is set to false by default, but can be enabled as so:</p>
<p><code>$dirstructure = "/opt/app/users";</code></p>
<p><code>if (!mkdir($dirstructure, <strong>0</strong>, true)) {<br />
die('Failed to create folders!');<br />
}</code></p>
<p>Now that the folders are created and verified, I use <a href="http://www.php.net/manual/en/function.file-exists.php" target="_blank">file_exists</a> and <a href="http://www.php.net/manual/en/function.is-readable.php" target="_blank">is_readable</a> to make sure that my users.txt file is there and can be seen. If not, we&#8217;ll use one of the file functions to create it:</p>
<p><code>$cwd = <strong>getcwd</strong>();<br />
$filename = $cwd . "/users.txt;<br />
if(<strong>file_exists</strong>($filename) &amp;&amp; <strong>is_readable</strong>($filename)){<br />
echo "File Exists and is readable";<br />
}else{<br />
<em>echo "File does not exist or is not readable";</em></code><br />
<code>touch($filename);<br />
}</code></p>
<p>If you notice, I added the <a href="http://us.php.net/manual/en/function.getcwd.php" target="_blank">getcwd</a> function to look for a file called users.txt in my current directory. If you need to see whether a file is executable instead of readable, you can simply use the <a href="http://us.php.net/manual/en/function.is-executable.php" target="_blank">is_executable</a> function, or to see if it&#8217;s writable, use <a href="http://us.php.net/manual/en/function.is-writable.php" target="_blank">is_writable</a>:</p>
<p><code>$filename = '/opt/app/users/users.txt';</code></p>
<p><code>if (!is_executable($filename)) {<br />
echo $filename.' is not executable';<br />
}<br />
</code><code>if (!is_writable($filename)) {<br />
echo $filename.' is not writable';<br />
} </code></p>
<p>Note that the result of these commands is based on the user running them. For instance, if the file is owned by the user root and is set to 600 permissions (root read/write only), but the user &#8216;user1&#8242; is running the script, the tests in the above lines of code will fail since that user does not have permissions to the file in question.</p>
<h3>Creating and deleting files</h3>
<p>There are a few functions you can use to create files with PHP. Here are the most commonly used: <a href="http://us2.php.net/manual/en/function.fopen.php" target="_blank">fopen</a>, <a href="http://www.php.net/manual/en/function.file-put-contents.php" target="_blank">file_put_contents</a>, <a href="http://us2.php.net/manual/en/function.touch.php" target="_blank">touch,</a> If you want to delete a file, simply use <a href="http://us2.php.net/unlink" target="_blank">unlink</a>.  In the below example</p>
<p><code>$filename = "/opt/app/users/users.txt";<br />
unlink($filename);<br />
</code></p>
<p>Unlink is not to be confused with the opposite of <a href="http://us2.php.net/manual/en/function.symlink.php" target="_blank">symlink</a>, which creates a symbolic link  (shortbut) between files:</p>
<p><code>symlimk("/opt/app/users/users.txt", "/home/nessa/Desktop/users.txt-shortcut");</code></p>
<p>And <a href="http://php.net/rmdir" target="_blank">rmdir</a> will remove a folder:</p>
<p><code>if (!is_dir('temp')) {<br />
mkdir('temp');<br />
}<br />
rmdir('temp');</code></p>
<h3>Writing to files</h3>
<p>The most common way to write to files is using the fopen function. Using my original example, asl.php is going to write the values of the arguments to a file called users.txt:</p>
<p><code>$filename = "/opt/app/users/users.txt";<br />
$fh = fopen($filename, 'w') or die("can't open file");<br />
$data = $age . $gender . $location;<br />
fwrite($fh, $date);<br />
fclose($fh);</code></p>
<h3>Reading contents of a file</h3>
<p>If you want the script to read the file, you can use a number of function such as <a href="http://us3.php.net/manual/en/function.readfile.php" target="_blank">readfile</a>, <a href="http://us3.php.net/manual/en/function.file-get-contents.php" target="_blank">file_get_contents</a>, <a href="http://us3.php.net/manual/en/function.fopen.php" target="_blank">fopen</a>, <a href="http://us3.php.net/manual/en/function.fread.php" target="_blank">fread</a>, and <a href="http://us3.php.net/manual/en/function.file.php" target="_blank">file</a>. The actual function you would use depends on what you&#8217;re planning on doing with the data. If you simply want to display the contents of the file as a string:</p>
<p><code>$filename = "/opt/app/users/users.txt";<br />
$data = file_get_contents($filename);<br />
echo $data;</code></p>
<p>Will display:</p>
<p><code>23 female virginia</code></p>
<p>If you need a more programmatic way of displaying the data, such as reading each column as a set of values (like if you&#8217;re inserting all this into a database), you&#8217;d use the file() function which will load the contents of the file into an array. Here&#8217;s a simple loop that echoes out each line in the file:</p>
<p><code>$filename = "/opt/app/users/users.txt";<br />
$lines = file($filename);</code></p>
<p><code>foreach ($lines as $line_num =&gt; $line)</code><br />
<code>{<br />
print "{$line_num} : " . $line . "\n";<br />
}</code></p>
<h3>Reading contents of a folder</h3>
<p>You can use the <a href="http://us3.php.net/opendir" target="_blank">opendir</a> function to run a loop and read the contents of a folder:</p>
<p><code>// open the current directory by opendir</code></p>
<p><code>$dirname = "/opt/app";<br />
$handle=opendir($dirname);</code></p>
<p><code>while (($file = readdir($handle))!==false) {<br />
echo "$file \n";<br />
}</code></p>
<p><code>closedir($handle);</code></p>
<h3>Changing permissions and ownership:</h3>
<p>In the above example where I was checking to see if the file was readable, I didn&#8217;t actually specify anything to address permissions &#8211; instead, I just created the file. To change the permissions or ownership of files, you can use the <a href="http://us2.php.net/chmod" target="_blank">chmod</a> and <a href="http://us2.php.net/chown" target="_blank">chown</a> functions.</p>
<p><code>$filename = "/opt/appf/users/users.txt";<br />
$username = posix_getpwuid(fileowner($filename));</code></p>
<p><code>// Get the octal value of permissions<br />
$perms = substr(sprintf('%o', fileperms($filename')), -4);</code></p>
<p><code>if($username[name] != "nessa" &amp;&amp; $perms != "0755" ){<br />
chmod($filename, 0755);<br />
chown($filename, "nessa");<br />
echo "Permissions fixed";<br />
}else{<br />
echo "Permissions are correct";</code></p>
<p>If you want to change the umask (that is, the default permissions of files created by the script), you can use the <a href="http://us.php.net/manual/en/function.umask.php" target="_blank">umask</a> function &#8211; which actually revokes permissions instead of setting them.</p>
<h3>Copying, moving, and renaming</h3>
<p>Say I want to rename the /opt/app folder to /etc/app. I&#8217;d use the <a href="http://us.php.net/manual/en/function.rename.php" target="_blank">rename</a> function as so, validating on whether of not it was renamed successfully:</p>
<p><code>if(!rename("/opt/app","/etc/app")){<br />
echo "Rename failed";<br />
}</code></p>
<p>You can also use the <a href="http://us.php.net/manual/en/function.copy.php" target="_blank">copy</a> function to copy files, noting that if the &#8220;new&#8221; file or folder already exists, it will be overwritten.</p>
<p><code>if(!copy("/opt/app","/etc/app")){<br />
echo "Copy failed";<br />
}</code></p>
<h2>User and File information</h2>
<h3>Getting user and group data</h3>
<p>The <a href="http://us3.php.net/fileowner" target="_blank">fileowner</a> function as shown above will return the UID of the file, but I specified the username. You can use <a href="http://us3.php.net/manual/en/function.posix-getpwuid.php" target="_blank">posix_getpwuid</a> to return an array with the user&#8217;s information in a more usable format:</p>
<div>
<p><code>$filename = "/opt/app/users/users.txt";</code><code><br />
$username = posix_getpwuid(fileowner($filename));<code>print_r($username);</code></code></p>
</div>
<div>Will return:</div>
<p><code>Array<br />
(<br />
[name] =&gt; nessa<br />
[passwd] =&gt; x<br />
[uid] =&gt; 1000<br />
[gid] =&gt; 1000<br />
[gecos] =&gt; Vanessa V.,,,<br />
[dir] =&gt; /home/nessa<br />
[shell] =&gt; /bin/bash<br />
)</code></p>
<p>So you can simply echo out the array values of $username based on the keys. For example, to get the shell of the user in the above example, simply echo to the &#8216;shell&#8217; key from the $username array:</p>
<p><code>echo $username[shell];</code></p>
<p>If you want to get group information for a file, you can use the same method, but with <a href="http://us.php.net/manual/en/function.filegroup.php" target="_blank">filegroup</a> and <a href="http://us.php.net/manual/en/function.posix-getgrgid.php" target="_blank">posix_getgrgid</a>:</p>
<p><code>$filename = "/opt/app/users/users.txt";</code><br />
<code>print_r(posix_getgrgid(filegroup($filename)));</code></p>
<h3>Getting file information</h3>
<p>You can also get information about a file using the <a href="http://us.php.net/manual/en/function.stat.php" target="_blank">stat</a> or <a href="http://us.php.net/manual/en/function.fstat.php" target="_blank">fstat</a> functions, which return the results to an array:</p>
<p><code>$filename = "/opt/app/users/users.txt";</code><br />
<code>$stat = stat($filename);</code><br />
<code>print_r($stat);</code></p>
<p>Will return a giant array of information for the file. If you only want to return one value, say, the size, echo it out like you would a normal array:</p>
<p><code>echo $stat[size];</code></p>
<p>So here we&#8217;ve finished the first part of PHP command line scripting, which covered the use of files, folder, and users. The next parts will go over command execution and process management.</p>
<p>See: <a href="http://www.v-nessa.net/2010/05/21/command-line-php-part-2" target="_self">Command Line PHP: Part 2,</a> <a href="http://www.v-nessa.net/2010/05/25/command-line-php-part-3" target="_blank">Command Line PHP: Part 3<br />
</a></p>
<p><map name='google_ad_map_310_7fa65e237551a74a'>
<area shape='rect' href='http://imageads.googleadservices.com/pagead/imgclick/310?pos=0' coords='1,2,367,28' />
<area shape='rect' href='http://services.google.com/feedback/abg' coords='384,10,453,23'/></map>
<img usemap='#google_ad_map_310_7fa65e237551a74a' border='0' src='http://imageads.googleadservices.com/pagead/ads?format=468x30_aff_img&amp;client=&amp;channel=&amp;output=png&amp;cuid=310&amp;url= http%3A%2F%2Fwww.v-nessa.net%2F2010%2F05%2F18%2Fcommand-line-php-part-1' /></p><img src="http://www.v-nessa.net/?ak_action=api_record_view&id=310&type=feed" alt="" />]]></content:encoded>
			<wfw:commentRss>http://www.v-nessa.net/2010/05/18/command-line-php-part-1/feed</wfw:commentRss>
		<slash:comments>13</slash:comments>
		</item>
		<item>
		<title>8 Steps to Starting a Free Online Service</title>
		<link>http://www.v-nessa.net/2010/03/28/8-steps-to-starting-a-free-online-service</link>
		<comments>http://www.v-nessa.net/2010/03/28/8-steps-to-starting-a-free-online-service#comments</comments>
		<pubDate>Sun, 28 Mar 2010 21:42:12 +0000</pubDate>
		<dc:creator>Nessa</dc:creator>
				<category><![CDATA[uncategorized]]></category>
		<category><![CDATA[internet]]></category>
		<category><![CDATA[site design]]></category>
		<category><![CDATA[tutorials]]></category>

		<guid isPermaLink="false">http://www.v-nessa.net/?p=288</guid>
		<description><![CDATA[Working in the web hosting industry, I come across a lot of interesting sites and not surprisingly, I&#8217;ve found that a good number of new site owners have at least one of two goals in mind &#8211; to become well-known on the Internet, or to make money&#8230;sometimes even both.  It&#8217;s also not surprising to find [...]]]></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%2Fwww.v-nessa.net%2F2010%2F03%2F28%2F8-steps-to-starting-a-free-online-service"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fwww.v-nessa.net%2F2010%2F03%2F28%2F8-steps-to-starting-a-free-online-service&amp;source=nessa421&amp;style=normal&amp;service=bit.ly&amp;b=2" height="61" width="50" /><br />
			</a>
		</div>
<p>Working in the web hosting industry, I come across a lot of interesting sites and not surprisingly, I&#8217;ve found that a good number of new site owners have at least one of two goals in mind &#8211; to become well-known on the Internet, or to make money&#8230;sometimes even both.  It&#8217;s also not surprising to find out that less than an eighth of the people that have these goals will never meet them.</p>
<p>One of the more common trends I&#8217;ve noticed is the creation of free services.  No individual wants to pay for using things on the Internet nowadays, and anyone who has a choice between a paid and a free service will consider the free choice first.  Offering a free service also may mean big bucks for you in the long run, so if you were thinking about enhancing your presence on the Internet by offering a service, here are some tips to help get you started.</p>
<p><strong>1) Come up with a solution</strong></p>
<p>People turn to using services because they provide some kind of value that can help or solve a real-life issue. For instance, Mint.com offers free financial planning services. Facebook and MySpace offer social networking to help you keep in touch with other people. These services were unique to their time, which is why they are so popular &#8211; and now millions of people use them.  The first thing you should think about when starting any new service is what you can offer for people that may have a dilemma or need for efficiency. Stuck?  Carry a mini notebook around and jot down things that you do on a daily basis, then look back and think: Is there something on this list that would be easier to do or track if there was a something out there to help me out?  Also, don&#8217;t waste your time trying to clone free services that already exist unless you&#8217;re prepared to offer something that they don&#8217;t.  Instead, focus on coming up with something unique.</p>
<p><strong>2) See what&#8217;s already out there</strong></p>
<p>When I was in technical support, I would come across <em>at least</em> two customers every week that appeared to be starting some kind of social networking site, and some even admitted that they&#8217;re trying to launch the next MySpace.  Let&#8217;s get a reality check here &#8211; most of the popular social networking sites out there have been around for years and by now have millions of users, and are endorsed by multi-billion dollar companies.  You&#8217;re not going to have the next eBay or Youtube, so don&#8217;t waste your time trying.   When there are already hundreds of services offering the one that you&#8217;re trying to launch, you really need to know what you&#8217;re doing if you plan on being successful at reaching your target audience.  Your best bet at success is offering something that no one else does.</p>
<p>Instead, again, focus on bringing something new to the table or improving a service that isn&#8217;t as readily available.  One of the best ways to get attention for a free service is basing it off a paid one that is at least moderately successful.  The simple concept of something being free will entice your targeted audience to at least try it.</p>
<p><strong>3) Figure out how you&#8217;re going to do it</strong></p>
<p>Listen here, dreamer &#8211; if you want people to use your service, you have to do <span style="text-decoration: line-through;">some</span> a lot of technical planning.  Depending on what kind of service you&#8217;re starting, you may end up needing a design and custom content management software for your website, neither of which comes easy or cheap.  If you&#8217;re tech-savvy, expect to spend at least 10 hours a week for several months on development alone. If you&#8217;re not a technical person when it comes to programming and site design, well, let&#8217;s hope you have quite a bit of money saved up.</p>
<p>But &#8211; don&#8217;t just start throwing a bunch of junk together. You need to site down with a pencil and paper and plan out all the major aspects of your website before you get started.  This tends to be the most time-consuming part of the entire process if you&#8217;re doing this all yourself, because you have to think about how everything is going to tie together as far as programming, layout, and security.  Then there&#8217;s the actual doing of all this, which takes even more time.  Be aware of exactly what you&#8217;re needing and how long it&#8217;s actually going to take. Once you have a plan, start on it as soon as possible.  It helps to make an outline of what needs to get done, and then set deadlines for those items.</p>
<p><strong>4) Think about maintenance</strong></p>
<p>Running a service doesn&#8217;t end at its launch, that is, if you want your users to continue using it.  You need to think about how you&#8217;re going to support and maintain your service &#8211; your users may try to contact you every so often if they need help, or the site itself may eventually need maintenance and updates performed.  If you don&#8217;t think you&#8217;re going to be able to maintain the site yourself, see if you have any friends that will be willing to help out. Depending on how successful your service ends up, you may eventually need to hire staff members to help you maintain the site.</p>
<p><strong>5) Make it free for them, but profitable to you</strong></p>
<p>You&#8217;ll want to make all this worth your time, otherwise you&#8217;ll probably end up giving up.  Free services are almost always supported by paid ads, which offer a per-click or per-sale incentive for you.  Always consider putting ads or endorsements on the site that will bring in money, but make sure they are relevant to what your service is offering and they don&#8217;t affect the usability of the site.  Search places like Commission Junction for affiliate programs or other services that you think your users will find helpful. Either way, find ways to make your site profitable, whether it be supported by ads, or giving the option for users to upgrade to a paid service that offers a few more features.</p>
<p><strong>6) Cover your ass</strong></p>
<p>Believe it or not, people can pretty much be sued for anything nowadays, regardless of how stupid it is.  I&#8217;m not saying that you need to hire a lawyer, but you need to make sure your bases are covered when it comes to dealing with people that are either just out for money, or want to take things to the extreme by holding you accountable for their problems. Anytime you offer a service, you&#8217;re going to have people who are not satisfied.  Therefore, you&#8217;ll want to draft a Terms of Use and/or legal document on your site specifically stating that you&#8217;re not responsible for what your users do, or how your service works.  Basically, don&#8217;t offer any kind of guarantee, and let your users know that they are using your service at their own rish.  The exception is in cases where personal information is stolen, as if you obtain and store such information on your site you are responsible for its security.  That also brings up the point that you should avoid obtaining personal information for your members that isn&#8217;t necessary for then to use your site.  If you do have to obtain such information, take a few extra steps to secure it and cover yourself against liability by encrptying information and getting PCI certified by a trusted provider.</p>
<p><strong>7) Make it known</strong></p>
<p>You need to get the word out about what you&#8217;re trying to do, and set it up far enough in advance to where people are actually looking forward &#8211; and waiting anxiously &#8211; to using your service. This means using Twitter, Facebook, and other social media networks to tell everyone about the site, and reach out to other blog owners that may be interested in posting about it.  You&#8217;ll want to start letting people know about it at least 2-4 weeks before your expected launch date.  Your site should have a visually-friendly page up indicating what services and features you will offer, when they will be available, and that it&#8217;s free.  It may also be worth setting up a mailing list that people can opt into so they are notified of updates, and purchasing ad space on more popular sites, which can eventually pay off if your service is a success.</p>
<p><strong>8) Stick with it</strong></p>
<p>One of the hardest parts of starting anything is sticking with it. In this case, you may be looking at a project lasting six months to well over a year.  If you think about giving up, motivate yourself by thinking about how much money you&#8217;re going to make, or how you&#8217;re going to be helping people.  If you find yourself in a bind, consider getting help or making your goals a little more realistic.</p>
<p><map name='google_ad_map_288_7fa65e237551a74a'>
<area shape='rect' href='http://imageads.googleadservices.com/pagead/imgclick/288?pos=0' coords='1,2,367,28' />
<area shape='rect' href='http://services.google.com/feedback/abg' coords='384,10,453,23'/></map>
<img usemap='#google_ad_map_288_7fa65e237551a74a' border='0' src='http://imageads.googleadservices.com/pagead/ads?format=468x30_aff_img&amp;client=&amp;channel=&amp;output=png&amp;cuid=288&amp;url= http%3A%2F%2Fwww.v-nessa.net%2F2010%2F03%2F28%2F8-steps-to-starting-a-free-online-service' /></p><img src="http://www.v-nessa.net/?ak_action=api_record_view&id=288&type=feed" alt="" />]]></content:encoded>
			<wfw:commentRss>http://www.v-nessa.net/2010/03/28/8-steps-to-starting-a-free-online-service/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Simple API Writing, Part I</title>
		<link>http://www.v-nessa.net/2009/02/09/simple-api-writing-part-i</link>
		<comments>http://www.v-nessa.net/2009/02/09/simple-api-writing-part-i#comments</comments>
		<pubDate>Tue, 10 Feb 2009 02:55:05 +0000</pubDate>
		<dc:creator>Nessa</dc:creator>
				<category><![CDATA[uncategorized]]></category>
		<category><![CDATA[cpanel]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[tutorials]]></category>

		<guid isPermaLink="false">http://www.v-nessa.net/?p=189</guid>
		<description><![CDATA[A lot of people don&#8217;t realize how easy it is to write an API with PHP. It really is as easy as having a simple PHP script accepting GET variables, and when you add in some security, you can pretty much do anything you want with a single script that accepts variables from any authenticated [...]]]></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%2Fwww.v-nessa.net%2F2009%2F02%2F09%2Fsimple-api-writing-part-i"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fwww.v-nessa.net%2F2009%2F02%2F09%2Fsimple-api-writing-part-i&amp;source=nessa421&amp;style=normal&amp;service=bit.ly&amp;b=2" height="61" width="50" /><br />
			</a>
		</div>
<p>A lot of people don&#8217;t realize how easy it is to write an API with PHP. It really is as easy as having a simple PHP script accepting GET variables, and when you add in some security, you can pretty much do anything you want with a single script that accepts variables from any authenticated source.  So a little while ago I <a href="http://www.v-nessa.net/2008/05/07/sexifying-whm-with-xml-api" target="_blank">posted about the new cPanel XML API</a> and how to integrate that with your own scripts &#8211; well now, I&#8217;ll use that as an example to show you how to write an API for <em>their</em> API, a.k.a, an API connector.   Though in real applications you wouldn&#8217;t need an API, all you&#8217;d need is a PHP script that accepts GET or POST input to perform some kind of action. In this example, we&#8217;ll have a script that automatically adds DNS zones to a nameserver that runs cPanel as well.</p>
<p>Most APIs do the same thing &#8211; you have a script, then that script accepts post/get variables, then does something.</p>
<p>The Interface (addzone.php):</p>
<p>You guy remember the one I posted a while back &#8211; well, we&#8217;ll use the same one only a tad different.  This is the script that runs statically on the server, which accepts the variables passed through the URL:</p>
<p><code><br />
<span style="color: #ff66cc;"></span></code><span style="color: #ff66cc;">&lt;?php<br />
// API for adding a DNS zone to ns cluster<br />
$isinclude = &#8220;1&#8243;; // specifies $isinclude for xmlapi.php<br />
// GET &amp; POST definitions</span></p>
<p><span style="color: #ff66cc;">$key = &#8220;098f6bcd4621d373cade4e832627b4f6&#8243;;<br />
$domain = $_GET['domain'];<br />
$ip = $_GET['ip'];</span></p>
<p><span style="color: #ff66cc;">// Validation &#8211; make sure that we have the right information</span></p>
<p><span style="color: #ff66cc;">if($_POST['key'] != $key){ echo &#8220;Invalid key!!&#8221;; die(); }<br />
if(empty($domain)){ echo &#8220;Domain value missing!!&#8221;; die(); }<br />
if(empty($ip)){ echo &#8220;IP Value missing!!&#8221;; die(); }</span></p>
<p><span style="color: #ff66cc;">$theServer = &#8220;ns1.v-nessa.net&#8221;; // the server to connect to<br />
$apiPath = &#8220;/xml-api/adddns?domain=$domain&amp;ip=$ip&#8221;; // the xml api path<br />
</span></p>
<p><span style="color: #ff66cc;">$user = &#8220;root&#8221;; // use to connect to whm as<br />
</span></p>
<p><span style="color: #ff66cc;">// ns1 hash (whm &gt; remote access)<br />
</span></p>
<p><span style="color: #ff66cc;">$rhash = &#8220;</span><span style="color: #ff66cc;">e9917f16b3fda69137192725a06b68e7</span><br />
<span style="color: #ff66cc;"> 230e99fd445473807e33d637878641a5<br />
&#8211;edited out for sake of length&#8211;<br />
f673567ab443acedc77f9aec62ff953f&#8221;;</span></p>
<p><span style="color: #ff66cc;">// Include the API connector<br />
include(&#8220;xmlapi.php&#8221;);</span></p>
<p><span style="color: #ff66cc;">// Output XML Result<br />
$xmlObject=simplexml_load_string($xmlresult);</span></p>
<p><span style="color: #ff66cc;">echo $xmlObject-&gt;result-&gt;statusmsg . &#8220;\n&#8221;;</span></p>
<p><span style="color: #ff66cc;">?&gt;</span></p>
<p>The file that is called via include() is the basic xml function file which constructs all of the variables from the outser script (shown above).  You can get a copy of of xmlapi.php from <a href="http://v-nessa.net/scripts/whmapi/xmlapi" target="_blank">here</a>, but for this example you need to comment out the output.</p>
<p>Now all we need to do is pass the variables that the script needs in order to know what information to process, which is $ip and $domain.  Therefore, in order to successfully call this API, you would enter the following in a browser:</p>
<blockquote><p>http://v-nessa.net/api/addzone.php?domain=test.v-nessa.net&amp;ip=205.134.252.71</p></blockquote>
<p>This will pass the &#8216;domain&#8217; and &#8216;ip&#8217; variables to addzone.php, which uses the XML API to connect to WHM and add a dns zone on the nameserver ns1.v-nessa.net.  This is a problem though &#8211; what&#8217;s to keep outsiders from finding this and abusing it?  Well, there are several forms of non-interactive authentication you can use, such as:</p>
<ul>
<li>Have an allow list of ips that can access the script (look up environmental variables at php.net)</li>
<li>Requiring a key or token</li>
</ul>
<p>I generally use a key, though there are better ways to do this.  The way I&#8217;m about to show you is simple and secure, but slightly limits the way your API can be called.</p>
<p>First, I generated an md5 hash and defined it in the scipt (remember <span style="color: #ff66cc;">$key = &#8220;098f6bcd4621d373cade4e832627b4f6&#8243;; <span style="color: #000000;">?).  Then all I need to do is make sure that key is used whenever I call the API. Notice that in addzone.php it&#8217;s defined as a POST variable?  That is mainly for preference but you can just as easily make it a GET variable and just add it to your URL line.  Here I want it to be posted, so I can call the API through cURL as follows:</span></span></p>
<blockquote><p>curl -k http://v-nessa.net/api/addzone.php?domain=test.v-nessa.net&amp;ip=205.134.252.71 -d <span style="color: #ff66cc;">key = &#8220;098f6bcd4621d373cade4e832627b4f6</span></p></blockquote>
<p><span style="color: #ff66cc;"><span style="color: #000000;">And there you have it! A very simple way to write an API using POST and GET.</span><br />
</span></p>
<p><span style="color: #ff66cc;"><br />
</span></p>
<p><!--adsense--></p>
<p><map name='google_ad_map_189_7fa65e237551a74a'>
<area shape='rect' href='http://imageads.googleadservices.com/pagead/imgclick/189?pos=0' coords='1,2,367,28' />
<area shape='rect' href='http://services.google.com/feedback/abg' coords='384,10,453,23'/></map>
<img usemap='#google_ad_map_189_7fa65e237551a74a' border='0' src='http://imageads.googleadservices.com/pagead/ads?format=468x30_aff_img&amp;client=&amp;channel=&amp;output=png&amp;cuid=189&amp;url= http%3A%2F%2Fwww.v-nessa.net%2F2009%2F02%2F09%2Fsimple-api-writing-part-i' /></p><img src="http://www.v-nessa.net/?ak_action=api_record_view&id=189&type=feed" alt="" />]]></content:encoded>
			<wfw:commentRss>http://www.v-nessa.net/2009/02/09/simple-api-writing-part-i/feed</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>How to Add Services to Chkservd</title>
		<link>http://www.v-nessa.net/2008/06/28/how-to-add-services-to-chkservd</link>
		<comments>http://www.v-nessa.net/2008/06/28/how-to-add-services-to-chkservd#comments</comments>
		<pubDate>Sun, 29 Jun 2008 01:45:00 +0000</pubDate>
		<dc:creator>Nessa</dc:creator>
				<category><![CDATA[uncategorized]]></category>
		<category><![CDATA[cpanel]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[tutorials]]></category>

		<guid isPermaLink="false">http://www.v-nessa.net/2008/02/01/how-to-add-services-to-chkservd</guid>
		<description><![CDATA[.!. .!. Chkservd is the service in cPanel that checks to make sure that services are running, then restarts them if necessary. It&#8217;s also responsible for the &#8216;Service Manager&#8217; section in cPanel, which is an interface where added services can be easily checked on and off. To add a new service, create a line in [...]]]></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%2Fwww.v-nessa.net%2F2008%2F06%2F28%2Fhow-to-add-services-to-chkservd"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fwww.v-nessa.net%2F2008%2F06%2F28%2Fhow-to-add-services-to-chkservd&amp;source=nessa421&amp;style=normal&amp;service=bit.ly&amp;b=2" height="61" width="50" /><br />
			</a>
		</div>
<div style="display:none">.!.</div>
<div style="display:none">.!.</div>
<p>Chkservd is the service in cPanel that checks to make sure that services are running, then restarts them if necessary. It&#8217;s also responsible for the &#8216;Service Manager&#8217; section in cPanel, which is an interface where added services can be easily checked on and off.<br />
To add a new service, create a line in <strong>/etc/chkserv.d/chkservd.conf</strong> in the same format as the others:</p>
<blockquote><p>service:1</p>
</blockquote>
<p>1 means the service should be enabled, 0 means it&#8217;s off.<br />
In <strong>/etc/chkserv.d</strong> each service has its own file. Create a file called as the name of the service you are monitoring. The contents of the file are in the format of:</p>
<blockquote>
<pre>#SERVICE = PORT, SEND, RESPONSE, RE-START COMMAND</pre>
</blockquote>
<p><p> There are two ways that cPanel checks services with chkservd:</p>
<ul>
<li>Connection-based monitoring &#8211; By default, cPanel will try to connect to the service&#8217;s specified port, issue a command, and if a response is received within 10 seconds it will consider the service to be online. For instance, FTP:</li>
</ul>
<blockquote>
<pre>service[ftpd]=21,QUIT,220,/scripts/restartsrv_ftpserver</pre>
</blockquote>
<ul>
<li>Process-based monitoring &#8211; cPanel will check for a specific process to determine whether it is online. For instance, named:</li>
</ul>
<blockquote>
<pre>service[named]=x,x,x,/scripts/restartsrvr_bind,named,named|bind</pre>
</blockquote>
<p>If you have more than one restart command, you can separate them with semicolons in order of preference that they should be run. Output of these commands will be logged to the chkservd.log<br />
After you&#8217;ve created the service&#8217;s configuration file, restart chkservd:</p>
<blockquote>
<pre>/etc/init.d/chkservd restart</pre>
</blockquote>
<p>You should then see the service listed in WebHost Manager in the &#8216;service manager section&#8217;<br />
Chkservd logs are in /var/log/chkservd.log. Checks are done every 8 minutes, and everyone online service gets a +, offline services get a -. If the service is determined to be offline, the restart command(s) specified in that service&#8217;s chkservd configuration file is issued and the output is logged.</p>
<p>If you don&#8217;t even have chkservd installed, it&#8217;s probably missing and you need to <a title="Install MIssing Chkservd" href="http://www.ducea.com/2006/06/12/chkservd-missing-on-cpanel-installed-on-centos/" target="_blank">install it</a>.</p>
<p><map name='google_ad_map_143_7fa65e237551a74a'>
<area shape='rect' href='http://imageads.googleadservices.com/pagead/imgclick/143?pos=0' coords='1,2,367,28' />
<area shape='rect' href='http://services.google.com/feedback/abg' coords='384,10,453,23'/></map>
<img usemap='#google_ad_map_143_7fa65e237551a74a' border='0' src='http://imageads.googleadservices.com/pagead/ads?format=468x30_aff_img&amp;client=&amp;channel=&amp;output=png&amp;cuid=143&amp;url= http%3A%2F%2Fwww.v-nessa.net%2F2008%2F06%2F28%2Fhow-to-add-services-to-chkservd' /></p><img src="http://www.v-nessa.net/?ak_action=api_record_view&id=143&type=feed" alt="" />]]></content:encoded>
			<wfw:commentRss>http://www.v-nessa.net/2008/06/28/how-to-add-services-to-chkservd/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Alternative PHP Caching FTW</title>
		<link>http://www.v-nessa.net/2008/06/27/alternative-php-caching-ftw</link>
		<comments>http://www.v-nessa.net/2008/06/27/alternative-php-caching-ftw#comments</comments>
		<pubDate>Fri, 27 Jun 2008 12:24:47 +0000</pubDate>
		<dc:creator>Nessa</dc:creator>
				<category><![CDATA[uncategorized]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[tutorials]]></category>

		<guid isPermaLink="false">http://www.v-nessa.net/2008/03/27/alternative-php-caching-ftw</guid>
		<description><![CDATA[.!. We get a TON of requests for the PHP APC pecl module because after having adopted suPHP into our configuration, eAccelerator is worthless. It&#8217;s quick to install, and especially if you&#8217;re running suPHP or phpsuexec, each user can maintain their own settings within their local php.ini without me having to do anything &#8212; basically [...]]]></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%2Fwww.v-nessa.net%2F2008%2F06%2F27%2Falternative-php-caching-ftw"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fwww.v-nessa.net%2F2008%2F06%2F27%2Falternative-php-caching-ftw&amp;source=nessa421&amp;style=normal&amp;service=bit.ly&amp;b=2" height="61" width="50" /><br />
			</a>
		</div>
<div style="display:none">.!.</div>
<p>We get a TON of requests for the <a href="http://us3.php.net/apc" target="_blank">PHP APC</a> pecl module because after having adopted suPHP into our configuration, eAccelerator is worthless.  It&#8217;s quick to install, and especially if you&#8217;re running suPHP or phpsuexec, each user can maintain their own settings within their local php.ini without me having to do anything &#8212; basically the best thing that a lazy system admin can ask for.</p>
<p>Soooo, here&#8217;s how you install it:</p>
<p><code><br />
<span style="color: #ff66cc;"> wget http://pecl.php.net/get/APC-3.0.17.tgz<br />
tar -xvzf  APC-3.0.17.tgz<br /> <strong style="display:none"></strong><br />
phpize<br />
./configure &amp;&amp; make &amp;&amp; make install</span><br />
</code></p>
<p>Then just add &#8220;extension=/apc.so&#8221; to your php.ini and you&#8217;re done.  With PHP under Apache this will load the APC module for everyone, but for suPHP users you&#8217;ll need to add it to their php.ini which will also allow them to <a href="http://us3.php.net/apc" target="_blank">modify their own APC settings</a>. These are the ones I recommend using:</p>
<pre><span style="color: #ff66cc;">apc.enabled = 1</span></pre>
<pre><span style="color: #ff66cc;">apc.shm_segments = 1</span></pre>
<pre><span style="color: #ff66cc;">apc.shm_size = 30</span></pre>
<pre><span style="color: #ff66cc;">apc.optimization = 0</span></pre>
<pre><span style="color: #ff66cc;">apc.ttl = 7200</span></pre>
<pre><span style="color: #ff66cc;">apc.user_ttl = 7200</span></pre>
<pre><span style="color: #ff66cc;">apc.num_files_hint = 1000</span></pre>
<pre><span style="color: #ff66cc;">apc.mmap_file_mask = /tmp/apc.XXXXXX</span></pre>
<p>Now, if you want to get even sexier with it I came across <a href="http://www0.fh-trier.de/~beckerr/apcphpgui.phtml" target="_blank">this little tool</a> that monitors the performance of APC on your server.</p>
<p><!--adsense--></p>
<p><map name='google_ad_map_149_7fa65e237551a74a'>
<area shape='rect' href='http://imageads.googleadservices.com/pagead/imgclick/149?pos=0' coords='1,2,367,28' />
<area shape='rect' href='http://services.google.com/feedback/abg' coords='384,10,453,23'/></map>
<img usemap='#google_ad_map_149_7fa65e237551a74a' border='0' src='http://imageads.googleadservices.com/pagead/ads?format=468x30_aff_img&amp;client=&amp;channel=&amp;output=png&amp;cuid=149&amp;url= http%3A%2F%2Fwww.v-nessa.net%2F2008%2F06%2F27%2Falternative-php-caching-ftw' /></p><img src="http://www.v-nessa.net/?ak_action=api_record_view&id=149&type=feed" alt="" />]]></content:encoded>
			<wfw:commentRss>http://www.v-nessa.net/2008/06/27/alternative-php-caching-ftw/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Dual Monitor Setup in Ubuntu 7.10, ATI Radeon</title>
		<link>http://www.v-nessa.net/2008/06/12/dual-monitor-setup-in-ubuntu-710-ati-radeon</link>
		<comments>http://www.v-nessa.net/2008/06/12/dual-monitor-setup-in-ubuntu-710-ati-radeon#comments</comments>
		<pubDate>Fri, 13 Jun 2008 04:50:50 +0000</pubDate>
		<dc:creator>Nessa</dc:creator>
				<category><![CDATA[uncategorized]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[tutorials]]></category>
		<category><![CDATA[ubuntu]]></category>

		<guid isPermaLink="false">http://www.v-nessa.net/?p=158</guid>
		<description><![CDATA[The company just bought our department brand hooked up PC&#8217;s that include ATI Radeon dual output graphics cards with massive monitors.  This is probably the only time I&#8217;d willingly admit that Windows came out ahead, as I spent a good 2 days trying to get my dual monitors to work with Ubuntu.  I finally got [...]]]></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%2Fwww.v-nessa.net%2F2008%2F06%2F12%2Fdual-monitor-setup-in-ubuntu-710-ati-radeon"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fwww.v-nessa.net%2F2008%2F06%2F12%2Fdual-monitor-setup-in-ubuntu-710-ati-radeon&amp;source=nessa421&amp;style=normal&amp;service=bit.ly&amp;b=2" height="61" width="50" /><br />
			</a>
		</div>
<p>The company just bought our department brand hooked up PC&#8217;s that include ATI Radeon dual output graphics cards with massive monitors.  This is probably the only time I&#8217;d willingly admit that Windows came out ahead, as I spent a good 2 days trying to get my dual monitors to work with Ubuntu.  I finally got it figured out and I&#8217;m embarrassed to say that the answer was in front of my the whole time &#8212; a fucking GUI!  Anywho, those of you who are having trouble with this as well, here&#8217;s what I did to make it work:</p>
<p>My setup:</p>
<ul>
<li>Dell Vostro 200, Dual Core Intel CPUs, 2 Gb RAM</li>
<li>ATI Radeon HD 2400 dual output graphics card (both monitors plugged into card)</li>
<li>Two Dell 17&#8221; monitors</li>
</ul>
<p>So first, shimmy over to <a href="http://ati.amd.com/support/driver.html" target="_blank">http://ati.amd.com/support/driver.html</a> and select your distro and card model, and download the file to your desktop.</p>
<p>In Terminal, <strong>chmod +x ati-driver-installer-&lt;version&gt;.run</strong></p>
<p>Select Linux x86 installation, automatic</p>
<p>After the installation is complete, run:</p>
<p><strong>sudo aticonfig &#8211;initial</strong></p>
<p>Reboot.</p>
<p>After reboot, run <strong>fglrxinfo</strong> and you should get something like this describing your card:</p>
<blockquote><p>OpenGL vendor string: ATI Technologies Inc.<br />
OpenGL renderer string: ATI Radeon HD 2400 PRO<br />
OpenGL version string: 2.1.7537 Release</p></blockquote>
<p>At this point you probably see that both monitors are enabled, but are mirroring each other.  <strong>If you don&#8217;t</strong>, you might need to manually active the second:</p>
<p><strong>sudo aticonfig &#8211;query-monitor</strong></p>
<p>Use the output of that command and run:</p>
<p><strong>sudo ati-config &#8211;enable-monitor=&lt;result1&gt;,&lt;result2&gt;</strong></p>
<p>Replace result1 and result2 with the output of the first command.  Possible results are: <strong>none, crt1, crt2, lvds, tv, fmds1, tmds2</strong></p>
<p>If the enable works, make it permanent:</p>
<p><strong>sudo aticonfig &#8211;force-monitor=&lt;result1&gt;,&lt;result2&gt;</strong></p>
<p>When both your monitors are up (whether they look how you want or not), in your GNOME gui, go to <strong>Applications &gt; ATI Catalyst Control Center. </strong>This is where you configure how you want your dual monitors to act.</p>
<p>In Display Manager, set the dropdown to two monitors and change the Display Mode to &#8220;Big Desktop&#8221; &#8212; this will enable both monitors as one long desktop that you can drag your mouse and windows between.  You can also go ahead and set your resolution.</p>
<p>And there you go &#8212; easy dual monitor setup for Ubuntu 7.10!</p>
<p><strong>UPDATE:</strong> Major issues with graphics after I upgraded to 8.10 &#8211; I found these instructions which worked:</p>
<p><a href="http://wiki.cchtml.com/index.php/Ubuntu_Intrepid_Installation_Guide#Installing_the_restricted_drivers_manually" target="_blank">http://wiki.cchtml.com/index.php/Ubuntu_Intrepid_Installation_Guide#Installing_the_restricted_drivers_manually</a></p>
<p><map name='google_ad_map_158_7fa65e237551a74a'>
<area shape='rect' href='http://imageads.googleadservices.com/pagead/imgclick/158?pos=0' coords='1,2,367,28' />
<area shape='rect' href='http://services.google.com/feedback/abg' coords='384,10,453,23'/></map>
<img usemap='#google_ad_map_158_7fa65e237551a74a' border='0' src='http://imageads.googleadservices.com/pagead/ads?format=468x30_aff_img&amp;client=&amp;channel=&amp;output=png&amp;cuid=158&amp;url= http%3A%2F%2Fwww.v-nessa.net%2F2008%2F06%2F12%2Fdual-monitor-setup-in-ubuntu-710-ati-radeon' /></p><img src="http://www.v-nessa.net/?ak_action=api_record_view&id=158&type=feed" alt="" />]]></content:encoded>
			<wfw:commentRss>http://www.v-nessa.net/2008/06/12/dual-monitor-setup-in-ubuntu-710-ati-radeon/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Creating and Installing an SPF Record</title>
		<link>http://www.v-nessa.net/2008/06/09/creating-and-installing-an-spf-record</link>
		<comments>http://www.v-nessa.net/2008/06/09/creating-and-installing-an-spf-record#comments</comments>
		<pubDate>Mon, 09 Jun 2008 18:36:35 +0000</pubDate>
		<dc:creator>Nessa</dc:creator>
				<category><![CDATA[uncategorized]]></category>
		<category><![CDATA[tutorials]]></category>

		<guid isPermaLink="false">http://www.v-nessa.net/2008/01/09/creating-and-installing-an-spf-record</guid>
		<description><![CDATA[.!. Have you ever received a bounce for spam that was sent by you&#8230;only it wasn&#8217;t sent by you? Email spoofing is one of the easiest concepts to understand for us, but the hardest to explain to end users who confuse spoofing with email hacking and hijacking. The way I explain it to our customers [...]]]></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%2Fwww.v-nessa.net%2F2008%2F06%2F09%2Fcreating-and-installing-an-spf-record"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fwww.v-nessa.net%2F2008%2F06%2F09%2Fcreating-and-installing-an-spf-record&amp;source=nessa421&amp;style=normal&amp;service=bit.ly&amp;b=2" height="61" width="50" /><br />
			</a>
		</div>
<div style="display:none">.!.</div>
<p>Have you ever received a bounce for spam that was sent by you&#8230;only it wasn&#8217;t sent by <em>you</em>?  <a href="http://en.wikipedia.org/wiki/E-mail_spoofing" target="_blank">Email spoofing</a> is one of the easiest concepts to understand for us, but the hardest to explain to end users who confuse spoofing with email hacking and hijacking.  The way I explain it to our customers is that spoofing is simply when someone (usually spammers) sends an email that looks as if it came from one person, when it really came from someone else.</p>
<p>Regardless of what some email providers say, there is no honest and straight forward way to keep people from spoofing your email, unless you have access to the real sender&#8217;s mail system.  However, there is a way to keep legitimate mail servers from accepting spoofed email by creating an SPF record for your domain.</p>
<p>An SPF record (<strong>s</strong>ender <strong>p</strong>olicy <strong>f</strong>ramework) in short is a DNS record that you add to your domain&#8217;s zone file to specify which hosts are allowed to send mail on behalf of your domain.  For the most part you would only want the server hosting your domain to be able to send mail, but hat most of our customers don&#8217;t realize is that they unknowingly spoof email all the time!  Since ISP&#8217;s nowadays block SMTP port 25 for third-party mail servers, a lot of our customers use their ISP to send mail for their domain.  This is basically how email is spoofed&#8230;you put an email address as the &#8216;from&#8217; address in an email, and send it from a different mail server.  Even though this is legitimate email, they are basically allowing their ISP&#8217;s mail servers to send their domain&#8217;s email, even though their ISP has no authority or management rights over that email, since the domain is hosted on another server.</p>
<p>We usually require our customers to generate their own SPF records so that they can specify what servers they want to be able to send mail from, that way our hands stay clean if the SPF record causes them to not be able to send email.  If you go to www.openspf.org you can easily generate a custom SPF record to add to your DNS zone with little to no hassle.  The questions can be a little confusing for newbies, so here&#8217;s a quick walkthrough on how to answer them.</p>
<h4><strong>Question 1: A-Record</strong></h4>
<pre>v-nessa.net's IP address is 216.134.252.71 (vps71.inmotionhosting.com).
Does that server send mail for v-nessa.net?</pre>
<p>The wizard will attempt to resolve the domain to an IP, then do a rDNS on the IP for a hostname. You usually want to say <strong>YES</strong> unless your mail is hosted on a different server.</p>
<p><a title="Question_2:_MX-Record" name="Question_2:_MX-Record"></a></p>
<h4><strong>Question 2: MX-Record</strong></h4>
<pre>This wizard found 2 names for the MX servers for v-nessa.net:</pre>
<pre>vps71.inmotionhosting.com and v-nessa.net.
MX servers receive mail for v-nessa.net.
Do they also send mail from v-nessa.net?</pre>
<p>In most cases, this will be true. Exceptions for this is if you have an irregular MX record modification, or are using another outgoing mail server or domain to send mail.</p>
<h4><strong>Question 3: PTR</strong></h4>
<pre>Do you want to just approve any host whose name ends in v-nessa.net?</pre>
<p>Typically, you do not want to enable this setting unless you have mail accounts set up for subdomains or domains that are similar in ending that need to relay through this domain.  Or, if you use a subdomain as your sending host (like mail.domain.com, etc)</p>
<h4><strong>Question 4: A subs</strong></h4>
<pre>Do any other servers send mail from v-nessa.net?</pre>
<p>The answer is usually <strong>no</strong>. The only other server that would send on behalf of that domain would be the server name (you may need to ask your host for this), but this was already allowed in question 1. The next two fields can be left blank, unless you specifically have information to add to them.</p>
<div class="editsection"></div>
<h4><strong>Question 5: Include</strong></h4>
<pre>Could mail from v-nessa.net originate through servers belonging to some other domain?</pre>
<p>Fill in this field mainly if you are planning on using another mail server or domain (such as your ISP, gmail, etc.) to send mail. Otherwise say <strong>no.</strong></p>
<div class="editsection"></div>
<h4><strong>Question 6: ~all</strong></h4>
<pre>Do the above lines describe all the hosts that send mail from v-nessa.net?</pre>
<p>Check your answers and hit <strong>yes</strong>.<br />
At the bottom of the page you&#8217;ll see the nicely-generated SPF record that will look something like this:</p>
<pre>"v=spf1 a mx ~all"</pre>
<div class="editsection"></div>
<h3>Adding the Zone Entry</h3>
<p>You can add the SPF record either WHM (if you are on a cPanel server) or manually in the zone file of that domain.</p>
<p>The line will look something like this:</p>
<pre>v-nessa.net. 14400 IN TXT "v=spf1 a mx ~all"</pre>
<p>You can then verify the addition by doing a dig on the domain:</p>
<blockquote><p>dig v-nessa.net TXT</p>
</blockquote>
<pre><a href="http://www.dnsstuff.com/tools/lookup.ch?name=v-nessa.net&amp;type=TXT" class="external free" title="http://www.dnsstuff.com/tools/lookup.ch?name=v-nessa.net&amp;type=TXT" rel="nofollow"></a></pre>
<p><!--adsense--></p>
<p><map name='google_ad_map_139_7fa65e237551a74a'>
<area shape='rect' href='http://imageads.googleadservices.com/pagead/imgclick/139?pos=0' coords='1,2,367,28' />
<area shape='rect' href='http://services.google.com/feedback/abg' coords='384,10,453,23'/></map>
<img usemap='#google_ad_map_139_7fa65e237551a74a' border='0' src='http://imageads.googleadservices.com/pagead/ads?format=468x30_aff_img&amp;client=&amp;channel=&amp;output=png&amp;cuid=139&amp;url= http%3A%2F%2Fwww.v-nessa.net%2F2008%2F06%2F09%2Fcreating-and-installing-an-spf-record' /></p><img src="http://www.v-nessa.net/?ak_action=api_record_view&id=139&type=feed" alt="" />]]></content:encoded>
			<wfw:commentRss>http://www.v-nessa.net/2008/06/09/creating-and-installing-an-spf-record/feed</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
	</channel>
</rss>

