BigSmoke

Smokes your problems, coughs fresh air.

Page 37 of 52

Sending SMS notifications of md device failure

I just wrote a script to send sms from a unix machine and I thought it would be a good idea to add an sms notification to mdadm. Therefore I wrote this script, called handle-md-event.sh:

#!/bin/bash
 
# Add 
# PROGRAM /usr/local/sbin/handle-md-event.sh
# To mdadm.conf
 
event="$1"
device="$2"
related="$3"
# Don't use the FQDN, because on machines with misconfigured DNS, it can take a long time to retrieve it and result in an error
hostname=`hostname`
 
mailto="root"
  [ -z "$related" ];
  related="none specified"
  [  "$event"|grep -E -i "^rebuild[0-9]{2}$"` ];
  event="$event% done"
  percentage_notice="true"
 
message="mdadm on $hostname reports an event with device: $device: $event. Related devices: $related."
 
# Don't sms on Rebuild20, Rebuild40, Rebuild60 events.
# And check if /proc/mdstat actually contains an [U_] pattern, so that you only get SMSes on failures and not just random events.
[ "$percentage_notice" != "true" ] && [ -n "`grep '\[[^]]*_[^]]*\]' /proc/mdstat`" ];
  send-sms.sh -m "$message"
 
message="$message \n\nBecause there is/was a bug in the kernel, the normal routine checkarray function also reports Rebuildxxxxxxx, as opposed to check or something. Therefore, This message is probably just causded by the periodic check of the array, but to be sure, here is /proc/mdstat for you to check whether there is a drive failure: \n\n`cat /proc/mdstat`" -e "$message"|mail -s "Mdadm on $hostname reports event $event on device $device" $mailto

In /etc/mdadm.conf you need to add the following line:

PROGRAM /usr/local/sbin/handle-md-event.sh

If you already have a handler defined, you could write a wrapper script that does both.

Bash script for sending SMS using Mollie

I signed up for a Mollie account so that I can send SMS’s from my machines. To do that, I needed a bash script, so I wrote one:

#! /bin/bash
#
# Script to send an SMS email notifcation to Mollie's HTTP gateways
# Based on the SMS2Email script which can also be found on nagiosexchange.org
# Reworked by Dennis Storm - Brainstorm ICT
# Again reworked by Wiebe Cazemier (wiebe@halfgaar.net), to include proper failure checks
#
#################################################################################
 
config_file="/etc/send-sms.conf"
log_file="/var/log/send-sms.log"
  [ -L "$log_file" ];
  "cannot continue, $log_file is a symlink."
  2
 
touch "$log_file" > /dev/null 2>&1
 
sender="SMSScript"
  [ -f "$config_file" ];
  $config_file
 
curl_location=`which curl 2> /dev/null`
  [ -z "$curl_location" ];
  "Curl command not found. Install that." >&2
  1
 
logfail()
{
  message="$1"
  message="Failure: [`date`]: $message" 
 
  $message
 
  [ -w "$log_file" ];
    "$message" >> "$log_file"
 
 
  1
}
 
# Show usage if necessary
[ $# -eq 0 ]; then
    "Usage: $0 -s [sender] -n [numbers] -m [message] -u [username] -p [password]";
    "";
    "[numbers]  = SMS numbers (if multiple, enclose in quotes) to send message to.";
    "[message]  = Text of message you want to send";
    "[username] = Username assocated with Mollie  account";
    "[sender]   = Sender"
    "[password] = MD5 HTTP API Password assocated with Mollie account";
    ""
    "-d         = Dry run, pretend success."
    ""
    "The numbers, sender, username and password options are optional and";
    "override the account credentials defined in $config_file.";
    ""
    "A log file $log_file will be kept if it is writable to the user."
    "";
    1;
 
# Get command line arguments
[ "$1" != "" ] ;
    $1
   
  -n)
      # Get the SMS numbers that we should send message to
      numbers="$2";
      2;
      ;;
  -m)
      # Get the message we should send
      message="$2";
      2;
      ;;
  -s)
      # Get the sender to show in the SMS
      sender="$2";
      2;
      ;;
  -u)
      # Get the username
      username="$2";
      2;
      ;;
  -p)
      # Get the password
      password="$2";
      2;
      ;;
  -d)
      dry_run="dry_run";
      1;
      ;;
  *)
      "Unknown option: $1"
      1;
      ;;
   
  [ -z "$username" ];
  logfail "No username specified or found in $config_file."
  [ -z "$password" ];
  logfail "No password specified or found in $config_file."
  [ -z "$numbers" ];
  logfail "No numbers specified or found in $config_file."
 
message_length= -n "$message"|wc -c`
sender_length= -n "$sender"|wc -c`
  [ "$message_length" -gt "160" ];
  logfail "SMS message is longer than 160 chars ($message_length). That is not allowed." >&2
  [ "$sender_length" -gt "11" ];
  logfail "Sender is longer than 11 chars ($sender_length). That is not allowed." >&2
 
# We haven't sent the message yet
message_sent_ok=0;
 
# The API supports sending to a comma seperated list, but that doesn't seem
# to work well. Therefore, I space seperate them and just call the API for
# each number.
number $numbers; 
  [ ! "$dry_run" ];
    RESPONSE=`curl -s -d username="$username" -d md5_password="$password" -d originator="$sender" -d recipients="$number" -d message="$message" http://www.mollie.nl/xml/sms/`
 
    RESPONSE="<success>true</success>"
 
 
  # Curl was able to post okay...
  [ "$?" -eq "0" ];
    success_line_true= "$RESPONSE"|grep -i "<success>true</success>"`
 
    [ -z "$success_line_true" ];
      logfail "$message to $number. Response was: $RESPONSE"
   
 
    logfail "curl return an error while trying to contact mollie to send an SMS." >&2
 
 
  [ -w "$log_file" ];
    "Success: [`date`]: $dry_run Sent '$message' to $number" >> $log_file
 
  "Success sending sms(es)."

It has the following config file in /etc/notify_sms.conf:

# Default values. Can be overriden with command line arguments
username="halfgaar"
password="" # MD5sum of HTTP API password.
sender="Melk"
numbers="+316xxxxxxxx" # You can set multiple numbers by space seperating them. 

LDAP search filter for Thunderbird and Zimbra

When configuring an LDAP addressbook, one thing that has given me a lot of trouble, is the LDAP filter. Here are two I use.

For thunderbird:

(|(cn=%v*)(mail=%v*)(sn=%v*)(displayName=%v*)(givenName=%v*))

For Zimbra:

(|(cn=%s*)(mail=%s*)(sn=%s*)(displayName=%s*)(givenName=%s*))

In Zimbra, I had to configure our ruby-ldapserver to never return more than 50 results, because in the configuration panel, it runs a test based on a search query which goes fine, but it does another query with the %s literally repeated. This causes the SQL condition that is generated to be %s% and that gives a whole lot of results, hanging Zimbra. It is beyond me why Zimbra runs this second query, but I guess it’s a bug.

Debian network bridge setup for kvm/qemu

When you run virtual machines, the most convenient network setup is having a bridge between the virtual machine and your normal ethernet network. In Debian, I use the following config in /etc/network/interfaces to have such a bridge:

# /etc/network/interfaces -- configuration file for ifup(8), ifdown(8)
 
# The loopback interface
auto lo
iface lo inet loopback
 
# The first network card - this entry was created during the Debian installation
# (network, broadcast and gateway are optional)
auto eth1
iface eth1 inet manual
 
auto br0
iface br0 inet static
    address 192.168.1.101
    network 192.168.1.0
    broadcast 192.168.1.255
    netmask 255.255.255.0
    gateway 192.168.1.100
    bridge_ports eth1
    bridge_fd 9
    bridge_hello 2
    bridge_maxage 12
    bridge_stp off

In this setup, the br0 gets the IP address that eth1 had before. Intuitively, I would have created a bridge which would connect eth1 and new interfaces, but when I did that, I could not get it to work.

I then used a command similar to this to install the virtual machine:

virt-install --connect qemu:///system -n vm10 -r 512 --vcpus=2 -f ~/vm10.qcow2 -s 12 -c ~/debian-500-amd64-netinst.iso --vnc --noautoconsole --os linux --os-variant debianLenny --accelerate --network=bridge:br0 --hvm

You can adjust where necessary. What’s important, is the –network=bridge:br0. This makes sure that kvm is run with:

kvm [more options] -net nic,macaddr=54:52:00:52:1c:7c,vlan=0,model=virtio -net tap,fd=7,script=,vlan=0,ifname=vnet0

The network setup looks like:

br0       Link encap:Ethernet  HWaddr 00:15:17:23:83:67
          inet addr:192.168.1.101  Bcast:192.168.1.255  Mask:255.255.255.0
          inet6 addr: fe80::215:17ff:fe23:8367/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:1866633 errors:0 dropped:0 overruns:0 frame:0
          TX packets:1678602 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:892540330 (851.1 MiB)  TX bytes:971936093 (926.9 MiB)
 
eth1      Link encap:Ethernet  HWaddr 00:15:17:23:83:67
          inet6 addr: fe80::215:17ff:fe23:8367/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:13371212 errors:0 dropped:0 overruns:0 frame:0
          TX packets:12703312 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:100
          RX bytes:4234365756 (3.9 GiB)  TX bytes:201738186 (192.3 MiB)
          Memory:88180000-881a0000
 
lo        Link encap:Local Loopback
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:16436  Metric:1
          RX packets:2672817 errors:0 dropped:0 overruns:0 frame:0
          TX packets:2672817 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:493599313 (470.7 MiB)  TX bytes:493599313 (470.7 MiB)
 
vnet0     Link encap:Ethernet  HWaddr 00:ff:2d:a0:76:34
          inet6 addr: fe80::2ff:2dff:fea0:7634/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:159072 errors:0 dropped:0 overruns:0 frame:0
          TX packets:310906 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:500
          RX bytes:10860687 (10.3 MiB)  TX bytes:465526222 (443.9 MiB)

source for all this.

Making sure virtual machine guests shut down properly on a Debian host

I just installed libvirt and installed a vritual machine with virt-install. I also used virsh to configure it to autostart on machine start. This way, it integrates quite nicely with the host operating system.

However, I found out that libvirt provides no way to properly shut the machines down when the host goes down. It is completely beyond me that they didn’t implement this. When you shut down libvirtd, the guests just die…

Googling yielded almost nothing, except a bug report from 17 Mar 2009 with a request for this. The report still wasn’t handled, but the guy said that he wrote a crude script to do it. I mailed him to ask for it, and here it is:

#! /bin/sh
### BEGIN INIT INFO
# Provides:          kvm_domains
# Required-Start:    $remote_fs
# Required-Stop:     $remote_fs
# Default-Start:     
# Default-Stop:      0 6
# Short-Description: Shutdown kvm domains
# Description:       Shutdown kvm domains on reboot/poweroff.
#                    Forcefully kill instances that still run after a
#                    given timeout.
### END INIT INFO
 
# Author: Michael Biebl <biebl@teco.edu>
#
 
# Do NOT "set -e"
 
# PATH should only include /usr/* if it runs after the mountnfs.sh script
PATH=/sbin:/usr/sbin:/bin:/usr/bin
DESC="KVM domains"
VIRSH=/usr/bin/virsh
SCRIPTNAME=/etc/init.d/kvm_domains
TIMEOUT=60
 
# Exit if the package is not installed
[ -x "$VIRSH" ] || 0
 
# Define LSB log_* functions.
# Depend on lsb-base (>= 3.0-6) to ensure that this file is present.
. /lib/lsb/init-functions
 
#
# Function that stops the daemon/service
#
do_stop()
{
	domains=$($VIRSH -q list | awk '/running/ {print $2}')
 [ -z "$domains" ] ;
		log_progress_msg "none"
	 0
 
 d $domains ;
		$VIRSH -q shutdown $d > /dev/null
		log_progress_msg $d
 
 
	i=0
 [ $i -lt $TIMEOUT ] ;
	 $VIRSH -q list | grep -q running ;
			i=$(($i+1))
			log_progress_msg "."
			sleep 1
	
		 0
	
 
	# forcefully kill the remaining kvm instances
	killall -9 kvm
 1 
}
 
 "$1"
  start)
	;;
  stop)
	log_begin_msg "Stopping $DESC:"
	do_stop
 "$?"
		0) log_end_msg 0 ;;
		1) log_end_msg 1 ;;
 
	;;
  restart|force-reload)
	;;
  *)
	#echo "Usage: $SCRIPTNAME {start|stop|restart|reload|force-reload}" >&2
 "Usage: $SCRIPTNAME {start|stop|restart|force-reload}" >&2
 3
	;;
 
:

It depends on text output by virsh, so it’s not the most robust, but it works.

Run this to put in it in the proper runlevels (the 10 on my system makes sure it executes before kvm and libvirt):

update-rc.d kvm_domains stop 10 0 6 .

Dumping a bunch of MP3s as WAV files

I just used the following command for converting a directory with a bunch of MP3s to WAV. Does someone know a command that is shorter? I find mine a bit convoluted to say the least.

mkdir wav
ls *mp3|while i;  mpg123 --stdout "$i" > wav/ $i|sed -r -e 's/^([0-9]+) .*$/\1/'`.wav;

The directory looks like this:

$ ls -1
01 - Meant to Be.mp3
02 - Reflections.mp3
03 - Semester Days.mp3
04 - Friend.mp3
05 - True Gemini.mp3
06 - Down the Road.mp3
07 - Tulip Trees.mp3
08 - Not Alone.mp3
09 - Woods of Chaos.mp3
10 - Twilight.mp3
[en] Readme - www.jamendo.com .txt
[es] Lee me - www.jamendo.com .txt
[fr] Lisez moi - www.jamendo.com .txt
[it] Readme - www.jamendo.com .txt
License.txt
Rob Costlow - Solo Piano - Woods of Chaos.1.0.jpg

Adding a recycle bin to a samba share

People are stupid and remove things accidentally. You can partly mitigate that by adding recycle bin functionality to a samba share.

[Our documents]
  comment = Central storage for all our documents
  path = /home/smb
  guest ok = yes
  writeable = yes
  browseable = yes
  force group = samba
  create mask = 0660
  directory mask = 0770
 
  ; recycler
  vfs object = recycle:recycle
  recycle:subdir_mode = 0770
  recycle:repository = .recycle ; directory name
  recycle:keeptree = Yes
  recycle:touch = Yes
  recycle:versions = No
  recycle:maxsize = 100000000 ; 100 metric million bytes 

The action is hooked on the delete action. Pressing shift-delete won’t prevent files from being moved to the recycler, which is good.

You can then make a cron job which throws away old files:

# Every day at 6am
0 6 * * * root    find /home/smb/.recycle/  f -mtime +5 -delete > /dev/null

XTerm configuration

I just created a gist for my XTerm configuration (separated from the rest of my X resources). Here’s a snapshot of the current version:

XTerm*background: black
XTerm*Foreground: Grey

XTerm*faceName: Liberation Mono
XTerm*faceSize: 10

XTerm*on2Clicks: regex [^  \n]+

XTerm*bellIsUrgent: true

! Make the terminal 127 by 42 characters in size
XTerm*geometry: 127x44+64+0

! By default, XTerm composes special chars with META. With this setting I can work my readline magic instead.
XTerm*metaSendsEscape: true

! Bracketed paste mode requires the allowWindowOps resource to be true 
XTerm*allowWindowOps: true

XTerm*saveLines: 1000

! Don't jump to the bottom when there's output
XTerm*VT100*scrollTtyOutput: false

XTerm*VT100.Translations: #override \
    ShiftInsert: insert-selection(CLIPBOARD) \n\
    Insert: insert-selection(PRIMARY) \n\
    Shift: insert-selection(CLIPBOARD) \n\
    ShiftUp: scroll-back(1) \n\
    ShiftDown: scroll-forw(1)


! vim: set syntax=xdefaults expandtab tabstop=4 shiftwidth=4:

Old Window Maker screenshot from April 2004

While cleaning up old images, I came across a screenshot of an old Window Maker configuration that I ran in 2004. It looks a bit different from my current configuration, but not that different, which just goes to say how little Window Maker has changed in the last five years. The main difference I see in terms of Window Maker capabilities is that Window Maker now has font anti-aliasing support.

I notice that I was actually using VIM’s folding support at the time. Also, it’s funny to see that I was in the middle of the development of a (now stale, even more badly written) fork of phpBB.

Window Maker Workspace (2004)

Window Maker Workspace (2004)

Modern self-hosted, open-source web statistics software

I’ve been using Google Analytics for most of my websites for quite some time. Philosophically, I’d prefer a self-hosted solution though. In the past I’ve used Webalizer and I still use awstats for my ad-hoc, static website, but these programs are a bit primitive and limited compared to Analytics.

Of the newer programs that I’ve been looking into Piwik looks the most promising to me, but there’s also Obsessive Website Statistics which looks pretty reasonable. W3Perl looks pretty, but seems rather spartan.

An example of Piwik in action

An example of Piwik in action

One of the things that has made me a bit shy of Google Analytics is its reliance on JavaScript, a dependence that means that I can’t gather statistics about robots or other user agents lacking JavaScript support. On the other hand, this method lets you gather much more data for the clients that do support JavaScript. Piwik depends on JavaScript in the same way as Google Analytics does. This can be seen as either an advantage or a disadvantage depending on your view on this issue.

I’d have to install Piwik to determine my view…

« Older posts Newer posts »

© 2024 BigSmoke

Theme by Anders NorenUp ↑