Monday, December 21, 2009

Script to record the IP address of your computers

I like to keep a simple script on all of my machines that routinely checks in with a server and records the current IP of the machine. It's great for ssh'ing into a machine that has a constantly changing IP address (like a laptop) and in case of theft, it could help track down the stolen machine.

I like to have the clients check in with a webserver, instead of a machine I own. Basic websites are cheap (like GoDaddy) and have high availability.

There will be three files that this project will use:
-CheckIn.php will be on the server and will record the IP.
-CheckIn.txt will store the IP addresses.
-CheckIn will be on the client. It will use wget to contact the server.

1. Here is CheckIn.php:

<?php
//Begin Setup - Change these variables
$filename = "CheckIn.txt"; //The name of the text file to save the IP addresses to.
$my_pass = "password"; //The password to see the IP addresses.
$max_lines = 100; //The maximum number of IP addresses to store. 0 for no limit.
//End Setup

if (!function_exists('file_put_contents')) {
function file_put_contents($filename, $data) {
$f = @fopen($filename, 'w');
if (!$f) {
return false;
} else {
$bytes = fwrite($f, $data);
fclose($f);
return $bytes;
}
}
}

$computer = htmlentities($_GET['user']);
$password = htmlentities($_GET['password']);
$contents = file_get_contents($filename);
if(!$computer){
if($password==$my_pass){
echo "<table border=1 cellpadding=2 cellspacing=2>";
echo $contents;
echo "</table>";
}
} else {
$output = "<tr>";
$output = $output."<td>".$computer."</td>";
$output = $output."<td>".$_SERVER['REMOTE_ADDR']."</td>";
$output = $output."<td>".date("ymd H:i D")."</td>";
$output = $output."<td>".time()."</td>";
$output = $output."<td>".$_SERVER['HTTP_REFERER']."</td>";
$output = $output."<td>".$_SERVER['HTTP_USER_AGENT']."</td>";
$output = $output."</tr>\n".$contents;
$counter = fopen("Stats", 'w');
fwrite($counter, $output);
fclose($counter);
if($max_lines!=0){
$array = file($filename);
for($i=sizeof($array); $i>=$max_lines;$i--){
unset($array[$i]);
}
$array=array_values($array);
file_put_contents($filename,implode($array));
}
}

?>


This code should work on all machines running PHP v4.3 and later. Change the filename, password, and max_lines at the beginning of the file to the values you want to use.

2. CheckIn.txt is an empty file to start with:

touch CheckIn.txt


3. Upload Checkin.php and Checkin.txt to your webserver. Setup the permissions so that Checkin.php is accessible, but Checkin.txt is not:

chmod 644 CheckIn.php
chmod 600 CheckIn.txt



4a. Add an entry to CheckIn.txt whenever there is a new Internet connection. This only works if you are using NetworkManager. As root, create the file /etc/NetworkManager/dispatcher.d/CheckIn:

#!/bin/sh

if [ "$2" = "up" ]; then
wget http://URL_TO_CHECKIN.PHP?user=COMPUTER -O /dev/null > /dev/null 2> /dev/null
fi


and make it executable:

chmod +x /etc/NetworkManager/dispatcher.d/CheckIn



4b. Add an entry to CheckIn.txt every 10 minutes. Either as a regular user, or as root, create a crontab:

export EDITOR=`which pico`
crontab -e


The choice of editor is completely up to you. Put the following in your crontab:

*/10 * * * * sh /root/script.sh > /dev/null 2> /dev/null


where the "*/10" indicates that the command should be run every 10 minutes. Wikipedia has an great page on the format of crontabs.

Finally, check to make sure that the crontab was installed correctly:

crontab -l

Sunday, December 20, 2009

The case against Swap

Swap, that extra partition you keep around in case you run out of memory, is actually, in most situations, a bad thing to have. Here's why.

Why swap was a good thing.

