Determining linux distribution

words by Brian Racer

I work with a wide variety of client server deployments, and sometimes it isn’t obvious(via uname) what distribution and version a server is running. Here is a quick list of common files which contain that information:

Debian          /etc/debian_release, /etc/debian_version,
Fedora          /etc/fedora-release
Gentoo          /etc/gentoo-release
Mandrake        /etc/mandrake-release
Novell SUSE     /etc/SUSE-release
Red Hat         /etc/redhat-release, /etc/redhat_version
Slackware       /etc/slackware-release, /etc/slackware-version
Solaris/Sparc   /etc/release
Sun JDS         /etc/sun-release
Ubuntu          /etc/lsb-release
UnitedLinux     /etc/UnitedLinux-release
Yellow dog      /etc/yellowdog-release

Ubuntu Tip: Force new windows to start centered on the desktop

words by Brian Racer

I use a pretty generic Gnome + Compiz desktop setup in Ubuntu, but one thing that really irks me is my applications always seem to start snapped to a corner. What I really want is for them to open centered on my desktop. You can achieve this by doing a little registry modification(I’m pretty sure there is a nice GUI app to adjust these settings, but I don’t believe it is installed by default).

Press Alt+F2 and enter gconf-config. This will open up Gnome’s registry editor.

Set the following two values:
Key: /apps/metacity/general/focus_new_windows Value: smart
Key: /apps/compiz/plugins/place/screen0/options/mode Value: 1

Now your applications should start up nice and centered :)


Using a sane user-agent for Ubuntu’s Firefox 3.5 – Shiretoko

words by Brian Racer

Ubuntu’s current release version of Firefox 3.5 is named Shiretoko and sends a user-agent of Shiretoko/3.5 rather than Firefox/3.5. This broke a number of sites I use that rely on browser sniffing such as Facebook Chat and DailyMotion. There are two ways to adjust this behavior:

1) Type about:config in the address bar. Search for ‘general.useragent.extra.firefox’. Double click “Shiretoko/3.5″ replace it with “Firefox/3.5″

2) Use the User Agent Switcher plugin. This I prefer this option as it also lets me set IE user agents so I can use a few sites that think they require IE, and also set iPhone header’s for development.


Subversion repository creation script

words by Brian Racer

Here is a simple script I use to create subversion repositories and setup common hook scripts. This assumes you are making svn available through an HTTPS/Apache/DAV.

My directory svn structure looks like the following:

$ tree -L 2 /home/svn
 
/home/svn
|-- conf
|   |-- permissions.conf
|   `-- mailer.conf
|-- repos
|   |-- repo1
|   |-- repo2
|   `-- repo3 
`-- scripts
    |-- post-commit
    |-- pre-commit
    `-- svncreate.sh

There are 3 main directories:

repos – This is where the actual subversion repositories are stored
scripts – Various scripts, including the following creation script, and also various hook scripts that repositories can symlink to
conf – Various configuration files that might contain mailer configuration or repository permissions(both outside the scope of this article)

The following script will create the new repository, set proper user and permissions, symlink common pre and pos commit scripts, and then make the initial import that contains the trunk/branches/tags structure.

#!/bin/bash
 
REPOS_URL=https://svn.example.com
REPOS_PATH=/home/svn/repos
SCRIPTS_PATH=/home/svn/scripts
APACHE_USER=www-data
 
SVNADMIN=`which svnadmin`
EXPECTED_ARGS=1
E_BADARGS=65
REPO=$1
 
