Posts Tagged “Linux”

Ever wanted / needed HTTPD or another service to run with a raised thread priority?

Well you have a couple of options, add additional lines to the /etc/init.d script to change the nice level by adding additional lines on startup, or if you only need to do this on a temporary basis without restarting the service but need every thread to have a raised priority you can use a bash script

1
2
3
4
5
6
#!/bin/bash
PIDS=`ps aux | grep httpd | grep -v 'grep' | awk '{print $2}'`;
for PID in ${PIDS[@]}
do
        renice 20 -p $PID
done

You can renice between -20 and +20, depending on your requirements you can use this script in a cron job to raise/lower priorities, change httpd for whatever service you want to change the thread priority for.

Ever needed to check files were being accessed / written to?

For this one you’re going to need the inotify-tools package, specifically the inotifywait binary.

1
inotifywait -m --timefmt "[%a %b %d %H:%M:%S %Y]" --format "%T [%e] %f" -r /folder/to/watch

An example usage is to ensure that caching is working correctly and that cache files are being used in place of processing PHP files, simply change “/folder/to/watch” to be your cache folder, and refresh a few pages.

All being well you’ll get an output similar to the following:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
y-tools-3.14)
(root@132 BUZZ1) # /usr/local/bin/inotifywait -m --timefmt "[%a %b %d %H:%M:%S %Y]" --format "%T [%e] %f" -r /path/to/saiweb/wp-content/cache/supercache/*
Setting up watches.  Beware: since -r was given, this may take a while!
Watches established.
[Thu Jul 15 20:59:37 2010] [OPEN] index.html
[Thu Jul 15 20:59:37 2010] [CLOSE_NOWRITE,CLOSE] index.html
[Thu Jul 15 21:00:08 2010] [OPEN,ISDIR]
[Thu Jul 15 21:00:08 2010] [OPEN,ISDIR] security
[Thu Jul 15 21:00:08 2010] [OPEN,ISDIR]
[Thu Jul 15 21:00:08 2010] [OPEN,ISDIR] vsftpd-chrooting-without-the-headache-allowing-shared-directories
[Thu Jul 15 21:00:08 2010] [OPEN,ISDIR]
[Thu Jul 15 21:00:08 2010] [CLOSE_NOWRITE,CLOSE,ISDIR] vsftpd-chrooting-without-the-headache-allowing-shared-directories
[Thu Jul 15 21:00:08 2010] [CLOSE_NOWRITE,CLOSE,ISDIR]
[Thu Jul 15 21:00:08 2010] [OPEN,ISDIR] the-zen-of-secured-shared-hosting-part-1
[Thu Jul 15 21:00:08 2010] [OPEN,ISDIR]
[Thu Jul 15 21:00:08 2010] [CLOSE_NOWRITE,CLOSE,ISDIR] the-zen-of-secured-shared-hosting-part-1
[Thu Jul 15 21:00:08 2010] [CLOSE_NOWRITE,CLOSE,ISDIR]
[Thu Jul 15 21:00:08 2010] [OPEN,ISDIR] php-security-considerations
[Thu Jul 15 21:00:08 2010] [OPEN,ISDIR]
[Thu Jul 15 21:00:08 2010] [CLOSE_NOWRITE,CLOSE,ISDIR] php-security-considerations
[Thu Jul 15 21:00:08 2010] [CLOSE_NOWRITE,CLOSE,ISDIR]
[Thu Jul 15 21:00:08 2010] [OPEN,ISDIR] antivirus-xp-2008-removal
[Thu Jul 15 21:00:08 2010] [OPEN,ISDIR]
[Thu Jul 15 21:00:08 2010] [CLOSE_NOWRITE,CLOSE,ISDIR] antivirus-xp-2008-removal
[Thu Jul 15 21:00:08 2010] [CLOSE_NOWRITE,CLOSE,ISDIR]
[Thu Jul 15 21:00:08 2010] [OPEN,ISDIR] suphplookupexception
[Thu Jul 15 21:00:08 2010] [OPEN,ISDIR]
[Thu Jul 15 21:00:08 2010] [CLOSE_NOWRITE,CLOSE,ISDIR] suphplookupexception
[Thu Jul 15 21:00:08 2010] [CLOSE_NOWRITE,CLOSE,ISDIR]
[Thu Jul 15 21:00:08 2010] [OPEN,ISDIR] honeypotting-for-viruses-statement-of-fees-200809
[Thu Jul 15 21:00:08 2010] [OPEN,ISDIR]
[Thu Jul 15 21:00:08 2010] [CLOSE_NOWRITE,CLOSE,ISDIR] honeypotting-for-viruses-statement-of-fees-200809
[Thu Jul 15 21:00:08 2010] [CLOSE_NOWRITE,CLOSE,ISDIR]
[Thu Jul 15 21:00:08 2010] [CLOSE_NOWRITE,CLOSE,ISDIR] security
[Thu Jul 15 21:00:08 2010] [CLOSE_NOWRITE,CLOSE,ISDIR]

