Monitor a directory or file for changes on Linux using inotify

Many times you may need to watch or monitor a file or directory for changes. When you look around for how to do this you will see MANY people suggesting that you use lsof and that does work very well. Another solution is the use of incron. This solution works far better for the cases where I have needed to know more of what is going on with a file or directory.

Installing incron is simple. On Debian and Ubuntu a simple

apt-get install incron

will get it done. Once it is installed you can add your users who will be allowed to use incron to the /etc/incron/incron.allow file. Thats it your user should now be able to use incrontab -e. For my examples I will be using root, and all the scripts I make will be for root only.

Next its time to talk a little about incron. It will work sort of the same as a regular crontab except that it is event driven and not time scheduled, so the syntax of the file will be a bit different. It is in the format:

<path> <mask> <command>

Where <path> is an absolute path on the file system that will be monitored. <mask> is an event symbol. For a full list of event symbols see man 5 incrontab. <command> is the command that will run when the event in the mask section happens. For this example I am going to use the IN_ALL_EVENTS mask, and show you a simple shell script you can use to just log some basic info about whats going on in our watched directory.

Lets make our shell script. Using your favorite text editor create the file /usr/local/sbin/incron_logger.sh In that file add the following:

#!/bin/bash
logfile=/var/log/inotify_backup_changes_test.log
path=$1
file=$2
event=$3
datetime=`date --rfc-3339=ns`
echo "${datetime} Change made in path: " ${path} >> ${logfile}
echo "${datetime} Change made to file: " ${file} >> ${logfile}
echo "${datetime} Change made due to event: " ${event} >> ${logfile}
echo "${datetime} End" >> ${logfile}

Save this file and chmod 700 the file. Next still as root type:

incrontab -e

The first thing we add is the path, in my case I want to monitor /tmp/watch_me This is just a directory in /tmp that I have created for the purpose of this demo. Next I will add the IN_ALL_EVENTS mask, and finally the command /usr/local/sbin/incron_logger.sh and then some args to call the script with. My completed incrontab entry looks as follows:

/tmp/watch_me IN_ALL_EVENTS /usr/local/sbin/incron_logger.sh $@ $# $%

The symbols added after the command are for the path,event related file name, and finally the event flag that triggered the command to run. Lets save this entry and go create some files and see what happens.

First I will create a file:
touch /tmp/watch_me/testfile1
Now lets take a look at the log:
cat /var/log/inotify_backup_changes_test.log
You should now see:

2011-02-25 10:05:18.450733000-06:00 Change made in path: /tmp/watch_me
2011-02-25 10:05:18.450733000-06:00 Change made to file: testfile1
2011-02-25 10:05:18.450733000-06:00 Change made due to event: IN_ATTRIB
2011-02-25 10:05:18.450733000-06:00 End
2011-02-25 10:05:18.454378794-06:00 Change made in path: /tmp/watch_me
2011-02-25 10:05:18.454378794-06:00 Change made to file: testfile1
2011-02-25 10:05:18.454378794-06:00 Change made due to event: IN_OPEN
2011-02-25 10:05:18.454378794-06:00 End
2011-02-25 10:05:18.456283635-06:00 Change made in path: /tmp/watch_me
2011-02-25 10:05:18.456283635-06:00 Change made to file: testfile1
2011-02-25 10:05:18.456283635-06:00 Change made due to event: IN_CREATE
2011-02-25 10:05:18.456283635-06:00 End
2011-02-25 10:05:18.457849952-06:00 Change made in path: /tmp/watch_me
2011-02-25 10:05:18.457849952-06:00 Change made to file: testfile1
2011-02-25 10:05:18.457849952-06:00 Change made due to event: IN_CLOSE_WRITE
2011-02-25 10:05:18.457849952-06:00 End

As you can see from this log we know when the file is opened for writing to make it, and then we know as soon as its been closed. This can be handy for many things, Ill let your imagination run wild on what you can do with this. If you have any questions or comments please feel free to ask and I will do my best to answer them.

hylafax+debian or Ubuntu = No font metric information found

We were recently going through a server migration. Moving from FreeBSD to Ubuntu Linux. One of the apps required to be moved was hylafax. On Debian and Ubuntu there is a hylafax-client package that provides sendfax which is really what we needed. I installed the package and we tested our app but all we got was failure.. We were greeted with the following:

textfmt: No font metric information found for “Courier-Bold”.
Usage: textfmt [-1] [-2] [-B] [-c] [-D] [-f fontname] [-F fontdir(s)] [-m N] [-o #] [-p #] [-r] [-U] [-Ml=#,r=#,t=#,b=#] [-V #] files… >out.ps
Default options: -f Courier -1 -p 11bp -o 0
Error converting document; command was “textfmt -B -f Courier-Bold -Ml=0.4in -p 11 -s default >’/tmp//sndfaxUSNM632′ <'/etc/issue.net'"

It took a a little bit of poking and prodding to figure this one out but to fix it I had to edit the following file:

/etc/hylafax/hyla.conf

In this file there is a setting for the FontMap. I appended /var/lib/defoma/gs.d/dirs/fonts. You will also need the gsfonts package but that is a listed as a dependency so you should already have it installed.

Bria 3 with Asterisk hanging up after 30 seconds of hold

Do you use Asterisk? Do you also use Bria with it? If so in newer 3.x versions of Bria you may find that callers are being hung up on after 10-30 seconds of being placed on hold. To fix this problem simply Click on the Softphone toolbar, then look for preferences, then to Advance. Next uncheck the Enable Inactivity Timers. The default value for this was 300 seconds. I think that was a typo and meant 300 centiseconds because if when we would adjust this value the time out would increase or decrease. 500 let the caller hold for about 50 seconds.

Building Fluxbox GIT on Ubuntu 10 and adding it to GDM

Many of you may recall from the past that this site used to be ALL about FluxBox my focus now is more on general Linux usage. I do however still use Fluxbox. Something I thought I would talk about is how to add Fluxbox to GDM and what it takes to build Fluxbox GIT on Ubuntu. This process should also work on Debian as well.

The first thing you will need to do is install some dependencies. The best way to do that is using the following commands:
apt-get install build-essential
Next you need to install some stuff specific to Fluxbox, the easy way to do that is like this:
apt-get build-dep fluxbox
Next you need to either grab a source tarball of git, or install git using the following command:
apt-get install git

You should now have everything you need to build the latest version of Fluxbox on your machine. Lets pull the code and build it. As a normal user and with out using sudo:
git clone git://git.fluxbox.org/fluxbox.git && cd fluxbox && ./autogen.sh
Once this completes successfully it will be time to configure the build options. Since you may be doing this just to test out the latest version and may still want to have the primary version installed via apt-get Im going to suggest configuring with the following options:
./configure --prefix=/usr/local && make && sudo make install
This will place the files that fluxbox git version installs into the /usr/local directory. Now fluxbox is installed and all you need to do is manually create a fluxbox.desktop file so that GDM will know about.

To make the fluxbox.desktop all you need to do is open your favorite text editor and create a file that looks like this:

[Desktop Entry]
Encoding=UTF-8
Name=Fluxbox-git
Comment=Highly configurable low resource X11 Window Manager
Exec=/usr/local/bin/startfluxbox
Terminal=False
TryExec=/usr/local/bin/startfluxbox
Type=Application

Next save this file in /usr/share/xsessions/ and name it fluxbox-git.desktop

You may need to restart X for the Fluxbox-git entry to show up for you to select, but thats it!! You should now have Ubuntu with Fluxbox Git installed. Enjoy!!

Flip Video UltraHD — on Ubuntu Linux

I mentioned in an earlier post that I recently acquired a new Flip UltraHD Video Camera. What I didnt mention is that it works like a champ on my Ubuntu 10.04 LTS desktop. All I had to do was turn on the flip video, and then plug it in. Next I waited a few moments and then it was mounted as a mass storage device. I was able to import he videos with f-spot, and watch them using VLC. This product just went from cool to kick ass!

Ubuntu Linux CUPS server with legeacy LPD support using cups-lpd

We recently upgraded a few of our servers. Some of them are still stuck on older FreeBSD and we can not upgrade them for a while longer. These older systems need to be able to print to printers that are shared on Windows desktops. One way of doing this is to setup CUPS. Some of the servers I replaced were replaced with the latest Ubuntu Server. I picked one of them and setup Samba. Next I setup CUPS on it. At this point I was really hoping that the lpd stuff would just start working.. That was and is not the case. A tad more configuration is required to get the lpd support. To get the lpd support you need to install an inetd server. I tried xinetd but never could get it working, so I opted to try openbsd-inetd. This worked perfect. To get the cups-lpd working I had to edit /etc/inetd.conf and I added the following:
printer stream tcp nowait lp /usr/lib/cups/daemon/cups-lpd cups-lpd
Now everything is working fine from my legacy FreeBSD machines.

Beginning Ubuntu Linux, Fourth Edition
CUPS: Common UNIX Printing System
Absolute FreeBSD: The Complete Guide to FreeBSD, 2nd Edition

Guruplug Server Plus — Booting from eSATA

Ive been doing a lot of testing with the guruplug plus lately. Since this thing is a loaner I dont want to make changes to the default settings if I dont have to. This has led me to do all my testing on USB thumbdrives, and on eSATA connected drives. This is a pretty simple thing to setup. Below I will walk you through what you need to do in order to boot from an eSATA connected device.

Pogoplug Multimedia Sharing Device – Gray
Linux Server Hacks

The first thing you need to is get connected to the guruplug through the jtag connector. Instructions for connecting using the jtag connector can be found here. Once connected power up the guru plug and allow it to boot up. Log in as the root user. If you have not yet, plug in and power up your eSATA drive. When I plugged mine in I got the following:

sheevaplug-debian:~# ata1: exception Emask 0x10 SAct 0x0 SErr 0x4010000 action 0xe frozen
ata1: edma_err_cause=00000010 pp_flags=00000000, dev connect
ata1: SError: { PHYRdyChg DevExch }
ata1: hard resetting link
ata1: link is slow to respond, please be patient (ready=0)
ata1: SATA link up 1.5 Gbps (SStatus 113 SControl F300)
ata1.00: ATA-7: WDC WD2000JS-00MHB0, 02.01C03, max UDMA/133
ata1.00: 390721968 sectors, multi 0: LBA48
ata1.00: configured for UDMA/133
ata1: EH complete
scsi 0:0:0:0: Direct-Access ATA WDC WD2000JS-00M 02.0 PQ: 0 ANSI: 5
sd 0:0:0:0: Attached scsi generic sg2 type 0
sd 0:0:0:0: [sdc] 390721968 512-byte logical blocks: (200 GB/186 GiB)
sd 0:0:0:0: [sdc] Write Protect is off
sd 0:0:0:0: [sdc] Write cache: enabled, read cache: enabled, doesn’t support DPO or FUA
sdc: sdc1
sd 0:0:0:0: [sdc] Attached SCSI disk

Next I need to create a partition on my disk. Normally I would use fdisk for this task but when I try I get:
sheevaplug-debian:~# fdisk /dev/sdc

WARNING: GPT (GUID Partition Table) detected on ‘/dev/sdc’! The util fdisk doesn’t support GPT. Use GNU Parted.

This means I need to install parted.
apt-get install parted
Next I can get a partition set up.
parted /dev/sdc
Now I already have 1 partition on this drive. We can see that by typing print
parted /dev/sdc

GNU Parted 1.8.8
Using /dev/sdc
Welcome to GNU Parted! Type ‘help’ to view a list of commands.

(parted) print

Model: ATA WDC WD2000JS-00M (scsi)
Disk /dev/sdc: 200GB
Sector size (logical/physical): 512B/512B
Partition Table: gpt

Number Start End Size File system Name Flags
1 17.4kB 10.2GB 10.2GB ext2 primary boot

I dont want to mess with this first partition so Im going to make a new one. The first partition was created from 0 to 10240 so I need to go from 10241 to 20481 to make another 10.2G partition.
(parted) mkpart primary ext2 10241 20481
(parted) print

Model: ATA WDC WD2000JS-00M (scsi)
Disk /dev/sdc: 200GB
Sector size (logical/physical): 512B/512B
Partition Table: gpt

Number Start End Size File system Name Flags
1 17.4kB 10.2GB 10.2GB ext2 primary boot
2 10.2GB 20.5GB 10.2GB ext3 primary

Next I want to toggle the boot flag so I type toggle and hit enter
(parted) toggle

Partition number? 2
Flag to Invert? boot/hidden/raid/lvm/hp-service/msftres/bios_grub? boot

(parted) print

Model: ATA WDC WD2000JS-00M (scsi)
Disk /dev/sdc: 200GB
Sector size (logical/physical): 512B/512B
Partition Table: gpt

Number Start End Size File system Name Flags
1 17.4kB 10.2GB 10.2GB ext2 primary boot
2 10.2GB 20.5GB 10.2GB ext3 primary boot

OK. Now Ill type q to quit, and then make a file system on the new partition.
mke2fs /dev/sdc2

… … …
This filesystem will be automatically checked every 30 mounts or
180 days, whichever comes first. Use tune2fs -c or -i to override.

Now to mount this new partition.
mount /dev/sdc2 /media/usb1/
Now a couple of cp commands will fill this disk with everything you need. This first cp will take a few minutes go grab a drink or something…
cp -avp / /media/usb1
Now to grab dev too. If you look in /media/usb1/dev you will notice it is empty. This would cause a kernel panic if we tried to boot into it now.
cp -ax /dev/ /media/usb1/
Now we are just about ready to reboot and start using our eSATA disk. All we need to do now is to give this new system a different name than the default install so its easy to tell them apart. To do this simply edit a configuration file.
echo "errr-esata" > /media/usb1/etc/hostname
Now we are ready to reboot. Type reboot and wait for the Marvell count down to appear and hit any key to stop the autoboot.
Now at the Marvell command prompt type
set x_bootargs_root root=/dev/sdc2 rootdelay=10
Be sure to use the correct root= line for your drive. This may be sda1 or sdb1 or even sdc1.
Next type boot and hit enter
If you get a kernel panic like so:

VFS: Cannot open root device “sdc2” or unknown-block(8,34)
Please append a correct “root=” boot option; here are the available partitions:
1f00 1024 mtdblock0 (driver?)
1f01 4096 mtdblock1 (driver?)
1f02 519168 mtdblock2 (driver?)
0800 195360984 sda driver: sd
0801 9999983 sda1
0802 10000976 sda2
Kernel panic – not syncing: VFS: Unable to mount root fs on unknown-block(8,34)
[] (unwind_backtrace+0x0/0xd4) from [] (panic+0x48/0x134)
[] (panic+0x48/0x134) from [] (mount_block_root+0x1c4/0x20c)
[] (mount_block_root+0x1c4/0x20c) from [] (prepare_namespace+0x168/0x1cc)
[] (prepare_namespace+0x168/0x1cc) from [] (kernel_init+0xd4/0x108)
[] (kernel_init+0xd4/0x108) from [] (kernel_thread_exit+0x0/0x8)

This means that you have told Marvell to boot from the wrong partition. In this case its telling me that sdc2 is unknown but it shows me there is an sda1 and sda2 so Im going to try sda2 instead.
Next you will get to this:

Bluetooth: vendor=0x2df, device=0x9105, class=255, fn=2
btmrvl_sdio mmc0:0001:2: firmware: requesting sd8688_helper.bin
btmrvl_sdio_download_helper: request_firmware(helper) failed, error code = -2
btmrvl_sdio_download_fw: Failed to download helper!
btmrvl_sdio_probe: Downloading firmware failed!

This same thing happens every time on the default file system too it just blows past it instead of waiting.. You can hit ctrl+c here or just wait and it will go on past.
Once it has finished booting we will see we are on our eSATA drive by looking at its host name:

Bluetooth: SCO (Voice Link) ver 0.6
Bluetooth: SCO socket layer initialized
Agent registered

Debian GNU/Linux 5.0 errr-esata ttyS0

errr-esata login:

Now I can log in and do what ever to this system and when I reboot unless I intervene it will boot back up in default mode on the default internal flash drive, since what we have done here doesnt last a reboot. I hope this helps some of you out there.

Guru Plug Server Plus — My First Look

So my boss Robert got a Guru Plug Server Plus, and to my great surprise and joy he sent it home with me to play with. Getting connected to it was simple, once it was plugged in it showed up in my wireless access point list on windows.
guruplug-wap-win
Pogoplug Multimedia Sharing Device

Once connected to the access point I got my network info and tried to ssh to the gateway. I was able to log in as root with a clever default root password. I was greeted with a familiar sight. guruplug-first-boot
Debian GNU/Linux 5.0 I connected the device to the internet and tried to apt-get update but found that didnt work. In the /etc/apt/sources.list file there was an entry for a private internal mirror. I had to comment that out and ran dpkg –configure -a since the system suggested it. Once I did that apt-get update worked and so I did an apt-get upgrade Upgraded everything that needed it. Next I installed less, and ntp. I went through the list of pre installed packages, it was pretty long. Some of the packages that stood out were Lighttpd, PERL, PHP5, Python 2.5, MySQL server and client, exim4, udhcpd, and samba 3.2.5. So for dirt you get a pretty powerful cheap ready to rock LAMP stack and File server and Wireless AP. Not so shabby. This puppy supports booting using all kinds of methods. If you are connected to it though the JTAG you will have the option to keep the system from booting. You will be given a prompt:
Hit any key to stop autoboot: 0
Marvell>> help

This will return a nice long list of options. You can choose between USB, TFTP, NFS, and many others. Im looking forward to the next couple of days of playing. I want to try out quagga and maybe asterisk. Check back soon for an update of what I do.

Red Hat Enterprise Linux 6 Beta – My First look

desktop-3-sysmon-sysinfo

I spent a few hours tonight playing around with Red Hat Enterprise Linux 6 Beta release tonight. So far it seems really nice. I had no issues getting flash-plugin installed from Adobe. I installed irssi and setup my network to use a static IP. All tasks were very familiar feeling from past releases. I mostly messed around with desktop stuff tonight. Tomorrow I hope to get to setup Apache PHP and MySQL, and maybe a few days later I will step through a mail server as well with Postfix.

Practical Guide to Fedora and Red Hat Enterprise Linux (5th Edition)
RHCE Red Hat Certified Engineer Linux Study Guide (Exam RH302) (Certification Press)

Hide your Lighttpd Version and Supress the X-Powered-By info given by PHP

A simple first step to some basic security on your web server is to make the response headers say as little as possible. This is not going to be the end all only thing you need to do to secure your web server, but hey like I said its a basic first step. When you hit a website and are looking at the content you might find your self wondering “What OS, and what web server is this person using.. And hey I see the pages end with .php I wonder what version of that they are using too..” Well this is all (by default on most systems) just pushed out to everyone who visits the site. You can find this with out even having to have any command line skills or know how to use wget or curl. A simple Firefox Plugin can tell anyone this. The typical output will look something like this:

X-Powered-By: PHP/5.2.6-1+lenny4
Content-Type: text/html; charset=utf-8
Cache-Control: no-cache, must-revalidate
Pragma: no-cache
Transfer-Encoding: chunked
Date: Sat, 27 Feb 2010 16:18:09 GMT
Server: lighttpd/1.4.25
200 OK

Wow thats a lot of info about this persons server… We can see here that they are running Debian Lenny, and they have php 5.2.6 with a patch set or 2 on it, and they have Lighttpd version 1.4.25. That now lets a possible attacker know which security lists to go hit up looking for possible exploits in any of the above mentioned software.. And a simple nmap command can automate this whole process of looking for a “mark” through entire net blocks in a matter of seconds.

Lets start by telling less info about our web server. The default response from Lighttpd is lighttpd #current-version# To change this all we need to do is edit our lighttpd.conf file. Using your favorite text editor lets open up lighttpd.conf and look though it for server.tag Odds are its not in there but thats OK we will add it and define the value.

server.tag = “WebServer”

Now that we have done that we will need to restart the web server. Next time we check our site it will look more like this:

X-Powered-By: PHP/5.2.6-1+lenny4
Content-Type: text/html
Transfer-Encoding: chunked
Date: Sat, 27 Feb 2010 15:56:46 GMT
Server: WebServer

Ah now that is much better but that pesky PHP is still telling everyone what OS and version of PHP we have.

Now lets shut PHP up. Using your favorite text editor open your php.ini file and lets look through it for expose_php By default the value will be set to On. We need to set it to Off. Now we need to restart Lighttpd again. Now our response headers will look like:

Content-Type: text/html
Transfer-Encoding: chunked
Date: Sat, 27 Feb 2010 16:02:47 GMT
Server: WebServer

Now again.. This is not the end all.. you still need to sercure the box with iptables or some other type of firewall because this did not make your server any more secure than it was before. All we did was HIDE the info making it harder to find out what you have. There are many other things you can do like running these services in a chroot jail, but this is not going to hurt to do.