Saturday 15 December 2012

xmllint : Command line XML parser and formatter

So you were given a XML file that came straight out of a windows system with no indentation and incorrect line endings. The simplest way out is xmllint.

The program does much more than formatting its input. Additional functions include: parsing, verifying, dropping empty nodes and many more.

Installing it on CentOS, Fedora and like, is performed via :

sudo yum -y install libxml2

openSUSE users may use yast or type something like:

zypper install libxml2

... while Debian and Ubuntu users will have to go like:

sudo apt-get install libxml2-utils

after you have it on your system, the easy way to fix the badly formated xml file would be :

xmllint --format badlyFormated.xml > wellFormated.xml

Thursday 13 December 2012

Gnome2 Default Keyring location

Just a quick note for me -- and anyone else out there -- The location of the keyring in gnome2 is in ~/gnome2/keyrings. And if you forget your keyring password then the easy way to start all over with a new keyring is:

rm ~/.gnome2/keyrings/default.keyring 

Thursday 6 December 2012

Using a raspberrypi as a file server

The idea came to me from a friend. I wanted to install a small network storage system to use merely as a file exchange repository at the office and I was looking to buy some kind of Ethernet disk, when he said to me why don't you do it with a raspberry and a USB flash drive?. The thought was intriguing -- to say the least, so here I am with all the little details:

I am not going to go through the entire process of downloading and preparing the raspberry SD card from the Raspberry Pi Downloads page. The cool thing with raspberry is that once you get it running for the first time, you get a real Debian Linux that does all you expect a descent OS to do.

A pleasant surprise with the raspberry image was that the default set-up registered itself to my dynamic DNS and I was able to log into raspberrypi the moment I plugged it into my LAN without touching a thing.

The first thing that I needed to do was change the hostname of the device. That way there would be no name conflicts when I add a fresh one for the next God knows what project that will come up...

Changing the host name is as simple as editing the file /etc/hostname, changing the single line with the word raspeberrypi to xena (Yes i wanted an ... epic name) and then rebooting. The DNS picked up the name change and logging into xina was as easy as typing ssh -l pi xena -X. (An even easier way to accomplish the task is to use raspi-config. Check the advanced options menu)

Next thing would be a plug the USB disk and make sure it gets mounted every time the system boots. I suppose that the proper way to make this work would be to tamper with /etc/fstab. I chose to do it a bit differently and ended up creating a file containing the last things that the system should do right after booting.

First create a mount point and mount the USB disk. In my case, I created /mnt/SFTP-Data and tested it with a:
mount /dev/sda1 /mnt/STFP-Data

The idea with executing commands right after boot is that we need to create a file, let's call it system-startup.sh that contains the above mount command, plua the necessary LSB comments, place it in /etc/init.d, make it executable and then run insserv to add this command as the last default runlevel action. The format of the comments section is :

#! /bin/sh
### BEGIN INIT INFO
# Provides: system-start.sh
# Required-Start: $remote_fs $syslog
# Required-Stop: $remote_fs $syslog
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: Start up script after boot
# Description: Enable service provided by daemon.
### END INIT INFO
mount /dev/sda1 /mnt/STFP-Data

...and the actual command to make this work is:
sudo insserv /etc/init.d/system-startup.sh

Finally, it time to install and configure Samba. The Debian Administrator's handbook says it all. Just remember that raspebrry-pi only has 256MB of actual RAM so keep away from web configuration tools like swat and go with the debconf and manually editing the the smb.conf file option.

After Samba is up and running edit the file /etc/samba/smb.conf and fix the basic staff like work group name and server description. Mine looks like this:

[global]
## Browsing/Identification ###

# Change this to the workgroup/NT-domain name your Samba server will part of
   workgroup = aryballos

# server string is the equivalent of the NT Description field
   server string = %h Raspberry-PI Server

# Windows Internet Name Serving Support Section:
# WINS Support - Tells the NMBD component of Samba to enable its WINS Server
  wins support = yes

In order to create a read write share that anyone can use, we need to create a new user that has read/write access to the disk and then force that use and group everytime that someone accesses data through the Samba share.