As can be seen the re-write rules are redirecting users to the cached files/folders, in the example above I have used my wp-supercache folder.

Ever needed to quickly get the memory usage of all threads for a service?

You have two options for this a single line

1
 ps -Ao rsz,comm,pid | grep <process name>

or a bash function you can place in your ~/.bashrc

1
2
3
4
5
6
7
8
function appmem(){
    if [ -z "$1" ]; then
        echo "appmem <string to filter>"
        echo "i.e. appmem httpd";
    else
        ps -Ao rsz,comm,pid | grep $1
    fi
}

You can then call this (after logging back in again to load the .bashrc up) using

1
appmem <filter>

replacing for instance with httpd will give you an output similar to the following:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
8032 httpd            6207
33080 httpd           13828
 8552 httpd           14095
28952 httpd           14102
 8540 httpd           14103
30848 httpd           16741
31296 httpd           16832
30452 httpd           18439
31044 httpd           19996
30968 httpd           23287
30356 httpd           23300
25636 httpd           24553
29712 httpd           24771
25588 httpd           24777
31632 httpd           24778
25608 httpd           24796
29716 httpd           24812
28152 httpd           24813
31684 httpd           31291

This shows memory in kilobytes, command, process id, you can see here I currently have 3mb/pid for each httpd process (due to my optimizations, I highly recommend you read parts 1-3)

Dump mysql data and compress on the fly

1
mysqldump -h <host> -u <user> -p <dbname> | bzip2 -c7 > /path/to/dump.sql.bz2

Self explanatory that one, pipes the output from mysqldump through bzip2 (which has better compression over gzip) and dumps it out to a file, if you _realy_ need a gziped file just replace bzip2 with gzip in the line above.

Ever needed a selection of passwords generated?

For this one you can use the secpwgen

1
2
3
function pwgen(){
        for (( i=0; i<=10; i++ )) do pwd=`secpwgen -Aadhs 10 2>&1 | grep ENTROPY | awk '{print $1}';`; echo "$i: $pwd"; done;  
}

Plant this in your ~/.basrc for a callable function that will genrate a selection of 10 secure passwords, handy when you’re fed up of 1337′ifying everything

example output:

1
2
3
4
5
6
7
8
9
10
11
0: 4>&B.\2R+--
1: )`WREEGZP{
2: ^)3"=F==|?0
3: ?1/|;;GF-2
4: [..///_([=AZ
5: }^%RC~U8//L
6: \//VNTQ[)->
7: @HE5@3)A%?
8: )|1C[BSIT*
9: C[//X^W<$G1
10: EOQ#Y%NI>-

Modify the “-Aadhs” args to your taste.

This concludes Volume 1 and a very long post, please contribute your one liners / helper scripts via the comments.

Cheers

buzz

Tags: , , , , , ,

Comments 2 Comments »

For security newer distros of RHEL and their derivatives an mounting /tmp with the noexec option.

Now if you have ever had to clean up a compromised web app you can see why this makes a lot of sense, and if not here’s a quick example.

Yours/Clients web app becomes compromised, running kernel has a buffer overflow that can lead to privilege escalation, attack writes out their code and compiles in /tmp, then runs said app from /tmp creating a pseudo root level shell, aka you’ve just been root kitted.

However there are legitimate reasons for using /tmp to compile, well I say legitimate, what I in fact mean is things like pecl, which you use to install extensions like APC require this …

workaround:

1
export TMPDIR='/a/paTh/your/user/can/write/to'

Failing that:

service httpd stop

DO NOT ALLOW ANY WEBAPP ACCESS WHILE NOEXEC IS IN USE!

1
2
3
mount -o,remount,rw,exec /tmp
pecl install apc
mount -o,remount,rw,noexec /tmp

DO NOT REMOVE THE NOEXEC OPTION IN /ETC/FSTAB PERMANENTLY YOU WILL REGRET DOING SO

Tags: , , ,

Comments No Comments »

Following on from Linux – Generating file manifests and then checking them I was always getting the same questions …

How long left on the manifest Buzz ?
How long left on the verification Buzz ?

And I HATE having to turn around an say … I don’t know …

The problem with the usual command line method is that it give no indication of progress, and by extension no indication that it was infact running and not ‘hung’ …

As such I have now added the ‘manifest’ command set to the Sysadmin toolset

The manifest command take two data types, the first is a folder path from which to build the file manifest from, the manifest itself is also compatible with the “md5sum –check” function.

The second is the path to the manifest itself, in this case the manifest command will verify each file against it’s entry in the manifest:

At each point the command give you an indication of it’s current status, however this does come at a small cost, the script has no concept of the size of you console and as such will always render out the same number of character meaning if you console is not wide enough it will not render correctly, in the videos I have the console on a high resolution monitor as can be seen each video itself is 900 pixels wide.

This process is CPU intensive (20-45% on one core of a intel core2duo 2.8GHZ) and uses around 140KB of memory.

Tags: , , , , , , , ,

Comments No Comments »

In part 4, I am going to cover more of an improvement than anything else to part 3

Part 3 itself is not incorrect, it correctly takes a memory footprint for each process running, the same as VIRT in top …

However in processes such as APACHE the VIRT memory is the size of all shared libraries, as correctly shown by pmap …

So what does this mean realy?

The memory usage is infact the following VIRT + RSS, where RSS is the resident set size, the RSS is a representation of the memory in use by the PID, and VIRT is shared between the child processes.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
[buzz@buzz_srv ~]# ps aux | grep httpd | grep -v 'grep'
root     16378  0.0  0.1 148640  3024 ?        Ss   Nov13   0:00 /usr/sbin/httpd
apache   20088  0.0  0.1 148640  3304 ?        S    Nov13   0:00 /usr/sbin/httpd
apache   20101  0.0  0.1 148640  3304 ?        S    Nov13   0:00 /usr/sbin/httpd
apache   20756  0.0  0.1 148640  3312 ?        S    Nov13   0:00 /usr/sbin/httpd
apache   20759  0.0  0.1 148640  3300 ?        S    Nov13   0:00 /usr/sbin/httpd
apache   20790  0.0  0.1 148640  3284 ?        S    Nov13   0:00 /usr/sbin/httpd
apache   20792  0.0  0.1 148640  3312 ?        S    Nov13   0:00 /usr/sbin/httpd
apache   20798  0.0  0.1 148640  3308 ?        S    Nov13   0:00 /usr/sbin/httpd
apache   20804  0.0  0.1 148640  3308 ?        S    Nov13   0:00 /usr/sbin/httpd
apache   20886  0.0  0.1 148640  3304 ?        S    Nov13   0:00 /usr/sbin/httpd
apache   20906  0.0  0.1 148640  3300 ?        S    Nov13   0:00 /usr/sbin/httpd
apache   20907  0.0  0.1 148640  3308 ?        S    Nov13   0:00 /usr/sbin/httpd
apache   20912  0.0  0.1 148640  3304 ?        S    Nov13   0:00 /usr/sbin/httpd
apache   20915  0.0  0.1 148640  3312 ?        S    Nov13   0:00 /usr/sbin/httpd
apache   20959  0.0  0.1 148640  3304 ?        S    Nov13   0:00 /usr/sbin/httpd
apache   20969  0.0  0.1 148640  3300 ?        S    Nov13   0:00 /usr/sbin/httpd
apache   20994  0.0  0.1 148640  3320 ?        S    Nov13   0:00 /usr/sbin/httpd
apache   20995  0.0  0.1 148640  3288 ?        S    Nov13   0:00 /usr/sbin/httpd
apache   20996  0.0  0.1 148640  3320 ?        S    Nov13   0:00 /usr/sbin/httpd
apache   20997  0.0  0.1 148640  3320 ?        S    Nov13   0:00 /usr/sbin/httpd
apache   20999  0.0  0.1 148640  3296 ?        S    Nov13   0:00 /usr/sbin/httpd

As can be seen above the ‘VIRT’ does not change between the child processes, where as the RSS does dependant on what the thread is doing at that time.

So below is an improved appmem function to allow for this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
function appmem {
        if [ -z "$1" ]; then
                echo "Usage: sysadmin appmem app_name i.e. (sysadmin appmem apache)";
        else
                RRES=(`ps aux | grep "$1" | grep -v 'grep' | grep -v "$0" | awk '{print $6}'`);
                VRES=(`ps aux | grep "$1" | grep -v 'grep' | grep -v "$0" | awk '{print $5}'`);
                COUNT=0;
                VMEM=0;
                RMEM=0;
                for RSS in ${RRES[@]}
                do
                        RMEM=$(($RSS+$RMEM));
                done;
                for VIRT in ${VRES[@]}
                do
                        VMEM=$(($VIRT+$VMEM));
                        COUNT=$(($COUNT+1));
                done;
                VMEM=$(($VMEM/$COUNT));
                VMEM=$(($VMEM/1024));
                RMEM=$(($RMEM/1024));
                echo -e "$YELLOW ----- MEMORY USAGE REPORT FOR '$1' ----- $CLEAR";
                echo "PID Count: $COUNT";
                echo "Shared Mem usage: $VMEM MB";
                echo "Total Resident Set Size: $RMEM MB";
                echo "Mem/PID: $(($RMEM/$COUNT)) MB";
        fi
}

Example output:

1
2
3
4
5
 ----- MEMORY USAGE REPORT FOR 'httpd' -----
PID Count: 41
Shared Mem usage: 140 MB
Total Resident Set Site: 95 MB
Mem/PID: 2 MB
Tags: ,

Comments 2 Comments »

PART 3 IS INACCURATE, THE BELOW SCRIPT IS FOR REFERENCE ONLY, IT HAS BEEN REPLACED IN PART 4

In part 3, I am going to cover a bash function that will allow you to profile the memory usage of any application by name.

By adding the function below into your script you can execute a command such as: sysadmin appmem apache

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
function appmem {
if [ -z "$1" ]; then
echo "Usage: sysadmin appmem app_name i.e. (sysadmin appmem apache)";
else
if [ -x '/usr/bin/pmap' ]; then
APID=(`ps aux | grep "$1" | grep -v 'grep' | grep -v "$0" | awk '{print $2}'`);
COUNT=0;
AMEM=0
for PID in ${APID[@]}
do
TMP=$((`pmap -x $PID | grep "total" | awk '{print $3}'`));
AMEM=$(($AMEM+$TMP));
COUNT=$(($COUNT+1));
done
AMEM=$(($AMEM/1024));
echo -e "$YELLOW ----- MEMORY USAGE REPORT FOR '$1' ----- $CLEAR";
echo "PID Count: $COUNT";
echo "Mem usage: $AMEM MB";
echo "Mem/PID: $(($AMEM/$COUNT)) MB";
echo -e "$RED"
echo -e "For more information run: pmap -x $PID $CLEAR";
else
echo 'Could not execute /usr/bin/pmap ... aborting';
exit;
fi
fi
}

Sample output:

1
2
3
4
5
6
<span style="color: #ffcc00;">----- MEMORY USAGE REPORT FOR 'apache' -----</span>
PID Count: 6
Mem usage: 1134 MB
Mem/PID: 189 MB
<span style="color: #ff0000;">
For more information run: pmap -x 123456</span>

You can of course replace ‘apache’ with the application or daemon name you want to profile the memory usage of.

This script does require that pmap is installed, if the script can not find it, it will abort.

As always any problems, post a comment.

UPDATE: Apparently I need to point out that if you haven’t read PART 2! then the colored output will not work … That’s why this entry is titled part 3, it does assume a degree of competence on your part in realizing part’s 1 and 2 may just be required reading …

NOTE: The above provides a complete memory footprint of the indvidual PID, the same as VIRT in top.

VIRT — Virtual Image (kb)
* The total amount of virtual memory used by the task. It includes all code, data and shared libraries plus pages that have been swapped out.
* VIRT = SWAP + RES

Tags: , ,

Comments 3 Comments »

/usr/bin/ld: skipping incompatible /usr/lib/libcom_err.so when searching for -lcom_err

his one has been bugging me for a couple of hours now, when trying to compile PHP on a 64bit OS …

Simple put it’s a missing symlink, and the config script is trying to “failover” to the version is can find which is 32 bit …

ln -sf /lib64/libcom_err.so.2 /lib64/libcom_err.so

Et voila fixed!

Tags: , , , , , , ,

Comments 1 Comment »

Part 2 has finally arrived …. don’t all cheer at once now …

In part two I will cover how to run an IP range scan using bash script, and if the host can be pinged retrieve the MAC address of the connected host.

Now bare in mind this script was written to run from a MAC running OSX Leopard.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#!/bin/bash
#colours
function colours {
CLEAR='\e[00m';
GREEN='\e[0;32m';
RED='\e[0;31m';
YELLOW='\e[1;33m';
}
#ipscan
function ipscan {
IPS_START=1;
IPS_END=254;
IPS_RANGE=192.168.1.
echo "Now running IPSCAN $IPS_RANGE$IPS_START - $IPS_RANGE$IPS_END"
for ((i=$IPS_START;i&lt;=$IPS_END;i+=1)); do
RESULT=`ping -c 1 -t 1 $IPS_RANGE$i | grep "bytes from"`;
if [ -z "$RESULT" ]; then
echo -e "$IPS_RANGE$i:$RED DEAD $CLEAR";
# If you comment out the above to report just the alive hosts, bash gets a bit funny about not processing anything here, so uncomment the below to keep it happy
#holder=$i;
else
MAC=`arp $IPS_RANGE$i | awk '{ print $4 }';`;
echo -e "$IPS_RANGE$i:$GREEN ALIVE $CLEAR ($MAC)";
fi
done
}
colours;
$1 $2

To make this work on your Linux distro replace -t in the ping command with -W and check the awk entry for the arp output, a display of (no) means that no ARP entries could be found for the host, and change the IP range to that of your network.

That’s it for this part, dump this is a file and chmod +x as useual and run with ./script.sh ipscan.

Tags: , , ,

Comments 1 Comment »

Prompted by the following remarks today …

Kerm: “;) there is always an abbreviation in the CLI as all sysadmins are lazy feckers”

Kerm: “Someone might think you actually do work occasionally, god forbid!”

Sysadmins are NOT inherently lazy, we just know how to save time, and are quite adept at doing so …ok?

You cheeky sods!

So let me clear up one instance in which I take a lot of information, and make it quickly and easily accessible using a “Lazy feckers” abbreviation …

Be warned this is a very jaded write up, read on at your own peril.

Right then, onto the point of this post, the sysadmin script part 1, this is going to cover how to check how many connections to a specific port you have on your server.

Trust me this becomes very useful when you have exhausted all other options when trying to figure out why your web server is running like a dog with no legs …

1
netstat -ant

After running the above on your SSH session you will see lines, and lines … and yet more lines of network connection information, especially if you just run this on a busy server.

Example (colours added):

tcp 0 0 ***.***.***.***:25 ***.***.***.***:32794 ESTABLISHED

Key:

PROTOCOL Tx Rx LOCALHOST:PORT FOREIGN_HOST:PORT CONNECTION STATE

From this information it’s pretty easy to spot this is an inbound SMTP connection.

(If you can’t see why, don’t worry it’s ok maybe it’s genetic)

Now this may be handy, but other than taking all this information and dumping it into a spreadsheet (god knows you love those spreadsheets !!! ), how are you going to figure out how many connections are occurring from that external host?

How infact are you going to be able to easily see how many total connections to that port you have ?!?!

Bash script, now for some history, Bash is the Bourne Again Shell, or as I like to think of it, it is the verb for what I will do to your head if you ask me what BASH / SSH / Shell is again …

Now create a directory:

1
2
mkdir ~/.sysadmin
cd ~/.sysadmin

Note the prefixing dot, this will create a “hidden” directory in your home directory (~), the reason for this is so you don’t have system admin script sat in your home directoy, as if you are like me, all sorts of crap moves in an out of that directory on a daily basis, and the last thing you want to do is to have to rummage through backups trying to find “that script you wrote to diagnose connection problems a year ago“.

The point is these scripts will become part of your workflow, once written they will rarely need updating, and should never be called directly, (I mean we’re lazy right? WTH do we want to be typing the full script path for? … oh yeh it saves time!).

In this case:

1
vi ~/.sysadmin/buzz.sh

You can of course call your script whatever you want, and use any text editor you want, if you don’t like / know vi …

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#!/bin/bash
# Sysadmin script PART 1 http://www.saiweb.co.uk
# Provided under the MIT license (http://www.opensource.org/licenses/mit-license.php)
# © D.Busby
function usage {
echo "Usage: portcon port";
echo "i.e. portcon 80";
}
function portcon {
echo "----- Active Connections For Port $1 -----";
netstat -ant | grep "ABC.DEF.HIJ.KLM:$1 " | wc -l
netstat -ant | grep "ABC.DEF.HIJ.KLM:$1 " | awk '{ print $5 }'  | awk -F \: '{ print $1  }' | sort | uniq -c  | sort -n
}
if [ -z "$1" ]; then
usage;
exit
fi
$1 $2

Ok so the above code is provided with two functions usage and portcon.

MAKE SURE YOU REPLACE “ABC.DEF.HIJ.KLM” WITH YOUR LOCAL IP ADDRESS

CHMOD this file to allow execution.

1
chmod +x ~/.sysadmin/buzz.sh

Now edit your bashrc file.

1
vi ~/.bashrc

And add the following:

alias buzz=’~/.sysadmin/buzz.sh’

Now exit (logout) your SSH session and log back in (or SU root > SU your_user for testing).

1
2
3
4
[buzz@buzz_srv ~]$ buzz
Usage: portcon port
i.e. portcon 80
[buzz@buzz_srv ~]$

Now run the portcon check …

1
2
3
4
5
6
7
8
9
10
11
12
13
14
[buzz@buzz_srv ~]$ buzz portcon 80
----- Active Connections For Port 80 -----
505
1 ***.***.***.***
3 ***.***.***.***
3 ***.***.***.***
4 ***.***.***.***
4 ***.***.***.***
5 ***.***.***.***
11 ***.***.***.***
14 ***.***.***.***
16 ***.***.***.***
76 ***.***.***.***
373 ***.***.***.***

(Yes before you ask ***.***.***.*** does display the correct IP address, I have purposely removed them for security).

So, I have taken something that would of resulted in netstat output > spreadsheet to formulas > at a estimate 30mins a time analysis to something that now takes less than 5 seconds to type, and get the relevant output, for roughly the same initial effort (30 mins scripting time).

You could argue you can keep a spreadsheet pre-setup with the right formulas / pivot tables and just dump the data each time, well yes you could but that’s no where near as quick as this …

And no trying to convince me it is as quick and better than the script above, for

  1. You have to wait for excel to open the spreadsheet
  2. You have to copy paste the data
  3. You have to wait for excel to process the formulas

If you have a machine that can do that in time equal to or less than the time it takes the script above to output the data, the only thing I have to say is, stop spending such a budget on desktops and get a better server.

Final Thoughts:

This write up is in jest, and is intended to be read as such, the code and methods provided above are factual. etc …

Tags: , ,

Comments No Comments »

So while reading Hackaday today I came across a “render farm” project which has about the same power usage as a desktop (400w) the difference is this one has 24cpu’s and 48gb of ram.

Tags: , ,

Comments No Comments »

a very basic video tutorial covering how to compile with debug information, load your app into gdb, set breakpoints and step through it.

No where near as much details as I wanted, but I never seem to get time to finish the full version, this will help in the interim.

NOTE: you will need XviD codec or use VLC.

If you re-distribute the video please give a link back (don’t force me to start water marking).

Tags: , ,

Comments 1 Comment »

Creative Commons License