1. Hard drives and RAM memory used to have similar speeds. RAM was faster, but not by so much that it meant the system was unusable if it was run off of the hard drive instead. When this is the case, it makes sense to use the hard drive as a backup, but slower memory.

2. Applications tended to fill the RAM. Imagine you have a system with 16MB of memory. You have a word processor that uses 12MB and an image editor that uses 12MB. To have both open simultaneously, you need to have an extra 8MB of storage somewhere. It makes sense to use the hard drive. This way, you can keep the entire word processor in memory when you're using it and when you switch to the image editor, the system can swap the word processor to disk and bring the image editor back to RAM. You'll experience a word processor and image editor that both run at full speed and the only slowdown you'll see is when you switch applications.



Why swap is (now) a bad thing.

1. RAM memory is now so much faster than the hard disk that the system is unusable if it runs off of the hard drive. Maybe this will change again someday as SSD's pickup speed, but for now, it's better to have an application crash or fail to open rather than have an almost frozen and completely unusable system.

2. In most cases, no single application consumes a majority of the RAM. Today, a large application might consume 15%-20% of the available RAM on your system. This makes it unlikely that you'll need to have one application's memory on disk while the other one is in RAM. Running out of RAM today is more likely due to having far too many applications open. The solution is not to mask it by swapping to disk, but rather to either change user behavior (keep fewer applications open) or install more RAM.

3. If the machine starts to thrash (i.e., access the swap continuously), it can be rough on a hard drive, especially if you're using a SSD, where the number of writes is limited.



Why not having swap is a good thing.

It can stop bugs. I had a buggy version of Adobe Acrobat that after you "closed" it, it would remain open in the background and slowly consume memory. After a couple of hours, all of the RAM would be gone and it would start in on the swap. After a couple of more hours, the system would be thrashing the disk and completely unusable. Without swap, after Acrobat used up all of the RAM, it would request more, the request would fail, and it would crash (and close). Of course, it would have been better if Adobe had produced a bug-free version of Acrobat, but consider in this case not having swap prevented my system from being brought down due to a buggy application.



Why not having swap could be a bad thing.

If you have a particular use case that requires you to use more memory than you have RAM, then you will need to have swap. But let me suggest that instead of permanently keeping around a swap partition, use a swap file instead and only activate it when you know you're going to be needing it.


My conclusions.

I think for most users, swap is an outdated concept and causes more trouble than its worth. And your applications probably don't require as much memory as you think. A couple of real-world examples:

I have an old P4 system with 384MB of RAM and no swap that's been running fine for word processing and Internet use for years. It has OpenSUSE 11.1 on it with XFCE.

I also have a laptop with 512MB of RAM and no swap, running OpenSUSE 11.1 with KDE 3.5. I use it for word processing, web surfing, watching Hulu and YouTube videos. I even use a TV tuner card to record shows. I used this machine to write a 100 page technical manual filled with graphics (both vector and bitmapped). Again, I've had no problems due to the lack of swap.

Thursday, December 17, 2009

Absolutely silent wget

I had an application where I wanted to use wget to request a file from an http server, but I wanted absolutely no output. No status, no errors, nothing to the console and nothing written to the disk. This is for a laptop "anti-theft" script I'm working on. Everytime an Internet connection is established, the local script calls a PHP script on my webserver, which records the IP address it was called from. As a result, I get a nice list of IP addresses where my laptop has been. However, I don't want the disk filling up with a bunch of HTML files, as is the standard practice for wget. The solution is this:

wget http://URL -O /dev/null > /dev/null 2>&1

The "-O" directs the HTML file to /dev/null, then ">" directs the standard output to /dev/null, and then "2>&1" directs the standard error to the standard output which goes to /dev/null. As a result, this is an absolutely silent (even if its fails) wget.

One quick word of warning, the "2>&1" does not work in the sh shell. So, in your script files, instead of:

#!/bin/sh

you'll need to use another shell (like bash):

#!/bin/bash

or, not use that fancy redirect at all and use "2> /dev/null" instead.