pi@xena /etc/samba $ groupadd microsoft
pi@xena /etc/samba $ useradd -c "Samba user" -m -d /mnt/mdz-disk/shared/ -g microsoft bill

There are two things here. First Bill does not have a password so he can not log in interactively. Second Bill's home is the directory on the disk where I want everybody to have full read/write access. Telling this to the Samba server requires that the following section be placed at the end of the smb.comf file ...

[public]
   comment = Public data in the USB drive for our work-group
   read only = no
   path = /mnt//mnt/STFP-Data/public
   guest ok = yes
   force user = bill
   force group = microsoft

... the directory is made and permissions are set

pi@xena /mnt/SFTP-Data $ sudo mkdir public
pi@xena /mnt/SFTP-Data $ sudo chown bill.microsoft public/

... and finally the samba service is restarted...

pi@xena /etc/samba $ sudo service samba restart
[ ok ] Stopping Samba daemons: nmbd smbd.
[ ok ] Starting Samba daemons: nmbd smbd.
pi@xena /etc/samba $ 

Thursday 18 October 2012

PHP: Workaround for the mailbox is empty imap error

If you are in the process of learning how to use the PHP imap* family of functions in order to manage a remote mailbox, here is a little hint to let you get away with the first annoying error warning you are likely to run into.

So here is how the story goes. You open am empty mailbox. Do something with it and then when you close it you get a PHP warning like :

Notice (8): Unknown: Mailbox is empty (errflg=1) [Unknown, line ??]

I have read many ways for handling this. The bottom line is that this is only a warning and due to the nature of the PHP imap functions, it will eventually be flashed when you call imap_close() or when your script exits. Fortunately each call to imap_errors() flashes the internal error log, so a simple way to avoid the entire hassle would be to code something like ...

    function connect()
    {
        $mailBoxx = @imap_open($this->server, $this->username, $this->password);

        if ($mailBox) {
            // call this to avoid the mailbox is empty error message
            if (imap_num_msg($mailBox) == 0)
                $errors = imap_errors();
            return TRUE;
        }
        // imap_errors() will contain the list of real errors
        return FALSE;
    }

Sunday 15 April 2012

bash scrupt to copy all songs in an m3u list into a folder

This is not the first time I thought about it and it took a lot of digging and googling in order to get the right command line to do it. So, all credit goes to the thefekete.net who is the initial poster and my only contribution is turning the initial command line into a script.

#!/bin/bash

# ------------------------------------------------------------------------------------
# Copy all files from a playlist to a dest folder
# ------------------------------------------------------------------------------------
if [ "$#" != 2 ]; then
 echo usage $0 playlist.m3u dest-dir
 exit 1
fi

if [ ! -d "$2" ]; then
    mkdir $2
    echo Creating directory `pwd`"/"$2
fi

if [ -z "$1" ]; then
 echo  $1 is not a valid file
 exit 2
fi

cat "$1" | grep -v '#' | while read i; do cp "${i}" "$2" ; echo "${i}"; done

Thank you the thefekete

Friday 17 February 2012

CakePHP: Loosing translated texts

This one drove me crazy for the last couple of hours, so I thought I better share it right away.

I have a bilingual CakePHP application that displays content messages translated from English to Greek. To achieve this I wrap all my English texts inside cake's __() function and then run the cake i18n extract script in order to assemble a .pot file. Finally, I translate my original messages to Greek using the POEdit program to create and manage the necessary translations. Everything seemed to work well: Each time I added new strings, I would execute the cake i18n extract script, then open POEdit, update my .po catalogue from the generated .pot file and translate only the new texts.

Except for today. I was asked to asked to add a few more messages, so I followed the standard procedure. but after I updated both my .po and .mo files, the messages on the web page remained in English despite my ... sincere efforts and honest desire to see them in Greek.

It took me a while to figure this out: The solution was as simple as to delete all files from the APP/tmp/cache/persistent directory.

Wednesday 15 February 2012

Command line to mount USB flash drives in Linux

The subject is not new and nothing beats the device notifier icon in KDE asking you what to do with a newly inserted flash drive. This post however, is meant to serve only as a note to me, regarding the safest procedure of setting up and mounting a flash drive from the command line.

