June 17th, 2008 at 11:58 am

Restore SSH Public Key

Today I did something stupid: I overwrote an SSH public key with a file from a different machine:

CODE:
  1. scp id_rsa.pub user@example.org:~/.ssh

Obviously, I wanted to place the Public Key for the account from one machine on the other one to append it to the authorized_keys file of the target account. Unfortunately, I didn't bear in mind that I already had a public key file (id_rsa.pub) in this directory. So I had to re-create the Public Key file from the Private Key. This is quite easy, it appears that the SSH developers already thought of this situation. The following code will restore the Public Key file from the Private Key (example for an RSA key):

CODE:
  1. cd ~/.ssh; echo "id_rsa" | ssh-keygen -y> id_rsa.pub 2>/dev/null

June 11th, 2008 at 11:03 am

Shell script to optimize all tables in all databases (MySQL)

If you have many databases with many write operations, it may be that the table overhead takes a good amount of space. (This is due to the fact that MySQL doesn't free the space of deleted entries.) With "optimizing" the tables, you can free that space.

Save the following script as /usr/local/sbin/optimizealltables.sh, make it chmod 700 (very important!), then replace YOURPASSWORD with your root MySQL password.

CODE:
  1. #!/bin/bash
  2.  
  3. MYSQL_LOGIN='-u root --password=YOURPASSWORD'
  4.  
  5. for db in $(echo "SHOW DATABASES;" | mysql $MYSQL_LOGIN | grep -v -e "Database" -e "information_schema")
  6. do
  7.         TABLES=$(echo "USE $db; SHOW TABLES;" | mysql $MYSQL_LOGIN |  grep -v Tables_in_)
  8.         echo "Switching to database $db"
  9.         for table in $TABLES
  10.         do
  11.                 echo -n " * Optimizing table $table ... "
  12.                 echo "USE $db; OPTIMIZE TABLE $table" | mysql $MYSQL_LOGIN >/dev/null
  13.                 echo "done."
  14.         done
  15. done

April 16th, 2008 at 11:20 am

Clear a sized select field

If you have have a select form element with a size attribute, one common option for the user is to leave it empty (especially in combination with multiple). The problem is, as soon as one or more options are selected, it is quite impossible in most browsers, to not select anything at all. And even if there is a way, it is not easy to accomplish. Try for yourself to deselect all items:

With a little JavaScript magic, we can offer a button to clear the select field:

JavaScript:
  1. function nl_clear_select(element)
  2. {
  3.     var opt_length = document.getElementById(element).options.length;
  4.     for (var i = 0; i <opt_length; i++)
  5.         document.getElementById(element).options[i].selected = false;
  6. }

Now try again to clear the select field. Hint: clicking on "Clear selection" will help a lot. ;)

Clear selection

Neat, eh?

April 10th, 2008 at 12:14 pm

Get radio button value in JavaScript

Here's how to get the currently checked value of radio button section. The parameter elementName is the name attribute of the radio input.

JavaScript:
  1. function getRadioValue(elementName)
  2. {
  3.     var element = document.getElementsByName(elementName);
  4.     var bt_count = element.length; // can't use element.length in the loop, as it would decrement
  5.  
  6.     for (var i = 0; i <bt_count; i++)
  7.         if (element[i].checked == true)
  8.             return element[i].value;
  9. }

April 3rd, 2008 at 12:06 pm

Calculate interest rates with a shell script

If you put your cash to a bank account, you will want to know how much money you get with a certain amount at a given rate within a given period. Save the following Bash script as /usr/local/bin/loancalc (or something like that), make it executable, and you will be able to calculate the return on your investments with a single one-liner.