if [ $# -ne $EXPECTED_ARGS ]
then
  echo "Usage: $0 reponame"
  exit $E_BADARGS
fi
 
$SVNADMIN create --fs-type fsfs $REPOS_PATH/$REPO
 
rm -rf /tmp/subversion-layout/
mkdir -pv /tmp/subversion-layout/{trunk,branches,tags}
 
ln -s $SCRIPTS_PATH/pre-commit $REPOS_PATH/$1/hooks/pre-commit
ln -s $SCRIPTS_PATH/post-commit $REPOS_PATH/$1/hooks/post-commit
 
chown $APACHE_USER:$APACHE_USER -R $REPOS_PATH/$1
chmod -R 2775 $REPOS_PATH/$1
 
svn import -m "Initial Import" /tmp/subversion-layout/ $REPOS_URL/$REPO
rm -rf /tmp/subversion-layout/

As you root you just run it as /home/svn/scripts/svncreate.sh reponame


Useful PHP Subversion Commit Hook

words by Brian Racer

Here is a subversion pre-commit hook script we use on PHP projects to make sure the developer making the commit is providing a meaningful description, and then PHP lint is run on each PHP script to make sure it will compile correctly.

#!/bin/bash
 
REPOS="$1"
TXN="$2"
 
PHP="/usr/bin/php"
SVNLOOK="/usr/bin/svnlook"
AWK="/usr/bin/awk"
GREP="/bin/egrep"
SED="/bin/sed"
 
CHANGED=`$SVNLOOK changed -t "$TXN" "$REPOS" | $AWK '{print $2}' | $GREP \\.php$`
 
for FILE in $CHANGED
do
    MESSAGE=`$SVNLOOK cat -t "$TXN" "$REPOS" "$FILE" | $PHP -l`
    if [ $? -ne 0 ]
    then
        echo 1>&2
        echo "***********************************" 1>&2
        echo "PHP error in: $FILE:" 1>&2
        echo `echo "$MESSAGE" | $SED "s| -| $FILE|g"` 1>&2
        echo "***********************************" 1>&2
        exit 1
    fi
done
 
# Make sure that the log message contains some text.
SVNLOOKOK=1
SVNLOOK=/usr/bin/svnlook
$SVNLOOK log -t "$TXN" "$REPOS" | \
   grep "[a-zA-Z0-9]" > /dev/null || SVNLOOKOK=0
if [ $SVNLOOKOK = 0 ]; then
  echo Empty log messages are not allowed. Please provide a proper log message. 1>&2
  exit 1
fi
 
# Make sure text might be meaningful
LOGMSGLEN=$($SVNLOOK log -t "$TXN" "$REPOS" | grep [a-zA-Z0-9] | wc -c)
if [ "$LOGMSGLEN" -lt 6 ]; then
  echo -e "Please provide a meaningful comment when committing changes." 1>&2
  exit 1
fi
 
# All checks passed, so allow the commit.
exit 0

Useful Linux Trick: cron @reboot

words by Brian Racer

There are various ways to make sure something is run at system startup – Redhat has /etc/rc.local script, and it and many others have /etc/init.d/* scripts – but many times you might not have access to those files or creating init scripts might be overkill for your needs.

People are always amazed when I tell them they can achieve this basic functionality by using cron. Many of our websites use Sphinx, the excellent full text indexer, to allow site searches. Should the server ever reboot, we need to make multiple search daemons start back up. Take the following line from a crontab:

crontab -l
 
@reboot /usr/local/bin/searchd --config ~/conf/sphinx.conf

This will make sure the searchd daemon starts on bootup.

Also there are a few other shortcuts you can use:

@yearly        Run once a year, "0 0 1 1 *".
@annually      (same as @yearly)
@monthly       Run once a month, "0 0 1 * *".
@weekly        Run once a week, "0 0 * * 0".
@daily         Run once a day, "0 0 * * *".
@midnight      (same as @daily)
@hourly        Run once an hour, "0 * * * *".

See man 5 cron for more information.

(And to be pedantic, @reboot is run when cron is started or restarted, not necessarily the OS itself. So /etc/init.d/cron restart would trigger that line to be run. You may want to keep that in mind.)


How to fix Munin’s MySQL Graph on cPanel

words by Brian Racer

We have a few cPanel servers deployed and to visually monitor performance we use the Munin monitoring tool. We were having issues where the MySQL graphs would stop updating. The bug has to do with one of the perl libraries the script uses, which causes the MySQL plugin to have problems location the mysqladmin program.

To fix these, create or edit the following file:

vi /etc/munin/plugin-conf.d/cpanel.conf

It should contain the following:

[mysql*]
user root
group wheel
env.mysqladmin /usr/bin/mysqladmin
env.mysqlopts --defaults-extra-file=/root/.my.cnf

This would load the username and password from root’s mysql config. If that file doesn’t exist you can create it:

sudo vi /root/.my.cnf
[client]
user="root"
pass="secret!password"

Now just restart Munin, wait a a little bit, and the graphs should start populating again!

sudo /etc/init.d/munin-node restart

Installing fonts in Ubuntu

words by Brian Racer

Recently I wanted to add some Mac-style fonts to my Ubuntu system. Although it requires slightly more work than just dragging the font files into a folder, it is still quite simple.

If you have full root or sudo access and you would like the font to be shared with all users of the system, you may want to put the files in /usr/local/share/fonts/truetype. An easy way to navigate to that location with root privileges is to press Alt+F2 and type:

gksudo nautilus /usr/local/share/fonts/truetype

You can then create a new directory and place your fonts into it.

Alternatively you may place the fonts in a directory inside your home folder. The files get placed in a hidden directory called .fonts. You may have to create this directory. Only you will be able to access these fonts.

mkdir ~/.fonts

Whichever you choose, you will need to reset the font cache . You can reset the cache with the following command:

sudo fc-cache -f -v

And for anyone interested, here are a nice set of free MacOS font alternatives to use in Windows or Linux

Mac-Fonts – this includes AppleGaramond, Aquabase, LITHOGRL, Lucida Grande, Lucida Mac, Lucon, MacGrand. I downloaded these from this site, however you need to go through multiple pages of referral sign-ups to access the file.

Monaco Linux – This is the font I use in vim, it looks great.

Inconsolata – This is a variation of Luc(as) de Groot’s Consolas font, which is another nice mono-spaced programming font featured in Windows Vista. Read more about it at the authors webpage.

You may also want to install the Miscrosoft Web Fonts(msttcorefonts):

sudo aptitude install msttcorefonts

chkdsk and Grub

words by Brian Racer

Recently I used GParted to resize an NTFS disk to dual boot Ubuntu and Windows XP. I finished the Ubuntu installation and everything seemed to be working fine until I tried to boot back into XP. Windows reported there might be disk corruption, ran chkdsk, and chkdsk ended up freezing. I rebooted again and saw that the grub bootloader was now also freezing. Delightful. Although I didn’t think chkdsk modified the MBR, upon further research in some cases it does(when run with the /r switch) and in this case ends up corrupting the MBR. To fix this issue you can perform the following:

Boot with an Ubuntu Live CD and open up a terminal.

sudo grub
 
grub> find /boot/grub/stage1

Note the hdx number and partition number to it’s right. Now type the following commands into the grub prompt:

grub> root (hdx, y)
 
grub> setup (hdx)
 
grub> quit

Note whitespace is important here. Now you can reboot. When Windows asks to run chkdsk hit a key to cancel. Once in Windows, open a command prompt and type:

chkntfs /c c:

This will schedule a disk check on reboot that will not alter the MBR. Reboot and allow the disk check to complete. It may automatically reboot your system again, but once that is finished both OS’s should boot fine from now on.


SVN autobackup restore

words by Brian Racer

I have been using Doug Hellman’s useful svnautobackup script for our subversion backups. I think it is a pretty useful script, but it only focuses on backups and not restoration.

During a recent server upgrade I needed to restore a large amount of repositories from our dumpfiles. I made the following shell script in php that will loop through all of the backup dumps and restore them. There is a similar tool that uses ruby, but it can only restore one repository and I do not know enough ruby to modify it :)

#!/usr/bin/php -q
<?php 
// edit this
$repo_dir = '/svn/';
$backup_dir = '/home/backup/svn/';
 
// don't edit this
foreach(new DirectoryIterator($backup_dir) as $file)
{ 
  if(isDir() && !$file->isDot())
  {
    // get files
    $dumpfiles = glob($backup_dir.$file.'/dumpfile*.bzip2');
    // sort them
    natsort($dumpfiles);
 
    // create the repo if not exists
    if(!is_dir($repo_dir.$file))
    {
      $cmd =  "svnadmin create {$repo_dir}{$file}";
      system(escapeshellcmd($cmd));
    }
 
    // restore dump files
    foreach($dumpfiles as $dumpfile)
    {
      $cmd = "bzcat {$dumpfile} | svnadmin load {$repo_dir}{$file}";
      system(escapeshellcmd($cmd));
    }
  }
}

For reference, here is the script that runs nightly though cron

#!/bin/bash
 
files=`ls /svn`
for file in $files
do
  if [ -d /svn/$file ]
  then
    mkdir -p $file
    /home/backup/scripts/svnautobackup/svnbackup.sh -v -i 100 --history-file /home/backup/svn/$file-hist --out-dir /home/backup/svn/$file /svn/$file
  fi
done