The current state of affairs is like this: We have a 32GB flash drive that is to be plugged in to a remote LAMP server where we want to place daily database backups. We only have access to the server via ssh so in order to automate the procedure, we are going to initially format the drive using the ext4 file system and then label it so that we won't care about the actual SCSI port that he device will use in the future.

Initial formatting and labelling

After the device has been plugged in for the first time, the easiest way to determine the actual SCSI port is to find the lines containing the word SCSI in the kernel displayed messages. This is as easy as :

[root@skymnos ~]# dmesg | grep SCSI
SCSI subsystem initialized
Block layer SCSI generic (bsg) driver version 0.4 loaded (major 252)
scsi0 : SCSI emulation for USB Mass Storage devices
sd 1:0:0:0: [sdb] Attached SCSI disk
sd 0:0:0:0: [sda] Attached SCSI removable disk
[root@skymnos ~]# 

Alternatively we could use the udisks --monitor command before pluggin in the device. This would produce output like the following:

[root@skymnos-wifi ~]# udisks --monitor
Monitoring activity from the disks daemon. Press Ctrl+C to cancel.
added:     /org/freedesktop/UDisks/devices/sde
added:     /org/freedesktop/UDisks/devices/sde1
So now we know that out flush drive is located under /dev/sda and the partition that we are going to work with is /dev/sda1. To format it we will use the mkfs.ext4 command with the -L option to specify a label for our file-system.

[root@skymnos ~]# mkfs.ext4 -L dbBackups /dev/sda1 
mke2fs 1.41.12 (17-May-2010)
Filesystem label=dbBackups
OS type: Linux
Block size=4096 (log=2)
Fragment size=4096 (log=2)
Stride=0 blocks, Stripe width=0 blocks
1949696 inodes, 7790336 blocks
389516 blocks (5.00%) reserved for the super user
First data block=0
Maximum filesystem blocks=0
238 block groups
32768 blocks per group, 32768 fragments per group
8192 inodes per group
Superblock backups stored on blocks: 
        32768, 98304, 163840, 229376, 294912, 819200, 884736, 1605632, 2654208, 
        4096000

Writing inode tables: done                            
Creating journal (32768 blocks): done
Writing superblocks and filesystem accounting information: done

This filesystem will be automatically checked every 39 mounts or
180 days, whichever comes first.  Use tune2fs -c or -i to override.
[root@skymnos ~]# 

Mounting

The -L dbBackups switch that we previously used in order to format the drive, tells mkfs to create a file system with a label of dbBackups. Now if you plug this to a system running a decent window manager with udev, this would be automatically mounted under /media/dbBackups. We are going the mimic the same behaviour.

[root@skymnos ~]# mkdir /media/dbBackups/
[root@skymnos ~]# mount -L dbBackups /media/dbBackups/
[root@skymnos ~]# df -h /media/dbBackups
Filesystem            Size  Used Avail Use% Mounted on
/dev/sda1              30G  172M   28G   1% /media/dbBackups
[root@skymnos ~]# 

A few more details: Since this is going to be backup storage disk, our lives will become much easier if we create a directory with full read-write permissions inside the drive like this:

[root@skymnos ~]# mkdir /media/dbBackups/data
[root@skymnos ~]# chmod o+w /media/dbBackups/data/
[root@skymnos ~]# 

So to sum it up. Mounting the flash drive on the remote server from my office machine requires -- well, apart from having someone plug the drive into a USB port doing something like this:

[thanassis@skymnos ~]$ sudo mount -L dbBackups /media/dbBackups/
[thanassis@skymnos-wifi ~]$ df -h
Filesystem            Size  Used Avail Use% Mounted on
/dev/sda1              68G  5.1G   62G   8% /
tmpfs                1006M   88K 1006M   1% /dev/shm
/dev/sdb1              30G  172M   28G   1% /media/dbBackups
[thanassis@skymnos ~]$ 

And what if I wanted the system to attempt to mount the drive each time it boots? In that case all I would have to do is add a line like /bin/mount -L dbBackups /media/dbBackups/ in the /etc/rc.d/rc.local file