CODE:
  1. #!/bin/bash
  2.  
  3. function calc()
  4. {
  5.     return $(echo "scale=$2; $1" | bc)
  6. }
  7.  
  8. if [ "$1" == "-h" ] || [ "$1" == "--help" ]; then
  9.     echo "$0 calculates the interest loan of a given amount with a given rate for a given duration."
  10.     echo "Usage: $0 AMOUNT RATE DURATION"
  11.     exit 0
  12. fi
  13.  
  14. if [ -z "$3" ]; then
  15.     echo "Please enter the amount, the rate and the duration (in this order)."
  16.     exit 1
  17. fi
  18.  
  19. AMOUNT=$1
  20. ZINS=$2
  21. DURATION=$3
  22.  
  23. echo "Investment: $AMOUNT bucks at a rate of $ZINS% for $DURATION years."
  24. echo "          Loan            Total"
  25.  
  26. for i in $(seq 1 $DURATION); do
  27.     INTERESTLOAN=$(echo "scale=10; ($AMOUNT/100)*$ZINS" | bc)
  28.     AMOUNT=$(echo "scale=10; $AMOUNT+$INTERESTLOAN" | bc)
  29.     printf "Year ${i} %8.2f " $INTERESTLOAN; printf " %14.2f\n" $AMOUNT;
  30. done
  31.  
  32. printf "Final amount: %1.2f bucks.\n" $AMOUNT

For example:

CODE:
  1. you@yourmachine ~ $ loancalc 3000 3.5 5
  2. Investment: 3000 bucks at a rate of 3.5% for 5 years.
  3.           Loan            Total
  4. Year 1   105.00         3105.00
  5. Year 2   108.68         3213.68
  6. Year 3   112.48         3326.15
  7. Year 4   116.42         3442.57
  8. Year 5   120.49         3563.06
  9. Final amount: 3563.06 bucks.

January 12th, 2008 at 6:23 pm

Looks like document root, but is in a subfolder

Are you using Google Sitemaps, and does your website have very many pages? Then you will usually have a sitemap index file along with a number of sitemap files in your document root. Now, you might want to tidy up and move those sitemap files to a subfolder -- but that doesn't work, as Google requires the sitemap files to be in the document root. What to do? You can use mod_rewrite to solve this:

Create the directory gg_sitemaps and move your sitemaps index as well as all your sitemap files there.

Add the following line to the file .htaccess in your document root (if it doesn't exists, create it):

CODE:
  1. RewriteRule ^(sitemap.*)$ /gg_sitemaps/$1 [L]

(Note: This assumes that your sitemap index and the sitemaps files start with the string sitemap, e.g. your sitemap index file it could be sitemaps.xml, while the sitemaps files could be sitemap0.xml, sitemap1.xml and so on.)

Now your sitemaps are out of the document root, but Google will still see them as if they were in there.

By the way, this also works for the Google sitemaps verification files: If you want to verify your site in Google Webmasters, you need to upload a file to your document root. (You could also add a meta tag, but that's not so good.) Adding a single file isn't a problem, but if you want to allow different people to manage this domain in different Google Webmaster accounts, or if you have multiple domains in the same document root, you will need to upload more than one file. Again, we can solve this with some mod_rewrite magic:

Create the directory gg_verify and move all your verification files there.

Add another line to the file .htaccess in your document root:

CODE:
  1. RewriteRule (^google.*$) /gg_verify/$1 [L]

Again, Google will think, the respective file is in the document root, while actually it is in the designated subfolder.

December 22nd, 2007 at 3:32 pm

Optimize your CSS

CSS files are the most downloaded parts of a website, as they are usually loaded with every webpage. Also, CSS files usually contain a lot of, from a technical point of view, unnesseccery characters. Therefore it is a good idea to optimize your CSS file(s) for faster loading. A good tool to remove pretty much all spare characters is the CSS compressor, which can reduce the file size of your CSS up to 25%. Of course, you should always keep a "source" version for modifications.

That tool of course is not able to optimize your CSS semantically, this must be done by you. Semantic optimization means that you should scrutinize your CSS file for redundancy. Do you possibly define background-image, background-position and background-repeat separately? Merge them into a single statement like background: #fff url(image.png) top left; -- you need the first ones only for overwriting a single other property. (That's why they are called Cascading Style Sheets.) Same goes for margin, border and padding with their -top, -right, -bottom, -left: Use them only for overwriting. In all other cases, merge them into one statement: For example, margin: 5px 2px; will assign a margin of 5px to the top and bottom, and 2px to the left and right. margin: 5px 2px 3px; will assign a margin of 5px to the top, 2px to the left and right, and 3px to the bottom. And margin: 5px 2px 3px 4px; will assign a margin of 5px to the top, 2px to the right, 3px to the bottom, and 4px to the left.

Other possibilities: Consider using relative paths to images instead of absolute ones. Remove unneeded definitions (or comment them out before sending them through the compressor). Combine multiple selectors in a single one (e.g. if you have #content_left a, #content_right a it could be possible to use #content a instead).

Optimizing your CSS by compression and good semantical style will shrink your CSS by 30-60%. This will make the loading of a webpage from your website noticeably faster, even with a fast connection.

December 19th, 2007 at 10:14 pm

Codelog WordPress theme released

I'm happy to announce the public release of the Codelog theme 0.1 for WordPress. The Codelog theme is a stylish and very lightweight two-column theme. If plain blogging is what you do, this theme is for you. The only features of this theme are fast loading, clean code and the elegant look. Ok, it also comes with multi-language support (German translation already included). But that's it, less is more!

If you like the Codelog theme, download it and give your blog a new look!

December 18th, 2007 at 10:07 am

Improve loading speed of webpages by compressing HTML

Here's a simple HTML "compressor" in PHP, which will reduce the size of HTML served to the client by 10 to 20 percent, depending on your indentation style and commenting. If many of your readers have lousy bandwidth, the slight overhead of this method is worth it.

PHP:
  1. <?php
  2.     function compress($content)
  3.     {
  4.         $content = preg_replace('/[\n\t\s]+/s', ' ', $content);
  5.         $content = preg_replace('/<!--.*?-->/s', '', $content);
  6.         return $content;
  7.     }
  8.  
  9.     ob_start();
  10.     require "/var/www/htdocs/somefile.php";
  11.     $content = ob_get_contents();
  12.     ob_end_clean();
  13.  
  14.     echo compress($content);
  15. ?>

By the way, if you have a rather hungry dynamic application (e.g. WordPress with certain plugins) on a rather weak server, consider using a caching solution like 1 Blog Cacher, so you don't have to regenerate the pages everytime somebody retrieves them. And, of course, consider using output gzip compression -- be it via webserver modules such as mod_gzip/mod_deflate or based on your web application.

December 17th, 2007 at 4:31 pm

Copying is expensive, moving is cheap

When you replace a comprehensive file tree via FTP, you will realize that it takes some time to do all the uploading. If your upload is going to replace old content, then one would usually first delete the old content, then upload the new one. (It is not a good idea to let the FTP client overwrite old contents, unless one knows exactly how the client behaves. For example, some clients merge existing trees, not deleting old files that are expunged rather than replaced, thus potentially raising security problems.)

However, the procedure of first deleting and then copying can leave your site naked or uncomplete for a couple of endless minutes. In the worst case, a user retrieves a page from your incomplete site and causes a database corruption or messes up the internal settings (this is not too unlikely with CMS applications). Therefore, the better way is to first upload the new content under a different name and then rename folders.

For example, if your web documents are in /var/www/docroot/, you would usually do the following: You delete everything in that directory and then upload the new content -- which has the above mentioned side effects. Instead, you should better do the following: Upload all new content to /var/www/docroot_new/, rename /var/www/docroot/ to /var/www/docroot_old/, finally rename /var/www/docroot_new/ to /var/www/docroot/. Afterwards, you can delete /var/www/docroot_old/. Renaming is very fast, as only the base directory's name has to be changed in the filesystem.

With this method, your website will only be naked for a few seconds, and there won't be an incomplete installation at any time.