<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-1895238826710454512</id><updated>2012-01-29T17:57:21.701+10:00</updated><category term='linux'/><category term='squid'/><category term='ext3'/><category term='init'/><category term='ps3'/><category term='filesystem'/><category term='handbrake'/><category term='mysql'/><category term='python'/><category term='heartbeat'/><category term='mediatomb'/><category term='vmware'/><category term='macosx'/><category term='nfs'/><category term='fedora'/><category term='redmine'/><category term='lvm'/><category term='transmission'/><category term='solaris'/><category term='bash'/><category term='drbd'/><category term='dstat'/><title type='text'>Jason Friedland</title><subtitle type='html'>All things RHEL/CentOS/Fedora Linux and RPM packaging, with a sprinkling of Solaris and Python.</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://blog.friedland.id.au/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1895238826710454512/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://blog.friedland.id.au/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Jason Friedland</name><uri>http://www.blogger.com/profile/00183680637848117317</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>33</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-1895238826710454512.post-9129275015404804250</id><published>2010-12-20T15:22:00.007+10:00</published><updated>2011-01-11T09:38:40.258+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='mediatomb'/><category scheme='http://www.blogger.com/atom/ns#' term='solaris'/><title type='text'>Installing Mediatomb on Solaris 11 Express</title><content type='html'>My home NAS is now running Solaris 11 for the 'express' purpose (sorry) of being able to use ZFS, and all the light, joy and happiness it brings to the world of storage. I'm using three 1TB SATA disks in a RAIDZ configuration, and using ZFS's built-in filesystem compression, CIFS and NFS sharing capabilities. Since I use a PS3 as my media center front-end I need a DLNA/UPnP media server and having used Mediatomb previously on Linux, that's what I'll walk through installing from source here today.&lt;br /&gt;&lt;br /&gt;Before starting, make sure you have GNU C compiler (gcc) and make installed. This is easily achieved using the new package management tools in Solaris 11. Try &lt;b&gt;man pkg&lt;/b&gt; to get started. &lt;br /&gt;&lt;br /&gt;For Mediatomb to correctly identify certain files' MIME types (like image/jpeg, for example) you need to build the GPL'd version of the file utility for a library called libmagic.&lt;br /&gt;&lt;pre&gt;tar zxvf file-5.04.tar.gz&lt;br /&gt;cd file-5.04&lt;br /&gt;./configure --prefix=/usr/local&lt;br /&gt;make&lt;br /&gt;make install&lt;br /&gt;&lt;/pre&gt;Check for libmagic library and headers:&lt;br /&gt;&lt;pre&gt;ls /usr/local/include&lt;br /&gt;ls /usr/local/lib&lt;br /&gt;&lt;/pre&gt;Next, download the source for Mediatomb and extract it.&lt;br /&gt;&lt;pre&gt;tar zxvf mediatomb-0.12.1.tar.gz&lt;br /&gt;cd mediatomb-0.12.1&lt;br /&gt;&lt;/pre&gt;The source code contains some apparently outdated prelink logic which breaks the build on newer versions of the OS, so we need to comment it out. You can either edit src/main.cc by hand or just use the following patch - save it to &lt;b&gt;main.cc.patch0&lt;/b&gt;.&lt;br /&gt;&lt;pre&gt;*** src/main.cc.orig&amp;nbsp;&amp;nbsp;&amp;nbsp; 2010-12-20 13:13:11.080796210 +1000&lt;br /&gt;--- src/main.cc 2010-12-20 13:13:30.478542756 +1000&lt;br /&gt;***************&lt;br /&gt;*** 141,146 ****&lt;br /&gt;--- 141,147 ----&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Ref&amp;lt;Array&amp;lt;StringBase&amp;gt; &amp;gt; addFile(new Array&amp;lt;StringBase&amp;gt;());&lt;br /&gt;&lt;br /&gt;+ /*&lt;br /&gt;&amp;nbsp; #ifdef SOLARIS&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; String ld_preload;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; char *preload = getenv("LD_PRELOAD");&lt;br /&gt;***************&lt;br /&gt;*** 155,160 ****&lt;br /&gt;--- 156,162 ----&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; exit(EXIT_FAILURE);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp; #endif&lt;br /&gt;+ */&lt;br /&gt;&lt;br /&gt;&amp;nbsp; #ifdef HAVE_GETOPT_LONG&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; while (1)&lt;br /&gt;&lt;/pre&gt;And apply the patch:&lt;br /&gt;&lt;pre&gt;patch src/main.cc &amp;lt; main.cc.patch0&lt;br /&gt;&lt;/pre&gt;Now configure, build and install:&lt;br /&gt;&lt;pre&gt;./configure --enable-libmagic --with-magic-h=/usr/local/include --with-magic-libs=/usr/local/lib&lt;br /&gt;make&lt;br /&gt;make install&lt;br /&gt;&lt;/pre&gt;At this stage, you could add your config files and fire up the daemon, however I'm going to create service manifests so we can manage startup and shutdown of Mediatomb via the Solaris Service Management Framework (SMF). Save this file as &lt;b&gt;/lib/svc/method/svc-mediatomb&lt;/b&gt;.&lt;br /&gt;&lt;pre&gt;#!/bin/sh&lt;br /&gt;. /etc/mediatomb.conf&lt;br /&gt;LD_LIBRARY_PATH=/usr/local/lib /usr/local/bin/mediatomb -d \&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; -u $MT_USER \&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; -g $MT_GROUP \&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; -P $MT_PIDFILE \&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; -l $MT_LOGFILE \&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; -m $MT_HOME \&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; -f $MT_CFGDIR \&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; -p $MT_PORT \&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; -e $MT_INTERFACE \&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; $MT_OPTIONS&lt;br /&gt;&lt;/pre&gt;Create &lt;b&gt;/etc/mediatomb.conf&lt;/b&gt;, setting appropriate values for variables above. Something like the following would suffice:&lt;br /&gt;&lt;pre&gt;MT_INTERFACE="rge0"&lt;br /&gt;MT_OPTIONS=""&lt;br /&gt;MT_PORT="50500"&lt;br /&gt;MT_USER="media"&lt;br /&gt;MT_GROUP="media"&lt;br /&gt;MT_PIDFILE="/var/run/mediatomb.pid"&lt;br /&gt;MT_LOGFILE="/var/log/mediatomb"&lt;br /&gt;MT_HOME="/etc"&lt;br /&gt;MT_CFGDIR="mediatomb"&lt;br /&gt;&lt;/pre&gt;Now for the service manifest - create this file as &lt;b&gt;/var/svc/manifest/application/mediatomb.xml&lt;/b&gt;.&lt;br /&gt;&lt;pre&gt;&amp;lt;?xml version="1.0"?&amp;gt;&lt;br /&gt;&amp;lt;!DOCTYPE service_bundle SYSTEM "/usr/share/lib/xml/dtd/service_bundle.dtd.1"&amp;gt;&lt;br /&gt;&amp;lt;service_bundle type="manifest" name="mediatomb"&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;service name="application/mediatomb" type="service" version="1"&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;create_default_instance enabled="false"/&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;single_instance/&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;dependency name="network" grouping="require_all" restart_on="error" type="service"&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;service_fmri value="svc:/milestone/network:default"/&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/dependency&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;dependency name="filesystem" grouping="require_all" restart_on="error" type="service"&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;service_fmri value="svc:/system/filesystem/local"/&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/dependency&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;exec_method type="method" name="start" exec="/lib/svc/method/svc-mediatomb" timeout_seconds="60"&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/exec_method&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;exec_method type="method" name="stop" exec=":kill" timeout_seconds="5"&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/exec_method&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;property_group name="startd" type="framework"&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;propval name="ignore_error" type="astring" value="core,signal"/&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/property_group&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;stability value="Evolving"/&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;template&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;common_name&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;loctext xml:lang="C"&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; UPnP Media Server&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/loctext&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/common_name&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;documentation&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;manpage title="mediatomb" section="1" manpath="/opt/local/share/man"/&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;doc_link name="mediatomb.cc" uri="http://mediatomb.cc"/&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/documentation&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/template&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/service&amp;gt;&lt;br /&gt;&amp;lt;/service_bundle&amp;gt;&lt;br /&gt;&lt;/pre&gt;Then validate, import and run the service:&lt;br /&gt;&lt;pre&gt;svccfg validate /var/svc/manifest/application/mediatomb.xml&lt;br /&gt;svccfg import /var/svc/manifest/application/mediatomb.xml&lt;br /&gt;svcs -a mediatomb&lt;br /&gt;svcadm enable mediatomb&lt;br /&gt;&lt;/pre&gt;If all went well you should now be able to connect to the Mediatomb web interface on port 50500.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1895238826710454512-9129275015404804250?l=blog.friedland.id.au' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.friedland.id.au/feeds/9129275015404804250/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://blog.friedland.id.au/2010/12/installing-mediatomb-on-solaris-11.html#comment-form' title='7 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1895238826710454512/posts/default/9129275015404804250'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1895238826710454512/posts/default/9129275015404804250'/><link rel='alternate' type='text/html' href='http://blog.friedland.id.au/2010/12/installing-mediatomb-on-solaris-11.html' title='Installing Mediatomb on Solaris 11 Express'/><author><name>Jason Friedland</name><uri>http://www.blogger.com/profile/00183680637848117317</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>7</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1895238826710454512.post-6528768762362718699</id><published>2010-11-06T11:53:00.002+10:00</published><updated>2010-11-06T11:53:59.968+10:00</updated><title type='text'>Scan for new devices in Solaris</title><content type='html'>This is how to tell Solaris to look for new devices when booting - append a '-r' to the kernel boot arguments:&lt;br /&gt;&lt;br /&gt;Select the Solaris entry GRUB menu that you want to boot, to edit, enter e&lt;br /&gt;Select the "kernel /platform" line, to edit that again enter e&lt;br /&gt;Add to the end of the 'kernel' line a space followed by -r &lt;br /&gt;Press enter key to accept the change&lt;br /&gt;Press b to boot&lt;br /&gt;&lt;br /&gt;Via: &lt;a href="http://blogs.sun.com/harcey/entry/solaris_x86_vmware_adding_a"&gt;http://blogs.sun.com/harcey/entry/solaris_x86_vmware_adding_a&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1895238826710454512-6528768762362718699?l=blog.friedland.id.au' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.friedland.id.au/feeds/6528768762362718699/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://blog.friedland.id.au/2010/11/scan-for-new-devices-in-solaris.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1895238826710454512/posts/default/6528768762362718699'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1895238826710454512/posts/default/6528768762362718699'/><link rel='alternate' type='text/html' href='http://blog.friedland.id.au/2010/11/scan-for-new-devices-in-solaris.html' title='Scan for new devices in Solaris'/><author><name>Jason Friedland</name><uri>http://www.blogger.com/profile/00183680637848117317</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1895238826710454512.post-7586124342920251319</id><published>2010-08-04T20:11:00.010+10:00</published><updated>2010-11-10T15:52:59.516+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='heartbeat'/><category scheme='http://www.blogger.com/atom/ns#' term='linux'/><category scheme='http://www.blogger.com/atom/ns#' term='nfs'/><category scheme='http://www.blogger.com/atom/ns#' term='drbd'/><title type='text'>Setting up a highly available NFS cluster</title><content type='html'>The following is a proof-of-concept HA NFS cluster running on RHEL 5, using DRBD for block-level replication and heartbeat for failover.&lt;br /&gt;&lt;br /&gt;In this example, I'll be setting up 2 nodes: &lt;b&gt;nfs01&lt;/b&gt; and &lt;b&gt;nfs02&lt;/b&gt;. Ensure that ALL commands and setup is run against both nodes EXCEPT where stated otherwise.&lt;br /&gt;&lt;br /&gt;Following is the partition table for a test install - the metadata partition &lt;b&gt;/dev/sda7&lt;/b&gt; and the data partition &lt;b&gt;/dev/sda8&lt;/b&gt; are unformatted and unmounted.&lt;pre&gt;[root@nfs01 ~]# fdisk -l /dev/sda&lt;br /&gt;&lt;br /&gt;Disk /dev/sda: 21.4 GB, 21474836480 bytes&lt;br /&gt;255 heads, 63 sectors/track, 2610 cylinders&lt;br /&gt;Units = cylinders of 16065 * 512 = 8225280 bytes&lt;br /&gt;&lt;br /&gt;   Device Boot      Start         End      Blocks   Id  System&lt;br /&gt;/dev/sda1   *           1          13      104391   83  Linux&lt;br /&gt;/dev/sda2              14         274     2096482+  82  Linux swap / Solaris&lt;br /&gt;/dev/sda3             275         535     2096482+  83  Linux&lt;br /&gt;/dev/sda4             536        2610    16667437+   5  Extended&lt;br /&gt;/dev/sda5             536         796     2096451   83  Linux&lt;br /&gt;/dev/sda6             797        1057     2096451   83  Linux&lt;br /&gt;/dev/sda7            1058        1074      136521   83  Linux&lt;br /&gt;/dev/sda8            1075        2610    12337888+  83  Linux&lt;br /&gt;&lt;/pre&gt;Instructions for building the DRBD RPMs, including the kernel module can be found &lt;a href="http://www.drbd.org/users-guide-emb/s-build-rpm.html"&gt;on the DRBD website&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;The kernel in use is the latest update for RHEL 5.5 at the time of writing, version kernel-2.6.18-194.3.1.el5.x86_64.rpm - DRBD must be compiled against your specific version of kernel-headers.&lt;br /&gt;&lt;br /&gt;Ensure at least the following RPMs are installed.&lt;pre&gt;rpm-build-4.4.2.3-18.el5    &lt;br /&gt;elfutils-0.137-3.el5        &lt;br /&gt;elfutils-libs-0.137-3.el5   &lt;br /&gt;flex-2.5.4a-41.fc6          &lt;br /&gt;glibc-devel-2.5-49.el5_5.2  &lt;br /&gt;glibc-headers-2.5-49.el5_5.2&lt;br /&gt;kernel-2.6.18-194.3.1.el5   &lt;br /&gt;kernel-devel-2.6.18-194.3.1.el5  &lt;br /&gt;kernel-headers-2.6.18-194.3.1.el5&lt;br /&gt;gcc-c++-4.1.2-48.el5&lt;br /&gt;gcc-4.1.2-48.el5&lt;br /&gt;make-3.81-3.el5&lt;br /&gt;&lt;/pre&gt;Use DRBD's built-in functionality to build both the userland and kernel module RPMs.&lt;pre&gt;[root@nfs01 build]# tar zxf drbd-8.3.8.tar.gz &lt;br /&gt;[root@nfs01 build]# cd drbd-8.3.8&lt;br /&gt;[root@nfs01 drbd-8.3.8]# ./configure --with-km=/usr/src/kernels/2.6.18-194.3.1.el5-x86_64/&lt;br /&gt;[root@nfs01 drbd-8.3.8]# make km-rpm rpm&lt;br /&gt;...&lt;br /&gt;You now have:&lt;br /&gt;/usr/src/redhat/RPMS/x86_64/drbd-bash-completion-8.3.8-1.x86_64.rpm&lt;br /&gt;/usr/src/redhat/RPMS/x86_64/drbd-pacemaker-8.3.8-1.x86_64.rpm&lt;br /&gt;/usr/src/redhat/RPMS/x86_64/drbd-km-2.6.18_194.3.1.el5-8.3.8-12.x86_64.rpm&lt;br /&gt;/usr/src/redhat/RPMS/x86_64/drbd-udev-8.3.8-1.x86_64.rpm&lt;br /&gt;/usr/src/redhat/RPMS/x86_64/drbd-utils-8.3.8-1.x86_64.rpm&lt;br /&gt;/usr/src/redhat/RPMS/x86_64/drbd-8.3.8-1.x86_64.rpm&lt;br /&gt;/usr/src/redhat/RPMS/x86_64/drbd-xen-8.3.8-1.x86_64.rpm&lt;br /&gt;/usr/src/redhat/RPMS/x86_64/drbd-heartbeat-8.3.8-1.x86_64.rpm&lt;br /&gt;&lt;/pre&gt;Install DRBD and modprobe the new module - a reboot is given in the examples here to check the module loads on a system restart.&lt;pre&gt;[root@nfs01 drbd-8.3.8]# rpm -ivh /usr/src/redhat/RPMS/x86_64/drbd-*&lt;br /&gt;[root@nfs01 drbd-8.3.8]# modprobe drbd # or...&lt;br /&gt;[root@nfs01 drbd-8.3.8]# reboot&lt;br /&gt;...&lt;br /&gt;[root@nfs01 drbd-8.3.8]# lsmod | grep drbd&lt;br /&gt;drbd                  277784  0 &lt;br /&gt;&lt;/pre&gt;Install the sample &lt;b&gt;/etc/drbd.conf&lt;/b&gt; file.&lt;pre&gt;# A comprehensively commented example of this file exists at:&lt;br /&gt;# /usr/share/doc/drbd-utils-8.3.8/drbd.conf.example&lt;br /&gt;&lt;br /&gt;resource r0 {&lt;br /&gt;&lt;br /&gt;    protocol C;&lt;br /&gt;    &lt;br /&gt;    # Parse error here:&lt;br /&gt;    # incon-degr-cmd "halt -f";&lt;br /&gt;    &lt;br /&gt;    startup {&lt;br /&gt;        degr-wfc-timeout 120;    # 2 minutes.&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    disk {&lt;br /&gt;        on-io-error   detach;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    net {&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    syncer {&lt;br /&gt;        rate 10M;&lt;br /&gt;        # group 1;&lt;br /&gt;        al-extents 257;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    on nfs01 {                   &lt;br /&gt;        device    /dev/drbd0;          &lt;br /&gt;        disk      /dev/sda8;           # NFS data partition&lt;br /&gt;        meta-disk /dev/sda7[0];        # 1024MB partition for DRBD metadata&lt;br /&gt;        address   192.168.1.101:7788;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    on nfs02 {                   &lt;br /&gt;       device    /dev/drbd0;           &lt;br /&gt;       disk      /dev/sda8;            # NFS data partition&lt;br /&gt;       meta-disk /dev/sda7[0];         # 1024MB partition for DRBD metadata&lt;br /&gt;       address   192.168.1.102:7788;  &lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;}&lt;/pre&gt;Install the sample &lt;b&gt;/etc/exports&lt;/b&gt; file, and ensure the NFS service is stopped and is not set to launch on system startup.&lt;br /&gt;&lt;pre&gt;/export/ 192.168.1.0/255.255.255.0(rw,no_root_squash,no_all_squash,sync)&lt;br /&gt;&lt;/pre&gt;&lt;pre&gt;[root@nfs01 drbd-8.3.8]# /etc/init.d/nfs stop&lt;br /&gt;[root@nfs01 drbd-8.3.8]# chkconfig nfs off&lt;br /&gt;&lt;/pre&gt;Configure the NFS statd daemon to use the hostname for the floating IP.&lt;pre&gt;[root@nfs01 ~]# echo &gt;&gt; /etc/sysconfig/nfs 'STATDARG="-n nfs.localdomain"'&lt;/pre&gt;Ensure there's no existing filesystem on your metadata partition, &lt;b&gt;/dev/sda7&lt;/b&gt; in this case.&lt;pre&gt;[root@nfs01 ~]# dd if=/dev/zero of=/dev/sda7 bs=1M count=256&lt;br /&gt;[root@nfs01 ~]# drbdadm create-md r0&lt;br /&gt;Writing meta data...&lt;br /&gt;initializing activity log&lt;br /&gt;NOT initialized bitmap&lt;br /&gt;New drbd meta data block successfully created.&lt;br /&gt;&lt;br /&gt;[root@nfs01 ~]# mkfs.ext3 /dev/sda8&lt;br /&gt;[root@nfs01 ~]# drbdadm up all&lt;br /&gt;&lt;br /&gt;[root@nfs01 ~]# cat /proc/drbd &lt;br /&gt;version: 8.3.8 (api:88/proto:86-94)&lt;br /&gt;GIT-hash: d78846e52224fd00562f7c225bcc25b2d422321d build by root@nfs01, 2010-06-18 16:52:07&lt;br /&gt; 0: cs:Connected ro:Secondary/Secondary ds:Inconsistent/Inconsistent C r----&lt;br /&gt;    ns:0 nr:0 dw:0 dr:0 al:0 bm:0 lo:0 pe:0 ua:0 ap:0 ep:1 wo:b oos:12217404&lt;/pre&gt;Do this only on node 1:&lt;pre&gt;[root@nfs01 ~]# drbdadm adjust all &lt;br /&gt;[root@nfs01 ~]# drbdadm -- --force primary r0&lt;br /&gt;&lt;br /&gt;[root@nfs01 ~]# cat /proc/drbd&lt;br /&gt;version: 8.3.8 (api:88/proto:86-94)&lt;br /&gt;GIT-hash: d78846e52224fd00562f7c225bcc25b2d422321d build by root@nfs01, 2010-06-18 16:52:07&lt;br /&gt; 0: cs:SyncSource ro:Primary/Secondary ds:UpToDate/Inconsistent C r----&lt;br /&gt;    ns:537600 nr:0 dw:0 dr:537600 al:0 bm:32 lo:0 pe:0 ua:0 ap:0 ep:1 wo:b oos:11679804&lt;br /&gt; [&gt;....................] sync'ed:  4.5% (11404/11928)M delay_probe: 102&lt;br /&gt; finish: 0:15:41 speed: 12,272 (10,336) K/sec&lt;br /&gt;&lt;br /&gt;# Completed now:&lt;br /&gt;[root@nfs01 ~]# cat /proc/drbd&lt;br /&gt;version: 8.3.8 (api:88/proto:86-94)&lt;br /&gt;GIT-hash: d78846e52224fd00562f7c225bcc25b2d422321d build by root@nfs01, 2010-06-18 16:52:07&lt;br /&gt; 0: cs:Connected ro:Primary/Secondary ds:UpToDate/UpToDate C r----&lt;br /&gt;    ns:12217401 nr:0 dw:0 dr:12217401 al:0 bm:746 lo:0 pe:0 ua:0 ap:0 ep:1 wo:b oos:0&lt;/pre&gt;Do this only on node 1:&lt;pre&gt;[root@nfs01 ~]# mount /dev/drbd0 /export&lt;br /&gt;[root@nfs01 ~]# mv /var/lib/nfs /export/&lt;br /&gt;[root@nfs01 ~]# cd /var/lib/&lt;br /&gt;[root@nfs01 ~]# mv nfs nfs.old&lt;br /&gt;[root@nfs01 ~]# ln -s /export/nfs&lt;/pre&gt;Do this only on node 2:&lt;pre&gt;[root@nfs02 ~]# cd /var/lib/&lt;br /&gt;[root@nfs02 lib]# mv nfs nfs.old&lt;br /&gt;[root@nfs02 lib]# ln -s /export/nfs&lt;br /&gt;&lt;/pre&gt;Ensure the EPEL repository is enabled and install heartbeat.&lt;pre&gt;[root@nfs01 ~]# yum install heartbeat.x86_64&lt;br /&gt;&lt;/pre&gt;Edit the &lt;b&gt;/etc/ha.d/ha.cf&lt;/b&gt; file.&lt;pre&gt;logfacility local0&lt;br /&gt;keepalive 2&lt;br /&gt;deadtime 10&lt;br /&gt;bcast eth0&lt;br /&gt;node nfs01.localdomain nfs02.localdomain&lt;br /&gt;auto_failback on&lt;br /&gt;&lt;/pre&gt;Edit &lt;b&gt;/etc/ha.d/haresources&lt;/b&gt; - the IP address is the floating one.&lt;pre&gt;nfs01.localdomain IPaddr::192.168.1.103/24/eth0 \&lt;br /&gt;    drbddisk::r0 Filesystem::/dev/drbd0::/export::ext3 nfs&lt;/pre&gt;Add a secret to &lt;b&gt;/etc/ha.d/authkeys&lt;/b&gt; file.&lt;pre&gt;auth 3&lt;br /&gt;3 md5 pa55word&lt;/pre&gt;&lt;pre&gt;chmod 600 /etc/ha.d/authkeys&lt;/pre&gt;Make sure the drbd and heartbeat servces are set to start on boot, and start them up:&lt;pre&gt;/etc/init.d/drbd start&lt;br /&gt;/etc/init.d/heartbeat start&lt;br /&gt;&lt;br /&gt;chkconfig drbd on&lt;br /&gt;chkconfig heartbeat on&lt;/pre&gt;That's a very brief and tersely documented example - you can now test failover by pulling a network cable :-)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1895238826710454512-7586124342920251319?l=blog.friedland.id.au' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.friedland.id.au/feeds/7586124342920251319/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://blog.friedland.id.au/2010/08/setting-up-highly-available-nfs-cluster.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1895238826710454512/posts/default/7586124342920251319'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1895238826710454512/posts/default/7586124342920251319'/><link rel='alternate' type='text/html' href='http://blog.friedland.id.au/2010/08/setting-up-highly-available-nfs-cluster.html' title='Setting up a highly available NFS cluster'/><author><name>Jason Friedland</name><uri>http://www.blogger.com/profile/00183680637848117317</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1895238826710454512.post-3041843188911213185</id><published>2010-04-12T12:30:00.002+10:00</published><updated>2010-04-12T12:33:07.219+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='linux'/><category scheme='http://www.blogger.com/atom/ns#' term='filesystem'/><category scheme='http://www.blogger.com/atom/ns#' term='ext3'/><title type='text'>Automount filesystems by label</title><content type='html'>Here's a handy (and from what's in the autofs the man pages, undocumented) trick for auto-mounting ext3 filesystems by label. Say I had a removable USB drive formatted as ext3 with the label &lt;b&gt;WD-250&lt;/b&gt; I could add this line to my auto.misc file:&lt;pre&gt;WD-250 -fstype=ext3 :LABEL=WD-250&lt;/pre&gt;The filesystem UUID also seems to work using this method.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1895238826710454512-3041843188911213185?l=blog.friedland.id.au' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.friedland.id.au/feeds/3041843188911213185/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://blog.friedland.id.au/2010/04/automount-filesystems-by-label.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1895238826710454512/posts/default/3041843188911213185'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1895238826710454512/posts/default/3041843188911213185'/><link rel='alternate' type='text/html' href='http://blog.friedland.id.au/2010/04/automount-filesystems-by-label.html' title='Automount filesystems by label'/><author><name>Jason Friedland</name><uri>http://www.blogger.com/profile/00183680637848117317</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1895238826710454512.post-371376109237297299</id><published>2010-03-30T14:24:00.005+10:00</published><updated>2010-04-12T12:33:55.220+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='redmine'/><category scheme='http://www.blogger.com/atom/ns#' term='linux'/><category scheme='http://www.blogger.com/atom/ns#' term='init'/><title type='text'>Init script for Redmine</title><content type='html'>With my new role at work as an Infrastructure Engineer in our Projects team, I've recently started using &lt;a href="http://www.redmine.org/projects/redmine"&gt;Redmine&lt;/a&gt;, a flexible project management web application written using Ruby on Rails framework, to keep myself and my projects organised.&lt;br /&gt;&lt;br /&gt;Redmine is distributed as source and doesn't include any management scripts other than the Ruby ones used to manage Rails. In order to start and stop it automatically on boot on my Fedora 12 workstation, I'm using the following init script.&lt;br /&gt;&lt;pre&gt;#!/bin/bash&lt;br /&gt;#&lt;br /&gt;# chkconfig: - 16 84&lt;br /&gt;# description: Start up Redmine&lt;br /&gt;#&lt;br /&gt;# processname: redmine&lt;br /&gt;# config: /etc/sysconfig/redmine&lt;br /&gt;&lt;br /&gt;# source function library&lt;br /&gt;. /etc/rc.d/init.d/functions&lt;br /&gt;&lt;br /&gt;# Get network config&lt;br /&gt;. /etc/sysconfig/network&lt;br /&gt;&lt;br /&gt;[ "${NETWORKING}" = "no" ] &amp;&amp; exit 0&lt;br /&gt;&lt;br /&gt;# Defaults&lt;br /&gt;DAEMON_HOME=/usr/local/redmine&lt;br /&gt;DAEMON_ARGS="-e production -d"&lt;br /&gt;&lt;br /&gt;# Daemon&lt;br /&gt;NAME=redmine&lt;br /&gt;RUBY=$(which ruby)&lt;br /&gt;&lt;br /&gt;APP_PIDFILE=$DAEMON_HOME/tmp/pids/server.pid&lt;br /&gt;DAEMON_PIDFILE=/var/run/$NAME.pid&lt;br /&gt;DAEMON_LOCKFILE=/var/lock/subsys/$NAME&lt;br /&gt;&lt;br /&gt;start() {&lt;br /&gt;    echo -n $"Starting ${NAME}: "&lt;br /&gt;        &lt;br /&gt;    cd $DAEMON_HOME&lt;br /&gt;    $RUBY script/server webrick $DAEMON_ARGS&lt;br /&gt;&lt;br /&gt;    sleep 2&lt;br /&gt;&lt;br /&gt;    status -p $APP_PIDFILE &amp;&gt; /dev/null &amp;&amp; echo_success || echo_failure&lt;br /&gt;    RETVAL=$?&lt;br /&gt;&lt;br /&gt;    if [ $RETVAL -eq 0 ]; then&lt;br /&gt;        touch $DAEMON_LOCKFILE&lt;br /&gt;        cat $APP_PIDFILE &gt; $DAEMON_PIDFILE&lt;br /&gt;    fi&lt;br /&gt;&lt;br /&gt;    echo&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;stop() {&lt;br /&gt;    echo -n $"Shutting down ${NAME}: "&lt;br /&gt;    &lt;br /&gt;    killproc -p $DAEMON_PIDFILE&lt;br /&gt;    RETVAL=$?&lt;br /&gt;&lt;br /&gt;    [ $RETVAL -eq 0 ] &amp;&amp; /bin/rm -f $DAEMON_LOCKFILE $DAEMON_PIDFILE&lt;br /&gt;&lt;br /&gt;    echo&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;case "$1" in&lt;br /&gt;    start)&lt;br /&gt;        start&lt;br /&gt;    ;;&lt;br /&gt;    stop)&lt;br /&gt;        stop&lt;br /&gt;    ;;&lt;br /&gt;    restart)&lt;br /&gt;        stop&lt;br /&gt;        start&lt;br /&gt;    ;;&lt;br /&gt;    status)&lt;br /&gt;        status -p $DAEMON_PIDFILE $NAME&lt;br /&gt;    ;;&lt;br /&gt;&lt;br /&gt;    *)&lt;br /&gt;        echo "Usage: $SCRIPTNAME {start|stop|restart|status}" &gt;&amp;2&lt;br /&gt;        exit 3&lt;br /&gt;    ;;&lt;br /&gt;esac&lt;/pre&gt;Once you have it in place in &lt;b&gt;/etc/init.d&lt;/b&gt;, run the following commands to install it, enable Redmine startup on boot and fire it up.&lt;pre&gt;chmod +x /etc/init.d/redmine&lt;br /&gt;chkconfig --add redmine&lt;br /&gt;chkconfig redmine on&lt;br /&gt;/etc/init.d/redmine start&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1895238826710454512-371376109237297299?l=blog.friedland.id.au' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.friedland.id.au/feeds/371376109237297299/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://blog.friedland.id.au/2010/03/init-script-for-redmine.html#comment-form' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1895238826710454512/posts/default/371376109237297299'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1895238826710454512/posts/default/371376109237297299'/><link rel='alternate' type='text/html' href='http://blog.friedland.id.au/2010/03/init-script-for-redmine.html' title='Init script for Redmine'/><author><name>Jason Friedland</name><uri>http://www.blogger.com/profile/00183680637848117317</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1895238826710454512.post-5867529121456772889</id><published>2010-03-21T09:01:00.005+10:00</published><updated>2010-04-12T12:34:21.783+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='bash'/><category scheme='http://www.blogger.com/atom/ns#' term='macosx'/><title type='text'>Automatically update the Terminal window title in Mac OS X</title><content type='html'>It seems Mac OS X doesn't provide the nice Bash functionality found in RHEL/CentOS/Fedora Linux that updates the terminal title after each command. For example, using Linux, if I do the following:&lt;pre&gt;cd ~/Developer&lt;/pre&gt;the window title is updated to:&lt;pre&gt;jason@rocksteady:~/Developer&lt;/pre&gt;While the Terminal app in OS X does allow you to customize the title to some extent by adding the TTY name, name of running process etc. I prefer the 'user@host:pwd' format.&lt;br /&gt;&lt;br /&gt;After digging around in /etc/bashrc on CentOS 5, I found you can set the &lt;a href="http://tldp.org/HOWTO/Bash-Prompt-HOWTO/x264.html"&gt;PROMPT_COMMAND&lt;/a&gt; Bash variable and have your title updated after every command. &lt;br /&gt;&lt;br /&gt;Add the following to your .bash_profile in Mac OS X to get the same behaviour:&lt;pre&gt;PROMPT_COMMAND='echo -ne "\033]0;${USER}@${HOSTNAME%%.*}:${PWD/#$HOME/~}"; echo -ne "\007"'&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1895238826710454512-5867529121456772889?l=blog.friedland.id.au' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.friedland.id.au/feeds/5867529121456772889/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://blog.friedland.id.au/2010/03/automatically-update-terminal-window.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1895238826710454512/posts/default/5867529121456772889'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1895238826710454512/posts/default/5867529121456772889'/><link rel='alternate' type='text/html' href='http://blog.friedland.id.au/2010/03/automatically-update-terminal-window.html' title='Automatically update the Terminal window title in Mac OS X'/><author><name>Jason Friedland</name><uri>http://www.blogger.com/profile/00183680637848117317</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1895238826710454512.post-3286846755192351434</id><published>2010-02-27T10:07:00.007+10:00</published><updated>2010-04-12T17:46:43.635+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='dstat'/><category scheme='http://www.blogger.com/atom/ns#' term='python'/><category scheme='http://www.blogger.com/atom/ns#' term='squid'/><title type='text'>Dstat plugin for squid proxy</title><content type='html'>I've been using &lt;a href="http://dag.wieers.com/home-made/dstat/"&gt;Dag Wieers' excellent system utility Dstat&lt;/a&gt; for a little while now and have recently starting exploring the possibility of extending it with my own plugins. Dstat is written in Python and so are its plugins, so that made the possibility all the more likely for me.&lt;br /&gt;&lt;br /&gt;In case you don't know what Dstat is:&lt;blockquote&gt;Dstat is a versatile replacement for vmstat, iostat, netstat, nfsstat and ifstat. Dstat overcomes some of their limitations and adds some extra features, more counters and flexibility. Dstat is handy for monitoring systems during performance tuning tests, benchmarks or troubleshooting.&lt;br /&gt;&lt;br /&gt;Dstat allows you to view all of your system resources instantly, you can eg. compare disk usage in combination with interrupts from your IDE controller, or compare the network bandwidth numbers directly with the disk throughput (in the same interval). &lt;/blockquote&gt;Check the &lt;a href="http://dag.wieers.com/home-made/dstat/"&gt;Dstat homepage&lt;/a&gt; for more details.&lt;br /&gt;&lt;br /&gt;I was mostly interested in obtaining some useful metrics on a squid proxy and plugging them into Dstat. Using squidclient, you can get all sorts of interesting info using a command line interface and that's what I'm using to get these stats. &lt;br /&gt;&lt;br /&gt;You'll need to ensure you have manager access enabled in your squid.conf like so:&lt;pre&gt;http_access allow manager localhost  &lt;br /&gt;http_access deny manager&lt;br /&gt;&lt;/pre&gt;The metrics I've chosen to extract are just a proof-of-concept really - I'll eventually tweak them to be somewhat more useful, and this O'Reilly article &lt;a href="http://onlamp.com/pub/a/onlamp/2004/03/25/squid.html"&gt;Eleven Metrics to Monitor for a Happy and Healthy Squid&lt;/a&gt; has always proven to be a good reference. &lt;br /&gt;&lt;br /&gt;You can &lt;a href="http://github.com/thesuperjason/dstat-plugins/blob/master/dstat_squid.py"&gt;check out the dstat_squid.py plugin&lt;/a&gt; from my &lt;a href="http://github.com/thesuperjason/dstat-plugins"&gt;dstat-plugins&lt;/a&gt; GitHub repository, or copy it below.&lt;pre&gt;# Dstat plugin for measuring various squid statistics.&lt;br /&gt;# Author: Jason Friedland &amp;lt;thesuperjason@gmail.com&amp;gt;&lt;br /&gt;#&lt;br /&gt;# This plugin has been tested with:&lt;br /&gt;# - Dstat 0.6.7&lt;br /&gt;# - CentOS release 5.4 (Final)&lt;br /&gt;# - Python 2.4.3&lt;br /&gt;# - Squid 2.6 and 2.7&lt;br /&gt; &lt;br /&gt;global squidclient_options&lt;br /&gt;squidclient_options = os.getenv('DSTAT_SQUID_OPTS') # -p 8080&lt;br /&gt; &lt;br /&gt;class dstat_squid(dstat):&lt;br /&gt;    def __init__(self):&lt;br /&gt;        self.name = 'squid status'&lt;br /&gt;        self.format = ('s', 8, 100)&lt;br /&gt;        self.vars = ('Number of file desc currently in use',&lt;br /&gt;            'CPU Usage, 5 minute avg',&lt;br /&gt;            'Total accounted',&lt;br /&gt;            'Number of clients accessing cache',&lt;br /&gt;            'Mean Object Size')&lt;br /&gt;        self.nick = ('fdesc',&lt;br /&gt;            'cpu5',&lt;br /&gt;            'mem',&lt;br /&gt;            'clients',&lt;br /&gt;            'objsize')&lt;br /&gt;        self.init(self.vars, 1)&lt;br /&gt;        &lt;br /&gt;    def check(self):&lt;br /&gt;        if not os.access('/usr/sbin/squidclient', os.X_OK):&lt;br /&gt;            raise Exception, 'Needs squidclient binary'&lt;br /&gt;        return True&lt;br /&gt; &lt;br /&gt;    def extract(self):&lt;br /&gt;        try:&lt;br /&gt;            for line in os.popen('/usr/sbin/squidclient %s mgr:info' &lt;br /&gt;                    % (squidclient_options), 'r').readlines():&lt;br /&gt;                l = line.split(':')&lt;br /&gt;                for item in self.vars:&lt;br /&gt;                    if l[0].strip() == item:&lt;br /&gt;                        self.val[item] = l[1].strip()&lt;br /&gt;                        break&lt;br /&gt;        except Exception, e:&lt;br /&gt;            if op.debug &gt; 1: print '%s: exception' (self.filename, e)&lt;br /&gt;            for name in self.vars: self.val[name] = -1&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1895238826710454512-3286846755192351434?l=blog.friedland.id.au' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.friedland.id.au/feeds/3286846755192351434/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://blog.friedland.id.au/2010/02/dstat-plugin-for-squid-proxy.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1895238826710454512/posts/default/3286846755192351434'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1895238826710454512/posts/default/3286846755192351434'/><link rel='alternate' type='text/html' href='http://blog.friedland.id.au/2010/02/dstat-plugin-for-squid-proxy.html' title='Dstat plugin for squid proxy'/><author><name>Jason Friedland</name><uri>http://www.blogger.com/profile/00183680637848117317</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1895238826710454512.post-9083732032938709701</id><published>2010-02-15T14:28:00.006+10:00</published><updated>2010-04-12T17:48:00.417+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='init'/><category scheme='http://www.blogger.com/atom/ns#' term='fedora'/><category scheme='http://www.blogger.com/atom/ns#' term='transmission'/><title type='text'>Init script for transmission used in official Fedora 12 package</title><content type='html'>Thanks to an &lt;a href="https://bugzilla.redhat.com/show_bug.cgi?id=556228"&gt;RFE filed in Red Hat Bugzilla&lt;/a&gt;, my &lt;a href="http://jasonfriedland.blogspot.com/2009/07/init-script-for-transmission-daemon-on.html"&gt;transmission-daemon init script&lt;/a&gt; which was originally written for RHEL 5 has made its way into the official Fedora 12 transmission-daemon-1.83-2.fc12.i686 package.&lt;br /&gt;&lt;br /&gt;The header of the script shows:&lt;pre&gt;# This is a modified version of the original init script at &lt;br /&gt;# http://jasonfriedland.blogspot.com/2009/07/init-script-for-transmission-daemon-on.html&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1895238826710454512-9083732032938709701?l=blog.friedland.id.au' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.friedland.id.au/feeds/9083732032938709701/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://blog.friedland.id.au/2010/02/init-script-for-transmission-used-in.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1895238826710454512/posts/default/9083732032938709701'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1895238826710454512/posts/default/9083732032938709701'/><link rel='alternate' type='text/html' href='http://blog.friedland.id.au/2010/02/init-script-for-transmission-used-in.html' title='Init script for transmission used in official Fedora 12 package'/><author><name>Jason Friedland</name><uri>http://www.blogger.com/profile/00183680637848117317</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1895238826710454512.post-3453784950892660106</id><published>2010-02-10T17:49:00.005+10:00</published><updated>2010-04-12T17:48:23.344+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='python'/><category scheme='http://www.blogger.com/atom/ns#' term='squid'/><title type='text'>Python script to time HTTP requests via a proxy server</title><content type='html'>Like the title says - I just want to time HTTP requests via different proxy servers to compare response times. &lt;br /&gt;&lt;br /&gt;I hadn't really used &lt;a href="http://wiki.python.org/moin/PythonDecorators"&gt;Python decorators&lt;/a&gt; before, but once you get your head around them they're an extremely useful design pattern.&lt;pre&gt;#!/usr/bin/env python&lt;br /&gt;&lt;br /&gt;# Script to time HTTP requets via a proxy server. &lt;br /&gt;&lt;br /&gt;# Sample output:&lt;br /&gt;# proxy01 [ http://www.news.com.au ] took 222.687 ms&lt;br /&gt;# proxy01 [ http://www.google.com ] took 134.649 ms&lt;br /&gt;# proxy02 [ http://www.news.com.au ] took 1387.021 ms&lt;br /&gt;# proxy02 [ http://www.google.com ] took 4197.468 ms&lt;br /&gt;&lt;br /&gt;import urllib, time&lt;br /&gt;&lt;br /&gt;proxies = ('proxy01', 'proxy02')&lt;br /&gt;urls = ('http://www.news.com.au', 'http://www.google.com')&lt;br /&gt;&lt;br /&gt;# Decorator for timing functions&lt;br /&gt;def timer(f):&lt;br /&gt;    def wrapper(*arg):&lt;br /&gt;        t_start = time.time()&lt;br /&gt;        r = f(*arg)&lt;br /&gt;        t_finish = time.time()&lt;br /&gt;        print '%s [ %s ] took %0.3f ms' % (proxy, url, (t_finish-t_start)*1000.0)&lt;br /&gt;        return r&lt;br /&gt;    return wrapper&lt;br /&gt;&lt;br /&gt;@timer&lt;br /&gt;def testProxy(proxy, url):&lt;br /&gt;    proxy = 'http://username:password@%s.localdomain:8080' % (proxy)&lt;br /&gt;    proxy_list = {'http': proxy}&lt;br /&gt;    try:&lt;br /&gt;        f = urllib.urlopen(url, proxies=proxy_list)&lt;br /&gt;        html = f.read()&lt;br /&gt;    except URLError, e:&lt;br /&gt;        print e.reason&lt;br /&gt;&lt;br /&gt;# Main&lt;br /&gt;if __name__ == "__main__":&lt;br /&gt;    for proxy in proxies:&lt;br /&gt;        for url in urls:&lt;br /&gt;            testProxy(proxy, url)&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1895238826710454512-3453784950892660106?l=blog.friedland.id.au' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.friedland.id.au/feeds/3453784950892660106/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://blog.friedland.id.au/2010/02/python-script-to-time-http-requests-via.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1895238826710454512/posts/default/3453784950892660106'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1895238826710454512/posts/default/3453784950892660106'/><link rel='alternate' type='text/html' href='http://blog.friedland.id.au/2010/02/python-script-to-time-http-requests-via.html' title='Python script to time HTTP requests via a proxy server'/><author><name>Jason Friedland</name><uri>http://www.blogger.com/profile/00183680637848117317</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1895238826710454512.post-6181587308634001544</id><published>2010-02-07T17:51:00.007+10:00</published><updated>2010-04-12T17:48:56.164+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='linux'/><category scheme='http://www.blogger.com/atom/ns#' term='vmware'/><title type='text'>Idle CPU usage and kernel options in RHEL 5.4 VMs</title><content type='html'>I was recently having (another) read through the &lt;a href="http://kb.vmware.com/kb/1006427"&gt;VMware documentation&lt;/a&gt; on best practices for timekeeping in Linux guest virtual machines, and while the article claims that using the "divider" option in RHEL 5.4 kernels running as a VM is no longer required for accurate timekeeping, it does (quite significantly) reduce CPU usage for idle machines, as this graph clearly illustrates.&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_w8Z0kaSfeCE/S3J8TFd7W0I/AAAAAAAAAeY/PtNrPY_t6wY/s1600-h/CentOS-5.4-idle-CPU.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 128px;" src="http://4.bp.blogspot.com/_w8Z0kaSfeCE/S3J8TFd7W0I/AAAAAAAAAeY/PtNrPY_t6wY/s320/CentOS-5.4-idle-CPU.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5436544367516670786" /&gt;&lt;/a&gt;At &lt;b&gt;point 1.&lt;/b&gt; the ESX host has no running VMs, &lt;b&gt;point 2.&lt;/b&gt; has an idle vanilla 2.6.18-164.11.1 kernel running on CentOS 5.4 and &lt;b&gt;point 3.&lt;/b&gt; is the same machine with "divider=10" passed to the kernel at boot.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1895238826710454512-6181587308634001544?l=blog.friedland.id.au' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.friedland.id.au/feeds/6181587308634001544/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://blog.friedland.id.au/2010/02/idle-cpu-usage-and-kernel-options-in.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1895238826710454512/posts/default/6181587308634001544'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1895238826710454512/posts/default/6181587308634001544'/><link rel='alternate' type='text/html' href='http://blog.friedland.id.au/2010/02/idle-cpu-usage-and-kernel-options-in.html' title='Idle CPU usage and kernel options in RHEL 5.4 VMs'/><author><name>Jason Friedland</name><uri>http://www.blogger.com/profile/00183680637848117317</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_w8Z0kaSfeCE/S3J8TFd7W0I/AAAAAAAAAeY/PtNrPY_t6wY/s72-c/CentOS-5.4-idle-CPU.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1895238826710454512.post-5052206788831892668</id><published>2010-01-12T19:15:00.004+10:00</published><updated>2010-04-12T17:49:13.723+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='bash'/><title type='text'>Converting FLAC to MP3</title><content type='html'>It's been a loooong time since my last post (3 months!) which is testament to how busy I've been at work in the crazy lead-up to the New Year. It's not going to let up anytime soon, but I do endeavour to post more.&lt;br /&gt;&lt;br /&gt;Here's a nifty Bash script to &lt;a href="http://github.com/thesuperjason/media-scripts/blob/master/convert/flac2mp3"&gt;convert a directory of FLAC files to MP3&lt;/a&gt; and ID3 tag them while we're at it.&lt;br /&gt;&lt;br /&gt;Feel free to contribute!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1895238826710454512-5052206788831892668?l=blog.friedland.id.au' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.friedland.id.au/feeds/5052206788831892668/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://blog.friedland.id.au/2010/01/converting-flac-to-mp3.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1895238826710454512/posts/default/5052206788831892668'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1895238826710454512/posts/default/5052206788831892668'/><link rel='alternate' type='text/html' href='http://blog.friedland.id.au/2010/01/converting-flac-to-mp3.html' title='Converting FLAC to MP3'/><author><name>Jason Friedland</name><uri>http://www.blogger.com/profile/00183680637848117317</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1895238826710454512.post-6973449025693311526</id><published>2009-09-07T21:24:00.003+10:00</published><updated>2010-04-12T17:49:47.485+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='bash'/><category scheme='http://www.blogger.com/atom/ns#' term='handbrake'/><title type='text'>Simple bash HandBrakeCLI wrapper</title><content type='html'>Here's a simple bash shell wrapper for using &lt;a href="http://handbrake.fr/"&gt;HandBrake&lt;/a&gt; to (backup, and) encode DVD video to MP4 (this is somewhat equivalent to the 'Normal' preset).&lt;pre&gt;#!/bin/bash&lt;br /&gt;# Usage: handbrake.sh "Some Title"&lt;br /&gt;&lt;br /&gt;TITLE=$1&lt;br /&gt;MOVIE_DIR=/var/media/Movies&lt;br /&gt;&lt;br /&gt;if [ -n "$TITLE" ]; then&lt;br /&gt;    mkdir -p $MOVIE_DIR/"$TITLE"&lt;br /&gt;    /usr/bin/HandBrakeCLI -i /dev/cdrom -o $MOVIE_DIR/"$TITLE"/"$TITLE".mp4 \&lt;br /&gt;        -e x264 -b 1500 -a 1 -E faac -B 160 -L -R Auto -6 dpl2 \&lt;br /&gt;        -f mp4 -m -2 -T -x ref=2:bframes=2:me=umh&lt;br /&gt;    exit 0&lt;br /&gt;else&lt;br /&gt;    exit 1&lt;br /&gt;fi&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1895238826710454512-6973449025693311526?l=blog.friedland.id.au' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.friedland.id.au/feeds/6973449025693311526/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://blog.friedland.id.au/2009/09/simple-bash-handbrakecli-wrapper.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1895238826710454512/posts/default/6973449025693311526'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1895238826710454512/posts/default/6973449025693311526'/><link rel='alternate' type='text/html' href='http://blog.friedland.id.au/2009/09/simple-bash-handbrakecli-wrapper.html' title='Simple bash HandBrakeCLI wrapper'/><author><name>Jason Friedland</name><uri>http://www.blogger.com/profile/00183680637848117317</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1895238826710454512.post-8159577960131128576</id><published>2009-09-07T18:24:00.015+10:00</published><updated>2010-04-12T17:50:18.472+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ps3'/><category scheme='http://www.blogger.com/atom/ns#' term='linux'/><category scheme='http://www.blogger.com/atom/ns#' term='mediatomb'/><title type='text'>Configuring MediaTomb for the PS3</title><content type='html'>Having just gone out and splurged on a shiny new PS3 Slim, I've had to make some changes on my file server to cater for what I previously thought was a severe limitation of the PS3 - lack of SMB support for connecting to network shares.&lt;br /&gt;&lt;br /&gt;I've now replaced my previous media center - an XBox running the excellent XBMC - with the PS3, however the only remote shares supported by the full-HD, H.264-capable PS3 are UPnP/DLNA media servers.&lt;br /&gt;&lt;br /&gt;As mentioned, I initially considered this a limitation but you really do get so much more with a UPnP server, such as transcoding (converting media formats on-the-fly and then streaming to the client) and using media metadata (such as ID3 tags in MP3 files) for searching and browsing.&lt;br /&gt;&lt;br /&gt;Enter &lt;a href="http://mediatomb.cc/"&gt;MediaTomb&lt;/a&gt;, "an open source (GPL) UPnP MediaServer with a nice web user interface, it allows you to stream your digital media through your home network and listen to/watch it on a variety of UPnP compatible devices".&lt;br /&gt;&lt;br /&gt;Actually the web interface isn't &lt;em&gt;that&lt;/em&gt; nice but it is functional, and you only have to visit it once.&lt;br /&gt;&lt;br /&gt;My current file server is running Fedora 11 and you'll find MediaTomb in the Everything repo, but you won't have any trouble finding or installing the software on RHEL/CentOS (via &lt;a href="https://fedoraproject.org/wiki/EPEL"&gt;EPEL&lt;/a&gt;) or &lt;a href="https://help.ubuntu.com/community/MediaTomb"&gt;Ubuntu&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;There are plenty of resources to get you up and running quickly so in this post I wanted to share the specifics of my setup, especially:&lt;ul&gt;&lt;li&gt;modifying the import script to preserve a directory heirarchy&lt;/li&gt;&lt;li&gt;using transcoding to stream video within RAR archives, Flash video and other formats the PS3 doesn't understand&lt;/li&gt;&lt;/ul&gt;One of the biggest annoyances is, because your video files will most likely lack any useful metadata, they'll all just get lumped into one big folder, even if you have them neatly organised into seasons, categories or video-type on your fileserver.&lt;br /&gt;&lt;br /&gt;Photos aren't quite so bad as they at least contain some metadata and MediaTomb will organise them by date by default.&lt;br /&gt;&lt;br /&gt;This however is easily overcome by modifying the &lt;span style="font-weight: bold;"&gt;import.js&lt;/span&gt; script (in /usr/share/mediatomb/js on RHEL/CentOS/Fedora systems).&lt;br /&gt;&lt;br /&gt;I use the following JavaScript (adapted from the workaround &lt;a href="http://blogs.sun.com/ralkire/entry/home_nas_as_a_ps31"&gt;posted here&lt;/a&gt;) which replaces the addVideo() and addPhoto() functions:&lt;pre&gt;function addMedia(obj, media_type) // media_type = Photos | Video&lt;br /&gt;{&lt;br /&gt;    // Change this to suit your folder naming scheme&lt;br /&gt;    var parent_folder = media_type;&lt;br /&gt;&lt;br /&gt;    var loc = obj.location.split('/');&lt;br /&gt;    var mediaFound = false;&lt;br /&gt;    var chain = new Array(media_type);&lt;br /&gt;&lt;br /&gt;    for (i=0; i&amp;lt;loc.length-1; i++) {&lt;br /&gt;        if (mediaFound) chain.push(loc[i]);&lt;br /&gt;        if (loc[i] == parent_folder) mediaFound = true;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    str = loc[loc.length-1];&lt;br /&gt;    obj.title = str.substring(0,str.lastIndexOf('.'));&lt;br /&gt;    addCdsObject(obj, createContainerChain(chain));&lt;br /&gt;}&lt;/pre&gt;You'll need to ensure that you change the function calls in the main section of the script like so:&lt;pre&gt;if (mime == 'video')&lt;br /&gt;{&lt;br /&gt;    addMedia(obj, 'Video');&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;if (mime == 'image')&lt;br /&gt;{&lt;br /&gt;    addMedia(obj, 'Photos');&lt;br /&gt;}&lt;/pre&gt;And that your top level folders which contain your Photos and Video are named exactly "Photos" and "Video" respectively or adjust the parent_folder variable accordingly.&lt;br /&gt;&lt;br /&gt;You should now see your files neatly organised just as they appear on the filesystem of your media server.&lt;br /&gt;&lt;br /&gt;I'll follow up on this post in a day or so with the configuration and software required to get transcoding of RARs and FLVs working.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1895238826710454512-8159577960131128576?l=blog.friedland.id.au' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.friedland.id.au/feeds/8159577960131128576/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://blog.friedland.id.au/2009/09/configuring-mediatomb-for-ps3.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1895238826710454512/posts/default/8159577960131128576'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1895238826710454512/posts/default/8159577960131128576'/><link rel='alternate' type='text/html' href='http://blog.friedland.id.au/2009/09/configuring-mediatomb-for-ps3.html' title='Configuring MediaTomb for the PS3'/><author><name>Jason Friedland</name><uri>http://www.blogger.com/profile/00183680637848117317</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1895238826710454512.post-986095570305241852</id><published>2009-08-03T12:49:00.006+10:00</published><updated>2010-04-12T17:50:44.467+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='linux'/><category scheme='http://www.blogger.com/atom/ns#' term='lvm'/><category scheme='http://www.blogger.com/atom/ns#' term='ext3'/><title type='text'>More fun with Linux RAID and LVM</title><content type='html'>In an earlier post, I performed a &lt;a href="http://jasonfriedland.blogspot.com/2009/07/creating-test-raid5-lvm-storage-pool.html"&gt;test RAID5 + LVM set up&lt;/a&gt; using files instead of disks. Now I'm going to fail a 'disk', replace it in the array, and then expand the LVM logical volume to include a second RAID5 array. &lt;br /&gt;&lt;br /&gt;In this example, I'll replace out /dev/loop2 as the faulty member. So, mark it as faulty, and remove it from the array. I'll also delete the loopback device.&lt;pre&gt;mdadm /dev/md0 --fail /dev/loop2&lt;br /&gt;mdadm /dev/md0 --remove /dev/loop2&lt;br /&gt;rm /var/tmp/hdc.img&lt;br /&gt;losetup -d /dev/loop2&lt;/pre&gt;Next, create a new disk, and add it to the array:&lt;pre&gt;dd if=/dev/zero of=/var/tmp/hdc.img bs=1024 count=1048576&lt;br /&gt;losetup /dev/loop2 /var/tmp/hdc.img &lt;br /&gt;fdisk /dev/loop2&lt;br /&gt;partprobe&lt;br /&gt;mdadm /dev/md0 --add /dev/loop2&lt;/pre&gt;And the rebuild will begin. Check its progress with:&lt;pre&gt;mdadm --detail /dev/md0&lt;/pre&gt;Now follow the steps in my previous post to build a second RAID5 array and call it md1; we'll be using using it to extend our original LVM volume group.&lt;pre&gt;[root@canard ~]# vgscan&lt;br /&gt;  Reading all physical volumes.  This may take a while...&lt;br /&gt;  Found volume group "vg_media" using metadata type lvm2&lt;/pre&gt;&lt;pre&gt;pvcreate /dev/md1&lt;br /&gt;vgextend vg_media /dev/md1&lt;/pre&gt;Find the total number of extents you have available, resize the LV to that new number and grow the EXT3 filesystem for the free space on your device:&lt;pre&gt;[root@canard ~]# vgdisplay vg_media | grep "Total PE"&lt;br /&gt;  Total PE              1010&lt;/pre&gt;So we'll extend to 1010 physical extents.&lt;pre&gt;lvextend -l 1010 /dev/mapper/vg_media-lv_media &lt;br /&gt;resize2fs /dev/mapper/vg_media-lv_media&lt;/pre&gt;If all went according to plan, you should now have a ~4GB LV with no remounting required.&lt;pre&gt;[root@canard ~]# lvdisplay /dev/vg_media/lv_media&lt;br /&gt;  --- Logical volume ---&lt;br /&gt;  LV Name                /dev/vg_media/lv_media&lt;br /&gt;  VG Name                vg_media&lt;br /&gt;  LV UUID                iS01Vt-Hyo7-GIiA-Sxlu-rc5J-bX5g-Trd9Ln&lt;br /&gt;  LV Write Access        read/write&lt;br /&gt;  LV Status              available&lt;br /&gt;  # open                 1&lt;br /&gt;  LV Size                3.95 GB&lt;br /&gt;  Current LE             1010&lt;br /&gt;  Segments               2&lt;br /&gt;  Allocation             inherit&lt;br /&gt;  Read ahead sectors     auto&lt;br /&gt;  - currently set to     256&lt;br /&gt;  Block device           253:0&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1895238826710454512-986095570305241852?l=blog.friedland.id.au' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.friedland.id.au/feeds/986095570305241852/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://blog.friedland.id.au/2009/08/more-fun-with-linux-raid-and-lvm.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1895238826710454512/posts/default/986095570305241852'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1895238826710454512/posts/default/986095570305241852'/><link rel='alternate' type='text/html' href='http://blog.friedland.id.au/2009/08/more-fun-with-linux-raid-and-lvm.html' title='More fun with Linux RAID and LVM'/><author><name>Jason Friedland</name><uri>http://www.blogger.com/profile/00183680637848117317</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1895238826710454512.post-3535691882170136982</id><published>2009-08-01T11:10:00.006+10:00</published><updated>2010-04-12T17:52:11.932+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='mysql'/><category scheme='http://www.blogger.com/atom/ns#' term='bash'/><title type='text'>Simple MySQL slave monitor</title><content type='html'>Here's a simple Bash script to monitor a MySQL slave, checking that a) MySQL is running, b) the slave process is running, and c) that it's not too far behind the master. &lt;br /&gt;&lt;br /&gt;We have a database slave that gets taken down every night for backups and this script checks that it came back up OK.&lt;br /&gt;&lt;br /&gt;It's designed to be executed via cron and it runs on our production Solaris servers from around the time that the backups should finish. With a couple of minor mods (path to mysql, for instance) it runs just fine on Linux too.&lt;pre&gt;#!/bin/bash&lt;br /&gt;&lt;br /&gt;# A simple MySQL process/replication status monitor - checks for&lt;br /&gt;# a Seconds_Behind_Master threshold and that both MySQL and the &lt;br /&gt;# slave process are running.&lt;br /&gt;&lt;br /&gt;# Errors&lt;br /&gt;ERR_SLAVE_STOPPED=1&lt;br /&gt;ERR_SLAVE_OVER_THRESHOLD=2&lt;br /&gt;ERR_MYSQL_STOPPED=3&lt;br /&gt;&lt;br /&gt;ERR=0&lt;br /&gt;&lt;br /&gt;# Backup vars - if a backup's running we don't bother alerting&lt;br /&gt;BACKUP_DIR=/u07/mysql/exports&lt;br /&gt;&lt;br /&gt;# Threshold settings&lt;br /&gt;SBM_THRESHOLD=150 # Seconds behind master threshold &lt;br /&gt;PROCS_THRESHOLD=2 # Minimum number of MySQL processes&lt;br /&gt;&lt;br /&gt;# Values&lt;br /&gt;NUM_SBM=`/opt/coolstack/mysql/bin/mysql -e "SHOW SLAVE STATUS \G" \&lt;br /&gt;    | grep Seconds_Behind_Master | cut -d ":" -f 2 | sed -e 's/\ //g'`&lt;br /&gt;NUM_PROCS=`pgrep mysql | wc -l | sed -e 's/\ //g'`&lt;br /&gt;&lt;br /&gt;# Tests&lt;br /&gt;if [ "$NUM_PROCS" -lt $PROCS_THRESHOLD ]; then&lt;br /&gt;    # Check backup is running&lt;br /&gt;    if [ ! -f $BACKUP_DIR/backingup ]; then&lt;br /&gt;        MSG="There are less than $PROCS_THRESHOLD MySQL processes running"&lt;br /&gt;        ERR=$ERR_MYSQL_STOPPED&lt;br /&gt;    fi&lt;br /&gt;fi&lt;br /&gt;&lt;br /&gt;if [ "$NUM_SBM" = "NULL" ]; then&lt;br /&gt;    MSG="The slave replication process has faulted"&lt;br /&gt;    ERR=$ERR_SLAVE_STOPPED&lt;br /&gt;fi&lt;br /&gt;&lt;br /&gt;if [ "$NUM_SBM" -gt $SBM_THRESHOLD ]; then&lt;br /&gt;    MSG="The slave replication process is $NUM_SBM seconds behind the master"&lt;br /&gt;    ERR=$ERR_SLAVE_OVER_THRESHOLD&lt;br /&gt;fi&lt;br /&gt;&lt;br /&gt;# Send email if errors&lt;br /&gt;if [ $ERR -gt 0 ]; then&lt;br /&gt;    echo $MSG | mailx -s "[CRON] MySQL Errors on `hostname`" you@example.com&lt;br /&gt;    exit $ERR&lt;br /&gt;fi&lt;br /&gt;&lt;br /&gt;exit 0&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1895238826710454512-3535691882170136982?l=blog.friedland.id.au' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.friedland.id.au/feeds/3535691882170136982/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://blog.friedland.id.au/2009/08/simple-mysql-slave-monitor.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1895238826710454512/posts/default/3535691882170136982'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1895238826710454512/posts/default/3535691882170136982'/><link rel='alternate' type='text/html' href='http://blog.friedland.id.au/2009/08/simple-mysql-slave-monitor.html' title='Simple MySQL slave monitor'/><author><name>Jason Friedland</name><uri>http://www.blogger.com/profile/00183680637848117317</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1895238826710454512.post-895069182975796078</id><published>2009-07-30T15:39:00.012+10:00</published><updated>2010-02-07T18:51:39.114+10:00</updated><title type='text'>Obtain your switch port ID on a Cisco device using CDP</title><content type='html'>Here's a handy way to use &lt;a href="http://www.tcpdump.org/tcpdump_man.html"&gt;tcpdump&lt;/a&gt; to capture &lt;a href="http://en.wikipedia.org/wiki/Cisco_Discovery_Protocol"&gt;CDP&lt;/a&gt; packets from your Cisco device, which will allow you to obtain the hostname, model and IOS version as well as the switch port you're patched into. &lt;br /&gt;&lt;br /&gt;Quite useful for when you need to confirm the port but don't fancy a trip to the datacenter.&lt;pre&gt;tcpdump -c1 -s0 -XX 'ether[20:2]=0x2000'&lt;/pre&gt;The tcpdump flags are:&lt;pre&gt;-c count, capture 1 packet&lt;br /&gt;-s snaglen, 0 don't use an offset&lt;br /&gt;-XX hex and ASCII packet data, including header&lt;br /&gt;ether[20:2]=0x2000 bytes 20 to 21 of the ethernet header, value of 2000 for CDP&lt;/pre&gt;Sample output follows showing that we're patched into FastEthernet2/0/11 on a 24 port Cisco Catalyst 3750 running IOS 12.2:&lt;pre&gt;[root@canard ~]# tcpdump -c1 -s0 -XX 'ether[20:2]=0x2000'&lt;br /&gt;13:01:38.634910 CDPv2, ttl: 180s, Device-ID 'sw01.klime', length 409&lt;br /&gt;... snip ...&lt;br /&gt; 0x0040:  0005 00c5 4369 7363 6f20 494f 5320 536f  ....Cisco.IOS.So&lt;br /&gt; 0x0050:  6674 7761 7265 2c20 4333 3735 3020 536f  ftware,.C3750.So&lt;br /&gt; 0x0060:  6674 7761 7265 2028 4333 3735 302d 4144  ftware.(C3750-AD&lt;br /&gt; 0x0070:  5649 5053 4552 5649 4345 534b 392d 4d29  VIPSERVICESK9-M)&lt;br /&gt; 0x0080:  2c20 5665 7273 696f 6e20 3132 2e32 2834  ,.Version.12.2(4&lt;br /&gt; 0x0090:  3429 5345 322c 2052 454c 4541 5345 2053  4)SE2,.RELEASE.S&lt;br /&gt; 0x00a0:  4f46 5457 4152 4520 2866 6332 290a 436f  OFTWARE.(fc2).Co&lt;br /&gt; 0x00b0:  7079 7269 6768 7420 2863 2920 3139 3836  pyright.(c).1986&lt;br /&gt; 0x00c0:  2d32 3030 3820 6279 2043 6973 636f 2053  -2008.by.Cisco.S&lt;br /&gt; 0x00d0:  7973 7465 6d73 2c20 496e 632e 0a43 6f6d  ystems,.Inc..Com&lt;br /&gt; 0x00e0:  7069 6c65 6420 5468 7520 3031 2d4d 6179  piled.Thu.01-May&lt;br /&gt; 0x00f0:  2d30 3820 3135 3a34 3220 6279 2061 6e74  -08.15:42.by.ant&lt;br /&gt; 0x0100:  6f6e 696e 6f00 0600 1663 6973 636f 2057  onino....cisco.W&lt;br /&gt; 0x0110:  532d 4333 3735 302d 3234 5000 0200 1100  S-C3750-24P.....&lt;br /&gt; 0x0120:  0000 0101 01cc 0004 c0a8 05fc 0003 0016  ................&lt;br /&gt; 0x0130:  4661 7374 4574 6865 726e 6574 322f 302f  &lt;strong&gt;FastEthernet2/0/&lt;/strong&gt;&lt;br /&gt; 0x0140:  3131 0004 0008 0000 0029 0008 0024 0000  &lt;strong&gt;11&lt;/strong&gt;.......)...$..&lt;br /&gt; 0x0150:  0c01 1200 0000 00ff ffff ff01 0221 ff00  .............!..&lt;br /&gt;... snip ...&lt;/pre&gt;My Linux tcpdump version was 'ported' from the equivalent Solaris snoop command.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1895238826710454512-895069182975796078?l=blog.friedland.id.au' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.friedland.id.au/feeds/895069182975796078/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://blog.friedland.id.au/2009/07/obtain-your-switch-port-id-on-cisco.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1895238826710454512/posts/default/895069182975796078'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1895238826710454512/posts/default/895069182975796078'/><link rel='alternate' type='text/html' href='http://blog.friedland.id.au/2009/07/obtain-your-switch-port-id-on-cisco.html' title='Obtain your switch port ID on a Cisco device using CDP'/><author><name>Jason Friedland</name><uri>http://www.blogger.com/profile/00183680637848117317</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1895238826710454512.post-1481216587704559245</id><published>2009-07-30T12:35:00.003+10:00</published><updated>2009-07-30T12:44:31.380+10:00</updated><title type='text'>Matching and replacing substrings using Bash</title><content type='html'>The Bash shell has some pretty nifty tricks when it somes to substring matching and replacement. The documentation over at &lt;a href="http://tldp.org/LDP/abs/html/string-manipulation.html"&gt;TLD&lt;/a&gt; is very comprehensive but here's the gist of it:&lt;blockquote&gt;${string#substring}&lt;br /&gt;Deletes shortest match of $substring from front of $string.&lt;br /&gt;&lt;br /&gt;${string##substring}&lt;br /&gt;Deletes longest match of $substring from front of $string.&lt;br /&gt;&lt;br /&gt;${string%substring}&lt;br /&gt;Deletes shortest match of $substring from back of $string.&lt;br /&gt;&lt;br /&gt;${string%%substring}&lt;br /&gt;Deletes longest match of $substring from back of $string.&lt;/blockquote&gt;So to provide an example when working with filenames, given the following files:&lt;pre&gt;file123.txt&lt;br /&gt;file456.txt&lt;br /&gt;file789.txt&lt;/pre&gt;If I want to rename them all to be Document-123.txt, Document-456.txt etc. I could do the following:&lt;pre&gt;for f in file*; do &lt;br /&gt;    mv $f Document-${f#file}&lt;br /&gt;done&lt;/pre&gt;And to rename the extensions to .doc, it's as easy as:&lt;pre&gt;for f in Document-*; do&lt;br /&gt;    mv $f ${f%.txt}.doc&lt;br /&gt;done&lt;/pre&gt;A more practical example might be to convert all FLAC files in a directory to MP3s and rename the extensions along the way. To achieve this you'd need flac and lame installed and do something like:&lt;pre&gt;for f in *.flac; do &lt;br /&gt;    flac -cd "$f" | lame -h - "${f%.flac}.mp3"&lt;br /&gt;done&lt;/pre&gt;Easy!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1895238826710454512-1481216587704559245?l=blog.friedland.id.au' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.friedland.id.au/feeds/1481216587704559245/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://blog.friedland.id.au/2009/07/matching-and-replacing-substrings-using.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1895238826710454512/posts/default/1481216587704559245'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1895238826710454512/posts/default/1481216587704559245'/><link rel='alternate' type='text/html' href='http://blog.friedland.id.au/2009/07/matching-and-replacing-substrings-using.html' title='Matching and replacing substrings using Bash'/><author><name>Jason Friedland</name><uri>http://www.blogger.com/profile/00183680637848117317</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1895238826710454512.post-3230452292460910454</id><published>2009-07-29T17:02:00.022+10:00</published><updated>2010-04-12T17:51:10.493+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='linux'/><category scheme='http://www.blogger.com/atom/ns#' term='lvm'/><category scheme='http://www.blogger.com/atom/ns#' term='ext3'/><title type='text'>Creating a test RAID5 + LVM storage pool</title><content type='html'>I'm currently planning an upgrade to my RHEL5 Linux storage server at home which will comprise three 1TB  disks in a RAID5 configuration so there's at least some redundancy in case of a disk failure, and Logical Volume Manager (LVM) in case I decide to expand the pool down the track.&lt;br /&gt;&lt;br /&gt;I thought it'd be a good idea to do a dry run using files instead of disks just to have a clear idea of what needs to be done. &lt;br /&gt;&lt;br /&gt;There's a excellent walkthrough over at &lt;a href="http://www.gagme.com/greg/linux/raid-lvm.php"&gt;http://www.gagme.com/greg/linux/raid-lvm.php&lt;/a&gt; and that's what I based my configuration on, so check it out for a little more background info.&lt;br /&gt;&lt;br /&gt;Create three zero-filled 1GB files:&lt;pre&gt;for d in a b c; do&lt;br /&gt;    dd if=/dev/zero of=/var/tmp/hd${d}.img bs=1024 count=1048576&lt;br /&gt;done&lt;/pre&gt;Next, set up the loopback devices:&lt;pre&gt;losetup /dev/loop0 /var/tmp/hda.img &lt;br /&gt;losetup /dev/loop1 /var/tmp/hdb.img &lt;br /&gt;losetup /dev/loop2 /var/tmp/hdc.img&lt;/pre&gt;Now we're going to use fdisk to create a 'Linux raid autodetect' partition on each 'disk':&lt;pre&gt;fdisk /dev/loop0&lt;br /&gt;fdisk /dev/loop1&lt;br /&gt;fdisk /dev/loop2&lt;/pre&gt;The output should look like this, my commands in &lt;strong&gt;bold&lt;/strong&gt;. Don't forget to do a partprobe once you're done.&lt;pre&gt;[root@canard ~]# fdisk /dev/loop0&lt;br /&gt;Device contains neither a valid DOS partition table, nor Sun, SGI or OSF disklabel&lt;br /&gt;Building a new DOS disklabel. Changes will remain in memory only,&lt;br /&gt;until you decide to write them. After that, of course, the previous&lt;br /&gt;content won't be recoverable.&lt;br /&gt;&lt;br /&gt;Warning: invalid flag 0x0000 of partition table 4 will be corrected by w(rite)&lt;br /&gt;&lt;br /&gt;Command (m for help): &lt;strong&gt;n&lt;/strong&gt;&lt;br /&gt;Command action&lt;br /&gt;   e   extended&lt;br /&gt;   p   primary partition (1-4)&lt;br /&gt;&lt;strong&gt;p&lt;/strong&gt;&lt;br /&gt;Partition number (1-4): &lt;strong&gt;1&lt;/strong&gt;&lt;br /&gt;First cylinder (1-127, default 1): &lt;br /&gt;Using default value 1&lt;br /&gt;Last cylinder or +size or +sizeM or +sizeK (1-127, default 127): &lt;br /&gt;Using default value 127&lt;br /&gt;&lt;br /&gt;Command (m for help): &lt;strong&gt;t&lt;/strong&gt;&lt;br /&gt;Selected partition 1&lt;br /&gt;Hex code (type L to list codes): &lt;strong&gt;fd&lt;/strong&gt;&lt;br /&gt;Changed system type of partition 1 to fd (Linux raid autodetect)&lt;br /&gt;&lt;br /&gt;Command (m for help): &lt;strong&gt;w&lt;/strong&gt;&lt;br /&gt;The partition table has been altered!&lt;br /&gt;&lt;br /&gt;Calling ioctl() to re-read partition table.&lt;br /&gt;&lt;br /&gt;WARNING: Re-reading the partition table failed with error 22: Invalid argument.&lt;br /&gt;The kernel still uses the old table.&lt;br /&gt;The new table will be used at the next reboot.&lt;br /&gt;Syncing disks.&lt;/pre&gt;&lt;pre&gt;partprobe&lt;/pre&gt;Now we're going to set up our RAID5 array on the md0 device with the 3 disks we just prepared:&lt;pre&gt;mdadm --create /dev/md0 --level=5 --raid-devices=3 \&lt;br /&gt;    /dev/loop0 /dev/loop1 /dev/loop2&lt;/pre&gt;And that's pretty much it for the RAID part. You can view that status of your md device using mdadm or viewing the proc entry, examples follow.&lt;pre&gt;[root@canard ~]# cat /proc/mdstat &lt;br /&gt;Personalities : [raid6] [raid5] [raid4] &lt;br /&gt;md0 : active raid5 loop2[3] loop1[1] loop0[0]&lt;br /&gt;      2047872 blocks level 5, 64k chunk, algorithm 2 [3/2] [UU_]&lt;br /&gt;      [=========&gt;...........]  recovery = 46.5% (476544/1023936) finish=4.3min speed=2112K/sec&lt;/pre&gt;&lt;pre&gt;[root@canard ~]# mdadm --detail /dev/md0 &lt;br /&gt;/dev/md0:&lt;br /&gt;        Version : 00.90.03&lt;br /&gt;  Creation Time : Wed Jul 29 11:46:47 2009&lt;br /&gt;     Raid Level : raid5&lt;br /&gt;     Array Size : 2047872 (2000.21 MiB 2097.02 MB)&lt;br /&gt;  Used Dev Size : 1023936 (1000.11 MiB 1048.51 MB)&lt;br /&gt;   Raid Devices : 3&lt;br /&gt;  Total Devices : 3&lt;br /&gt;Preferred Minor : 0&lt;br /&gt;    Persistence : Superblock is persistent&lt;br /&gt;&lt;br /&gt;    Update Time : Wed Jul 29 11:46:47 2009&lt;br /&gt;          State : clean, degraded, recovering&lt;br /&gt; Active Devices : 2&lt;br /&gt;Working Devices : 3&lt;br /&gt; Failed Devices : 0&lt;br /&gt;  Spare Devices : 1&lt;br /&gt;&lt;br /&gt;         Layout : left-symmetric&lt;br /&gt;     Chunk Size : 64K&lt;br /&gt;&lt;br /&gt; Rebuild Status : 53% complete&lt;br /&gt;&lt;br /&gt;           UUID : 1744c4be:0566a9ee:8a056ff6:bd165eb4&lt;br /&gt;         Events : 0.1&lt;br /&gt;&lt;br /&gt;    Number   Major   Minor   RaidDevice State&lt;br /&gt;       0       7        0        0      active sync   /dev/loop0&lt;br /&gt;       1       7        1        1      active sync   /dev/loop1&lt;br /&gt;       3       7        2        2      spare rebuilding   /dev/loop2&lt;/pre&gt;As you can see, md is in the process of building the array. Now it's time to configure the LVM side of things. &lt;br /&gt;&lt;br /&gt;First create a PV (physical volume), then a VG (volume group) consisting of your PV, then a LV (logical volume) on top of your VG. &lt;br /&gt;&lt;br /&gt;It's probably a good idea to check out the &lt;a href="http://tldp.org/HOWTO/LVM-HOWTO/"&gt;LVM docs&lt;/a&gt; prior to commencing this step to gain a good understanding of what it is and does. &lt;br /&gt;&lt;br /&gt;You could just as easily leave things here and format the md0 device as ext3, mount it, and you'd be done. But we're not doing that just yet. So, onwards:&lt;pre&gt;pvcreate /dev/md0&lt;br /&gt;vgcreate vg_media /dev/md0&lt;/pre&gt;Now display some info on your VG - the output should look a little like this - pay special attention to the number of PE (physical extents) you have available:&lt;pre&gt;[root@canard ~]# vgdisplay vg_media&lt;br /&gt;  --- Volume group ---&lt;br /&gt;  VG Name               vg_media&lt;br /&gt;  System ID             &lt;br /&gt;  Format                lvm2&lt;br /&gt;  Metadata Areas        1&lt;br /&gt;  Metadata Sequence No  2&lt;br /&gt;  VG Access             read/write&lt;br /&gt;  VG Status             resizable&lt;br /&gt;  MAX LV                0&lt;br /&gt;  Cur LV                1&lt;br /&gt;  Open LV               1&lt;br /&gt;  Max PV                0&lt;br /&gt;  Cur PV                1&lt;br /&gt;  Act PV                1&lt;br /&gt;  VG Size               1.95 GB&lt;br /&gt;  PE Size               4.00 MB&lt;br /&gt;  &lt;strong&gt;Total PE              499&lt;/strong&gt; &lt;br /&gt;  Alloc PE / Size       499 / 1.95 GB&lt;br /&gt;  Free  PE / Size       0 / 0   &lt;br /&gt;  VG UUID               2rsx3T-C1Lx-uMRf-kz1g-UyBP-tbTz-iC7K1f&lt;/pre&gt;OK so now we can go ahead and create the LV using the value for logical extents we obtained from the previous command:&lt;pre&gt;lvcreate -l 499 vg_media -n lv_media&lt;/pre&gt;And again, display some information:&lt;pre&gt;[root@canard ~]# lvdisplay /dev/vg_media/lv_media&lt;br /&gt;  --- Logical volume ---&lt;br /&gt;  LV Name                /dev/vg_media/lv_media&lt;br /&gt;  VG Name                vg_media&lt;br /&gt;  LV UUID                iS01Vt-Hyo7-GIiA-Sxlu-rc5J-bX5g-Trd9Ln&lt;br /&gt;  LV Write Access        read/write&lt;br /&gt;  LV Status              available&lt;br /&gt;  # open                 1&lt;br /&gt;  LV Size                1.95 GB&lt;br /&gt;  Current LE             499&lt;br /&gt;  Segments               1&lt;br /&gt;  Allocation             inherit&lt;br /&gt;  Read ahead sectors     auto&lt;br /&gt;  - currently set to     256&lt;br /&gt;  Block device           253:0&lt;/pre&gt;We're nearly done! All that's left to do is format and mount the LV:&lt;pre&gt;mkfs.ext3 /dev/vg_media/lv_media&lt;br /&gt;mkdir /mnt/lvtest&lt;br /&gt;mount /dev/vg_media/lv_media /mnt/lvtest&lt;/pre&gt;You'll notice that df reports the parity space as being used already, so out of the 3GB we should have around 2GB available for use:&lt;pre&gt;[root@canard ~]# df -h /mnt/lvtest/&lt;br /&gt;Filesystem            Size  Used Avail Use% Mounted on&lt;br /&gt;/dev/mapper/vg_media-lv_media&lt;br /&gt;                      2.0G   35M  1.8G   2% /mnt/lvtest&lt;/pre&gt;Next I'll be &lt;a href="http://jasonfriedland.blogspot.com/2009/08/more-fun-with-linux-raid-and-lvm.html"&gt;failing a disk and expanding the LV to incorporate a second RAID5 array&lt;/a&gt;. As ever, stay tuned.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1895238826710454512-3230452292460910454?l=blog.friedland.id.au' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.friedland.id.au/feeds/3230452292460910454/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://blog.friedland.id.au/2009/07/creating-test-raid5-lvm-storage-pool.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1895238826710454512/posts/default/3230452292460910454'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1895238826710454512/posts/default/3230452292460910454'/><link rel='alternate' type='text/html' href='http://blog.friedland.id.au/2009/07/creating-test-raid5-lvm-storage-pool.html' title='Creating a test RAID5 + LVM storage pool'/><author><name>Jason Friedland</name><uri>http://www.blogger.com/profile/00183680637848117317</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1895238826710454512.post-1323614616970858395</id><published>2009-07-26T10:20:00.011+10:00</published><updated>2009-08-02T12:28:28.950+10:00</updated><title type='text'>Installing and configuring SNMP on OpenSolaris</title><content type='html'>SNMP is installed and run slightly differently on OpenSolaris than on Solaris 10, so here's the basics on what you need to know.&lt;br /&gt;&lt;br /&gt;Firstly, you'll need to install the &lt;strong&gt;SUNWsmmgr&lt;/strong&gt; package.&lt;pre&gt;pkg install SUNWsmmgr&lt;/pre&gt;All of the config files, including &lt;strong&gt;snmpd.conf&lt;/strong&gt; have moved to &lt;strong&gt;/etc/sma/snmp&lt;/strong&gt;.&lt;br /&gt;&lt;br /&gt;The service you need to run is now called &lt;strong&gt;sma&lt;/strong&gt;.&lt;pre&gt;svcadm enable svc:/application/management/sma:default&lt;/pre&gt;Stay tuned as I'm currently setting up iSCSI targets on my OpenSolaris server at home and will be running the initiator from a RHEL5 box.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1895238826710454512-1323614616970858395?l=blog.friedland.id.au' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.friedland.id.au/feeds/1323614616970858395/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://blog.friedland.id.au/2009/07/installing-and-configuring-snmp-on.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1895238826710454512/posts/default/1323614616970858395'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1895238826710454512/posts/default/1323614616970858395'/><link rel='alternate' type='text/html' href='http://blog.friedland.id.au/2009/07/installing-and-configuring-snmp-on.html' title='Installing and configuring SNMP on OpenSolaris'/><author><name>Jason Friedland</name><uri>http://www.blogger.com/profile/00183680637848117317</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1895238826710454512.post-4806181963470337605</id><published>2009-07-20T13:37:00.014+10:00</published><updated>2010-04-12T17:51:48.069+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='linux'/><category scheme='http://www.blogger.com/atom/ns#' term='init'/><category scheme='http://www.blogger.com/atom/ns#' term='transmission'/><title type='text'>Init script for transmission-daemon</title><content type='html'>The RPM for the &lt;a href="http://www.transmissionbt.com/"&gt;Transmission&lt;/a&gt; bittorrent client version 1.34 in EPEL, or 1.72 in Fedora 11 don't include an init script for the daemon. Since that's all I use, I wrote my own.&lt;br /&gt;&lt;br /&gt;EDIT: Thanks to a helpful comment below, I've modified the script around the TRANSMISSION_HOME variable to fix config options being dropped on a restart.&lt;br /&gt;&lt;br /&gt;Also, you can edit the &lt;span style="font-weight:bold;"&gt;settings.json&lt;/span&gt; file in the config dir to further customise your install. See the wiki for help &lt;a href="http://trac.transmissionbt.com/wiki/EditConfigFiles"&gt;editing config files&lt;/a&gt;.&lt;pre&gt;#!/bin/bash&lt;br /&gt;#&lt;br /&gt;# chkconfig: - 16 84&lt;br /&gt;# description: Start up transmission-daemon&lt;br /&gt;#&lt;br /&gt;# processname: transmission-daemon&lt;br /&gt;# config: /etc/sysconfig/transmission&lt;br /&gt;&lt;br /&gt;# source function library&lt;br /&gt;. /etc/rc.d/init.d/functions&lt;br /&gt;&lt;br /&gt;# Get network config&lt;br /&gt;. /etc/sysconfig/network&lt;br /&gt;&lt;br /&gt;[ "${NETWORKING}" = "no" ] &amp;&amp; exit 0&lt;br /&gt;&lt;br /&gt;# Defaults&lt;br /&gt;TRANSMISSION_HOME=/var/lib/transmission&lt;br /&gt;&lt;br /&gt;DAEMON_USER="transmission"&lt;br /&gt;DAEMON_ARGS="-T --blocklist -g $TRANSMISSION_HOME/.config/transmission"&lt;br /&gt;&lt;br /&gt;# Daemon&lt;br /&gt;NAME=transmission-daemon&lt;br /&gt;&lt;br /&gt;DAEMON=$(which $NAME)&lt;br /&gt;DAEMON_PIDFILE=/var/run/$NAME.pid&lt;br /&gt;DAEMON_LOCKFILE=/var/lock/subsys/$NAME&lt;br /&gt;DAEMON_SCRIPTNAME=/etc/init.d/$NAME&lt;br /&gt;DAEMON_LOGFILE=/var/log/$NAME.log&lt;br /&gt;&lt;br /&gt;[ -x "$DAEMON" ] || exit 0&lt;br /&gt;&lt;br /&gt;start() {&lt;br /&gt;    echo -n $"Starting ${NAME}: "&lt;br /&gt;    &lt;br /&gt;    if [ -n "$TRANSMISSION_HOME" ]; then&lt;br /&gt;        export TRANSMISSION_HOME&lt;br /&gt;    fi&lt;br /&gt;&lt;br /&gt;    su - $DAEMON_USER -c "$DAEMON $DAEMON_ARGS"&lt;br /&gt;&lt;br /&gt;    sleep 2&lt;br /&gt;&lt;br /&gt;    status $NAME &amp;&gt; /dev/null &amp;&amp; echo_success || echo_failure&lt;br /&gt;    RETVAL=$?&lt;br /&gt;&lt;br /&gt;    if [ $RETVAL -eq 0 ]; then&lt;br /&gt;        touch $DAEMON_LOCKFILE&lt;br /&gt;        pidof -o %PPID -x $NAME &gt; $DAEMON_PIDFILE&lt;br /&gt;    fi&lt;br /&gt;&lt;br /&gt;    echo&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;stop() {&lt;br /&gt;    echo -n $"Shutting down ${NAME}: "&lt;br /&gt;    &lt;br /&gt;    killproc $NAME&lt;br /&gt;    RETVAL=$?&lt;br /&gt;&lt;br /&gt;    [ $RETVAL -eq 0 ] &amp;&amp; /bin/rm -f $DAEMON_LOCKFILE $DAEMON_PIDFILE&lt;br /&gt;&lt;br /&gt;    echo&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;case "$1" in&lt;br /&gt;    start)&lt;br /&gt;        start&lt;br /&gt;    ;;&lt;br /&gt;    stop)&lt;br /&gt;        stop&lt;br /&gt;    ;;&lt;br /&gt;    restart)&lt;br /&gt;        stop&lt;br /&gt;        start&lt;br /&gt;    ;;&lt;br /&gt;    status)&lt;br /&gt;        status $NAME&lt;br /&gt;    ;;&lt;br /&gt;&lt;br /&gt;    *)&lt;br /&gt;        echo "Usage: $SCRIPTNAME {start|stop|restart|status}" &gt;&amp;2&lt;br /&gt;        exit 3&lt;br /&gt;    ;;&lt;br /&gt;esac&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1895238826710454512-4806181963470337605?l=blog.friedland.id.au' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.friedland.id.au/feeds/4806181963470337605/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://blog.friedland.id.au/2009/07/init-script-for-transmission-daemon-on.html#comment-form' title='13 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1895238826710454512/posts/default/4806181963470337605'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1895238826710454512/posts/default/4806181963470337605'/><link rel='alternate' type='text/html' href='http://blog.friedland.id.au/2009/07/init-script-for-transmission-daemon-on.html' title='Init script for transmission-daemon'/><author><name>Jason Friedland</name><uri>http://www.blogger.com/profile/00183680637848117317</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>13</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1895238826710454512.post-7644337563226423839</id><published>2009-07-15T19:14:00.014+10:00</published><updated>2010-02-11T11:46:42.086+10:00</updated><title type='text'>Backing up F5 Big-IP device configuration</title><content type='html'>At my place of work we have a number F5 Big-IP devices which are used for load-balancing, failover, SSL offloading, application health monitoring and persistence. They are, quite simply, awesome. &lt;br /&gt;&lt;br /&gt;Each device forms one of an HA Active/Standby pair and naturally, we keep nightly backups of each pair's configuration.&lt;br /&gt;&lt;br /&gt;You can get the full blurb from the &lt;a href="http://www.f5.com/products/big-ip/"&gt;F5 website&lt;/a&gt;, but Big-IPs have a Linux-based service console and while they offer a web GUI for easy configuration, they also sport a fully-featured CLI and Bash shell via SSH. &lt;br /&gt;&lt;br /&gt;This makes it very simple to automate backing them up using standard Linux sysadmin tools.&lt;br /&gt;&lt;br /&gt;I'm sharing with you two Bash scripts - one resides on your management server and the other is installed on all your F5s which is then called by your nightly management script.&lt;br /&gt;&lt;br /&gt;You'll need to &lt;a href="http://www.google.com.au/search?q=set+up+ssh+keys"&gt;set up SSH keys&lt;/a&gt; to make this work.&lt;br /&gt;&lt;br /&gt;Here's the management cron script:&lt;pre&gt;#!/bin/bash&lt;br /&gt;&lt;br /&gt;# This script is run on your management server. It executes the backup script on each &lt;br /&gt;# devices and rsync's the saved files over.&lt;br /&gt;&lt;br /&gt;F5_ALL="host1 host2"&lt;br /&gt;&lt;br /&gt;cd /home/backupadm/f5&lt;br /&gt;&lt;br /&gt;for HOST in $F5_ALL; do&lt;br /&gt;    echo "Backing up $HOST ... "&lt;br /&gt;    ssh root@$HOST 'sh /root/bin/backup.sh'&lt;br /&gt;    rsync -avz -e '/usr/bin/ssh' root@$HOST:/var/local/ucs/daily.* backups/&lt;br /&gt;    echo&lt;br /&gt;done&lt;br /&gt;&lt;br /&gt;# Purge expired backups&lt;br /&gt;find ./backups/ -name "daily.*" -mtime +30 -exec rm -f {} \;&lt;br /&gt;&lt;/pre&gt;And the F5 script:&lt;pre&gt;#!/bin/bash&lt;br /&gt;&lt;br /&gt;# Install this script as /root/bin/backup.sh on all F5 devices.&lt;br /&gt;&lt;br /&gt;# See: https://support.f5.com/kb/en-us/solutions/public/3000/400/sol3499.html&lt;br /&gt;# for details on backing up F5 configs.&lt;br /&gt;&lt;br /&gt;cd /var/local/ucs&lt;br /&gt;&lt;br /&gt;# Purge expired backups&lt;br /&gt;find ./ -name "daily.*" -mtime +7 -exec rm -f {} \;&lt;br /&gt;&lt;br /&gt;# This the bigpipe utility - man bigpipe&lt;br /&gt;/bin/bigpipe config save daily.$(/bin/hostname).$(/bin/date +%F)&lt;br /&gt;&lt;br /&gt;# Check state for config sync "active | standby" and pull if we're the standby&lt;br /&gt;if [ $(/bin/bigpipe failover show | awk '{ print $2 }') = "standby" ]; then&lt;br /&gt;    /bin/bigpipe config sync pull    &lt;br /&gt;fi&lt;br /&gt;&lt;/pre&gt;You'll notice at the end of the last script that I perform an automatic pull of the Active device configuration to the Standby as well - this may or may not be necessary for your installation.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1895238826710454512-7644337563226423839?l=blog.friedland.id.au' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.friedland.id.au/feeds/7644337563226423839/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://blog.friedland.id.au/2009/07/backing-up-f5-big-ip-device.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1895238826710454512/posts/default/7644337563226423839'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1895238826710454512/posts/default/7644337563226423839'/><link rel='alternate' type='text/html' href='http://blog.friedland.id.au/2009/07/backing-up-f5-big-ip-device.html' title='Backing up F5 Big-IP device configuration'/><author><name>Jason Friedland</name><uri>http://www.blogger.com/profile/00183680637848117317</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1895238826710454512.post-1389900259464362613</id><published>2009-07-15T18:18:00.011+10:00</published><updated>2009-07-27T19:07:29.168+10:00</updated><title type='text'>Simple disk threshold check</title><content type='html'>Whew, it's been a while since my last post. I'll ease back into things with this very simple disk threshold check which you could run via cron. It works (has only been tested) on Linux.&lt;br /&gt;&lt;br /&gt;It's... well, simple.&lt;pre&gt;#!/bin/bash&lt;br /&gt;&lt;br /&gt;# Threshold usage in %&lt;br /&gt;threshold=90&lt;br /&gt;&lt;br /&gt;# Admin email&lt;br /&gt;email="you@example.org"&lt;br /&gt;&lt;br /&gt;df -l | while read l; do&lt;br /&gt;    usage=$(echo $l | awk '{ print $5 }' | sed -e 's/%//')&lt;br /&gt;    if [ $usage -gt $threshold ]; then&lt;br /&gt;        df -l | mail -s "[CRON] $(hostname) Disk Alert - ${threshold}% threshold exceeded" $email&lt;br /&gt;        break&lt;br /&gt;    fi&lt;br /&gt;done&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1895238826710454512-1389900259464362613?l=blog.friedland.id.au' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.friedland.id.au/feeds/1389900259464362613/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://blog.friedland.id.au/2009/07/simple-disk-threshold-check.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1895238826710454512/posts/default/1389900259464362613'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1895238826710454512/posts/default/1389900259464362613'/><link rel='alternate' type='text/html' href='http://blog.friedland.id.au/2009/07/simple-disk-threshold-check.html' title='Simple disk threshold check'/><author><name>Jason Friedland</name><uri>http://www.blogger.com/profile/00183680637848117317</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1895238826710454512.post-5042004344218074454</id><published>2009-06-17T11:55:00.011+10:00</published><updated>2009-07-27T19:18:16.485+10:00</updated><title type='text'>Parsing CLI options in Python</title><content type='html'>Python makes performing common scripting tasks easy - the batteries are included, as they say.&lt;br /&gt; &lt;br /&gt;Here's a simple script to connect to a host on a given TCP port using a specified timeout. It's designed to be run from the command line, and using the &lt;span style="font-weight:bold;"&gt;optparse&lt;/span&gt; module parsing options passed to the script is trivial.&lt;br /&gt; &lt;br /&gt;The script returns a non-zero value on failure, and optionally prints an informative message; it was originally written to be called by other programs, such as shell scripts, to test connectivity prior to executing other routines.&lt;br /&gt;&lt;br /&gt;The Python docs have &lt;a href="http://docs.python.org/dev/library/optparse.html"&gt;more info on the optparse module&lt;/a&gt;. &lt;br /&gt;&lt;br /&gt;Example usage is as follows:&lt;pre&gt;$ ./conn.py --ip 192.168.0.1 --port 1234 --timeout 5 -v&lt;/pre&gt;And here's the script:&lt;pre&gt;#!/usr/bin/env python&lt;br /&gt;&lt;br /&gt;import socket, sys, optparse&lt;br /&gt; &lt;br /&gt;p = optparse.OptionParser()&lt;br /&gt; &lt;br /&gt;# CLI Options&lt;br /&gt;p.add_option('-i', '--ip', action='store', type='string', dest='ip')&lt;br /&gt;p.add_option('-p', '--port', action='store', type='int', dest='port')&lt;br /&gt;p.add_option('-t', '--timeout', action='store', type='int', dest='timeout', default=1)&lt;br /&gt;p.add_option('-v', '--verbose', action='store_true', dest='verbose', default=False)&lt;br /&gt; &lt;br /&gt;(o, args) = p.parse_args()&lt;br /&gt; &lt;br /&gt;# Require IP and port&lt;br /&gt;if not o.ip or not o.port:&lt;br /&gt;    sys.stderr.write("Try -h for help \n")&lt;br /&gt;    sys.exit(255)&lt;br /&gt; &lt;br /&gt;s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)&lt;br /&gt;s.settimeout(o.timeout)&lt;br /&gt; &lt;br /&gt;try:&lt;br /&gt;    s.connect((o.ip, o.port))&lt;br /&gt;except socket.error, e:&lt;br /&gt;    if o.verbose:&lt;br /&gt;        sys.stderr.write("Connect to %s on port %i - FAIL \n" % (o.ip, o.port))&lt;br /&gt;    sys.exit(1)&lt;br /&gt;else:&lt;br /&gt;    if o.verbose:&lt;br /&gt;        sys.stdout.write("Connect to %s on port %i - PASS \n" % (o.ip, o.port))&lt;br /&gt;    sys.exit(0)&lt;br /&gt;finally:&lt;br /&gt;    s.close()&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1895238826710454512-5042004344218074454?l=blog.friedland.id.au' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.friedland.id.au/feeds/5042004344218074454/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://blog.friedland.id.au/2009/06/parsing-cli-options-in-python.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1895238826710454512/posts/default/5042004344218074454'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1895238826710454512/posts/default/5042004344218074454'/><link rel='alternate' type='text/html' href='http://blog.friedland.id.au/2009/06/parsing-cli-options-in-python.html' title='Parsing CLI options in Python'/><author><name>Jason Friedland</name><uri>http://www.blogger.com/profile/00183680637848117317</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1895238826710454512.post-8506719615031651049</id><published>2009-05-27T17:44:00.003+10:00</published><updated>2009-07-27T19:19:42.504+10:00</updated><title type='text'>Use ipcalc to calculate a broadcast, network and netmask</title><content type='html'>The &lt;strong&gt;ipcalc&lt;/strong&gt; utility is included with the &lt;strong&gt;initscripts&lt;/strong&gt; package on all RHEL/CentOS/Fedora systems. Here's a simple script to calculate the broadcast, netmask and network given an IP address in &lt;a href="http://en.wikipedia.org/wiki/CIDR"&gt;CIDR notation&lt;/a&gt;:&lt;pre&gt;#!/bin/bash&lt;br /&gt; &lt;br /&gt;echo -n "Enter IP address in CIDR notation: (eg. 192.168.0.0/24) "&lt;br /&gt;read IP_ADDRESS&lt;br /&gt; &lt;br /&gt;# Calculate network values&lt;br /&gt;BROADCAST=$(ipcalc -b $IP_ADDRESS)&lt;br /&gt;NETWORK=$(ipcalc -n $IP_ADDRESS)&lt;br /&gt;NETMASK=$(ipcalc -m $IP_ADDRESS)&lt;br /&gt; &lt;br /&gt;echo "Set up your ifcfg file with the following values:"&lt;br /&gt;echo $BROADCAST&lt;br /&gt;echo $NETWORK&lt;br /&gt;echo $NETMASK&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1895238826710454512-8506719615031651049?l=blog.friedland.id.au' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.friedland.id.au/feeds/8506719615031651049/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://blog.friedland.id.au/2009/05/use-ipcalc-to-calculate-broadcast.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1895238826710454512/posts/default/8506719615031651049'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1895238826710454512/posts/default/8506719615031651049'/><link rel='alternate' type='text/html' href='http://blog.friedland.id.au/2009/05/use-ipcalc-to-calculate-broadcast.html' title='Use ipcalc to calculate a broadcast, network and netmask'/><author><name>Jason Friedland</name><uri>http://www.blogger.com/profile/00183680637848117317</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1895238826710454512.post-3302570253218037744</id><published>2009-05-21T18:31:00.013+10:00</published><updated>2009-07-27T19:09:50.188+10:00</updated><title type='text'>Using at for one-off scheduled tasks</title><content type='html'>When you think of scheduled tasks on a Linux/Unix host, you think... cron, right? &lt;br /&gt;&lt;br /&gt;For one-off jobs using &lt;strong&gt;at&lt;/strong&gt; is much quicker, easier and simpler, plus there's no danger of you leaving an unwanted entry in your crontab once the job is complete.&lt;br /&gt;&lt;br /&gt;For example, say you need to take down a server for maintenance at 2am. And if you're anything like me, you don't want to have to get out of bed.&lt;pre&gt;[jason@bonito ~]$ at 2am tomorrow&lt;br /&gt;/sbin/shutdown -h 2 "System going down for maintenance in 2 minutes."&lt;br /&gt;job 2 at Fri May 22 02:00:00 2009&lt;/pre&gt;Easy. To view the details of the job, use &lt;strong&gt;atq&lt;/strong&gt;.&lt;pre&gt;[jason@bonito ~]$ atq&lt;br /&gt;2 Fri May 22 02:00:00 2009&lt;/pre&gt;To view the job itself, that is how it will run as a shell script, use the &lt;strong&gt;-c&lt;/strong&gt; flag followed by the job spec (which is 2 in our example). To remove a job, use &lt;strong&gt;atrm&lt;/strong&gt; or the &lt;strong&gt;-r&lt;/strong&gt; flag.&lt;br /&gt;&lt;br /&gt;Time specifications are well documented - from the man page:&lt;blockquote&gt;For example, to run a job at 4pm three days from now, use at 4pm + 3 days, to run a job at 10:00am on July 31, use at 10am Jul 31 and to run a job at 1am tomorrow, use at 1am tomorrow. The at utility also supports the POSIX time format (see -t option).&lt;br /&gt;&lt;/blockquote&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1895238826710454512-3302570253218037744?l=blog.friedland.id.au' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.friedland.id.au/feeds/3302570253218037744/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://blog.friedland.id.au/2009/05/using-at-for-one-off-scheduled-tasks.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1895238826710454512/posts/default/3302570253218037744'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1895238826710454512/posts/default/3302570253218037744'/><link rel='alternate' type='text/html' href='http://blog.friedland.id.au/2009/05/using-at-for-one-off-scheduled-tasks.html' title='Using at for one-off scheduled tasks'/><author><name>Jason Friedland</name><uri>http://www.blogger.com/profile/00183680637848117317</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1895238826710454512.post-986482986393308409</id><published>2009-05-19T18:08:00.003+10:00</published><updated>2009-07-27T19:08:36.298+10:00</updated><title type='text'>Send a binary file as an attachment to an email</title><content type='html'>Here's a quick little one-liner I posted over at &lt;a href="http://www.commandlinefu.com/"&gt;http://www.commandlinefu.com/&lt;/a&gt; on how to send a binary file, such as an archive or image as an attachment to an email from the command line.&lt;br /&gt;&lt;br /&gt;You'll need the &lt;strong&gt;sharutils&lt;/strong&gt; package installed on a RHEL/CentOS/Fedora system and of course a working MTA.&lt;br /&gt;&lt;br /&gt;So, here it is:&lt;pre&gt;uuencode archive.tar.gz archive.tar.gz \&lt;br /&gt;    | mail -s "Emailing: archive.tar.gz" user@example.com&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1895238826710454512-986482986393308409?l=blog.friedland.id.au' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.friedland.id.au/feeds/986482986393308409/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://blog.friedland.id.au/2009/05/send-binary-file-as-attachment-to-email.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1895238826710454512/posts/default/986482986393308409'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1895238826710454512/posts/default/986482986393308409'/><link rel='alternate' type='text/html' href='http://blog.friedland.id.au/2009/05/send-binary-file-as-attachment-to-email.html' title='Send a binary file as an attachment to an email'/><author><name>Jason Friedland</name><uri>http://www.blogger.com/profile/00183680637848117317</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1895238826710454512.post-7402327590506097767</id><published>2009-04-24T08:47:00.006+10:00</published><updated>2009-07-27T19:09:27.059+10:00</updated><title type='text'>SSH hostname autocomplete</title><content type='html'>At my place of work I have over 200 servers to manage, and while most of our management/admin/update processes are automated in some way, I'm incredibly lazy (not in the pejorative sense of course) I use the following line in my &lt;strong&gt;~/.bashrc&lt;/strong&gt; to do hostname autocompletion for the &lt;strong&gt;ssh&lt;/strong&gt; command.&lt;br /&gt;&lt;br /&gt;This tip probably won't work for Ubuntu users whose &lt;strong&gt;~/.ssh/known_hosts&lt;/strong&gt; file uses hashed hostnames by default. In Red Hat and Fedora it works just fine.&lt;pre&gt;complete -W "$(echo $(cat ~/.ssh/known_hosts | \&lt;br /&gt;    cut -f 1 -d ' ' | sed -e s/,.*//g | \&lt;br /&gt;    sort -u | grep -v "\["))" ssh&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1895238826710454512-7402327590506097767?l=blog.friedland.id.au' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.friedland.id.au/feeds/7402327590506097767/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://blog.friedland.id.au/2009/04/ssh-hostname-autocomplete.html#comment-form' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1895238826710454512/posts/default/7402327590506097767'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1895238826710454512/posts/default/7402327590506097767'/><link rel='alternate' type='text/html' href='http://blog.friedland.id.au/2009/04/ssh-hostname-autocomplete.html' title='SSH hostname autocomplete'/><author><name>Jason Friedland</name><uri>http://www.blogger.com/profile/00183680637848117317</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1895238826710454512.post-3370952582248020870</id><published>2009-04-15T17:41:00.015+10:00</published><updated>2009-07-27T19:19:08.271+10:00</updated><title type='text'>Bitbucket and pid, a simple PID file handler</title><content type='html'>Whilst on my current bent of all things Python, Mercurial and RPM, I stumbled across &lt;a href="http://bitbucket.org/"&gt;Bitbucket&lt;/a&gt; "&lt;em&gt;a place for you and your team to host and follow your Mercurial projects&lt;/em&gt;". &lt;br /&gt;&lt;br /&gt;You can access your repositories via SSH or HTTPS and projects feature a Wiki, Bug tracker and Source code browser. Bitbucket is written using the &lt;a href="http://www.djangoproject.com/"&gt;Django&lt;/a&gt; web framework. &lt;br /&gt;&lt;br /&gt;You get one free private repository and unlimited public ones that are limited to 150MB in size, with paid plans also being available.&lt;br /&gt;&lt;br /&gt;I'll let you get acquainted with its more intricate features, but to do so I uploaded &lt;strong&gt;pid&lt;/strong&gt;, a simple Python module I've written to handle PID (Process ID) files in my scripts.&lt;br /&gt;&lt;br /&gt;You can &lt;a href="http://bitbucket.org/thesuperjason/pid/src/"&gt;browse the source code&lt;/a&gt;, &lt;a href="http://bitbucket.org/thesuperjason/pid/wiki"&gt;view the Wiki&lt;/a&gt; (very spartan), or &lt;a href="http://bitbucket.org/thesuperjason/pid/downloads/"&gt;download a source RPM or Python egg&lt;/a&gt;. &lt;br /&gt;&lt;br /&gt;It's simple to use where you need to ensure that a script never runs as 2 concurrent processes:&lt;pre&gt;from pid import Pid, FileExistsError, FileDoesNotExistError&lt;br /&gt;import sys&lt;br /&gt;&lt;br /&gt;p = Pid('/tmp/test.pid')&lt;br /&gt; &lt;br /&gt;try:&lt;br /&gt;    p.start()&lt;br /&gt;except FileExistsError, e:&lt;br /&gt;    print e&lt;br /&gt;    sys.exit(1)&lt;br /&gt;  &lt;br /&gt;# [ ... do stuff ...]&lt;br /&gt;&lt;br /&gt;try:&lt;br /&gt;    p.finish()&lt;br /&gt;except FileDoesNotExistError, e:&lt;br /&gt;    print e&lt;/pre&gt;Please feel free to contribute, ridicule or provide any other feedback as you see fit.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1895238826710454512-3370952582248020870?l=blog.friedland.id.au' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.friedland.id.au/feeds/3370952582248020870/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://blog.friedland.id.au/2009/04/bitbucket-and-pid-simple-pid-file.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1895238826710454512/posts/default/3370952582248020870'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1895238826710454512/posts/default/3370952582248020870'/><link rel='alternate' type='text/html' href='http://blog.friedland.id.au/2009/04/bitbucket-and-pid-simple-pid-file.html' title='Bitbucket and pid, a simple PID file handler'/><author><name>Jason Friedland</name><uri>http://www.blogger.com/profile/00183680637848117317</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1895238826710454512.post-7069105746606910547</id><published>2009-04-06T09:35:00.008+10:00</published><updated>2009-07-27T19:17:07.217+10:00</updated><title type='text'>Verifying packages using Python's RPM API</title><content type='html'>As part of our custom CentOS 5 SOE server build, I include a number of 3rd-party and user-contributed packages. &lt;br /&gt;&lt;br /&gt;During the CD ISO creation process, I want to ensure that all the RPM packages I'm about to include have their header and payload MD5 checksum, and GPG signature verified, to ensure no un-signed or corrupt packages make their way into the build.&lt;br /&gt;&lt;br /&gt;Here's an easy way to do this via a simple Python script - you'll need to import all your GPG keys into your RPM database (&lt;em&gt;rpm --import&lt;/em&gt;) prior to running the check.&lt;pre&gt;import sys, os, rpm&lt;br /&gt;&lt;br /&gt;if len(sys.argv) &lt; 2:&lt;br /&gt;    sys.stderr.write("Usage: %s /path/to/package.rpm \n" % (sys.argv[0]))&lt;br /&gt;    sys.exit(1)&lt;br /&gt;&lt;br /&gt;package = sys.argv[1]&lt;br /&gt;ts = rpm.TransactionSet()&lt;br /&gt;&lt;br /&gt;try:&lt;br /&gt;    fd = os.open(package, os.O_RDONLY)&lt;br /&gt;except OSError, e:&lt;br /&gt;    sys.exit(1)&lt;br /&gt;&lt;br /&gt;try:&lt;br /&gt;    header = ts.hdrFromFdno(fd)&lt;br /&gt;    # At this point, all checks have passed&lt;br /&gt;except rpm.error, e:&lt;br /&gt;    sys.exit(1)&lt;br /&gt;&lt;br /&gt;os.close(fd)&lt;br /&gt;sys.exit(0)&lt;/pre&gt;For more info, see the &lt;a href="http://docs.fedoraproject.org/drafts/rpm-guide-en/ch16s02.html"&gt;Python RPM API&lt;/a&gt; docs.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1895238826710454512-7069105746606910547?l=blog.friedland.id.au' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.friedland.id.au/feeds/7069105746606910547/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://blog.friedland.id.au/2009/04/verifying-packages-using-pythons-rpm.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1895238826710454512/posts/default/7069105746606910547'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1895238826710454512/posts/default/7069105746606910547'/><link rel='alternate' type='text/html' href='http://blog.friedland.id.au/2009/04/verifying-packages-using-pythons-rpm.html' title='Verifying packages using Python&apos;s RPM API'/><author><name>Jason Friedland</name><uri>http://www.blogger.com/profile/00183680637848117317</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1895238826710454512.post-423723679789212128</id><published>2009-03-31T13:07:00.013+10:00</published><updated>2009-07-27T19:21:04.923+10:00</updated><title type='text'>Packaging Python cliutils for Fedora</title><content type='html'>As &lt;a href="http://twitter.com/thesuperjason/statuses/1416015172"&gt;promised&lt;/a&gt;, I've submitted &lt;a href="http://code.google.com/p/cliutils/"&gt;Python cliutils&lt;/a&gt; for review to be included as a Fedora package.&lt;br /&gt;&lt;br /&gt;I've only been using it for a couple of days so far, but I'm already finding the cliutils library really useful for everyday systems-admin scripting, where I'm frequently mix-n-matching Bash and Python.&lt;br /&gt;&lt;br /&gt;With cliutils, I can do just about everything in Python and call out to shell scripts and commands with ease.&lt;br /&gt;&lt;br /&gt;Here's an example:&lt;br /&gt;&lt;pre&gt;lines = Process('grep blogger.com access.log') | Process('wc -l')&lt;/pre&gt;This could also be written as: &lt;br /&gt;&lt;pre&gt;lines = sh.grep('blogger.com access.log') | sh.wc('-l')&lt;/pre&gt;Another handy feature is the &lt;span style="font-weight:bold;"&gt;@cliargs&lt;/span&gt; decorator, which parses command line arguments as method arguments as shown in this small script:&lt;br /&gt;&lt;pre&gt;from cliutils import sh, cliargs&lt;br /&gt;&lt;br /&gt;@cliargs&lt;br /&gt;def doSearch(domain, logfile='domains.log'):&lt;br /&gt;    """Usage: search.py domain [ --logfile file ]"""&lt;br /&gt;    lines = sh.grep('%s %s' % (domain, logfile)) | sh.wc('-l')&lt;br /&gt;    print "Lines with domain '%s': %s" % (domain, lines)&lt;br /&gt;&lt;br /&gt;doSearch()&lt;/pre&gt;And you could run this script like so: &lt;br /&gt;&lt;pre class="brush: bash; toolbar: false;"&gt;./search.py blogger.com --logfile access.log&lt;/pre&gt;There's also &lt;a href="http://packages.python.org/cliutils/"&gt;API documentation available&lt;/a&gt; and more examples and general usage docs on the project homepage.&lt;br /&gt;&lt;br /&gt;You can download the &lt;a href="http://jason.friedland.id.au/pkg/python-cliutils.spec"&gt;SPEC file&lt;/a&gt; and &lt;a href="http://jason.friedland.id.au/pkg/python-cliutils-0.1.3-1.fc10.src.rpm"&gt;SRPM for Fedora 10&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1895238826710454512-423723679789212128?l=blog.friedland.id.au' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.friedland.id.au/feeds/423723679789212128/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://blog.friedland.id.au/2009/03/packaging-python-cliutils-for-fedora.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1895238826710454512/posts/default/423723679789212128'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1895238826710454512/posts/default/423723679789212128'/><link rel='alternate' type='text/html' href='http://blog.friedland.id.au/2009/03/packaging-python-cliutils-for-fedora.html' title='Packaging Python cliutils for Fedora'/><author><name>Jason Friedland</name><uri>http://www.blogger.com/profile/00183680637848117317</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1895238826710454512.post-6747712296535529859</id><published>2009-03-31T10:44:00.003+10:00</published><updated>2009-03-31T14:32:06.108+10:00</updated><title type='text'>Installing SyntaxHighlighter for Blogger</title><content type='html'>I've just 'installed' Alex Gorbatchev's excellent &lt;a href="http://alexgorbatchev.com/wiki/SyntaxHighlighter"&gt;Syntax Highlighter&lt;/a&gt; for this blog. It's a snap to set up, is very well-documented and has configurable themes and highlighting options. &lt;br /&gt;&lt;br /&gt;The output looks like this:&lt;pre class="brush: python; toolbar: false;"&gt;&lt;br /&gt;import socket, sys&lt;br /&gt;&lt;br /&gt;if len(sys.argv) &lt; 2:&lt;br /&gt;    sys.stderr.write("Usage: %s args \n" % (sys.argv[0]))&lt;br /&gt;    sys.exit(1)&lt;br /&gt;&lt;br /&gt;s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)&lt;br /&gt;s.settimeout(1)&lt;/pre&gt;Very nice. &lt;br /&gt;&lt;br /&gt;For more information on &lt;a href="http://alexgorbatchev.com/wiki/SyntaxHighlighter:Themes"&gt;Themes&lt;/a&gt;, &lt;a href="http://alexgorbatchev.com/wiki/SyntaxHighlighter:Brushes"&gt;Syntaxes&lt;/a&gt; and &lt;a href="http://alexgorbatchev.com/wiki/SyntaxHighlighter:Usage"&gt;Usage&lt;/a&gt;, see the Wiki.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1895238826710454512-6747712296535529859?l=blog.friedland.id.au' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.friedland.id.au/feeds/6747712296535529859/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://blog.friedland.id.au/2009/03/installing-syntaxhighlighter-for.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1895238826710454512/posts/default/6747712296535529859'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1895238826710454512/posts/default/6747712296535529859'/><link rel='alternate' type='text/html' href='http://blog.friedland.id.au/2009/03/installing-syntaxhighlighter-for.html' title='Installing SyntaxHighlighter for Blogger'/><author><name>Jason Friedland</name><uri>http://www.blogger.com/profile/00183680637848117317</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1895238826710454512.post-2836265369205071734</id><published>2009-03-29T18:03:00.001+10:00</published><updated>2009-03-29T18:03:34.066+10:00</updated><title type='text'>Packaging the Grizzled Library for Fedora</title><content type='html'>I've recently joined the Fedora project to do my bit for the free and open-source software community, by packaging 3rd party software for inclusion in the main Fedora project repository.&lt;br /&gt;&lt;br /&gt;Software from the frequently-updated Fedora project often makes it downstream into RHEL; CentOS is a re-packaged distribution of RHEL so everybody wins.&lt;br /&gt;&lt;br /&gt;Being a long-time user of and advocate for Fedora, RHEL and CentOS I've decided it's time to give something back, and since I've been using RPM much more heavily recently, I figured packaging would be a natural fit.&lt;br /&gt;&lt;br /&gt;I'd like to focus on the broader area of 'useful Python packages for Linux systems adminstration' as this complements my day job nicely, so the first package I'll be submitting for inclusion is Brian Clapper's &lt;a href="http://bit.ly/10K2a"&gt;Python Grizzled Utility Library&lt;/a&gt; which contains a number of handy modules. The os.daemonize module is especially useful. &lt;br /&gt;&lt;br /&gt;Brian's website also includes comprehensive API documentation making it a snap to start using the library.&lt;br /&gt;&lt;br /&gt;You can download the &lt;a href="http://bit.ly/kzO3F"&gt;SPEC file&lt;/a&gt; and &lt;a href="http://bit.ly/4dBzo7"&gt;the SRPM for Fedora 10&lt;/a&gt; until of course the package is available in Fedora's package repository :-)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1895238826710454512-2836265369205071734?l=blog.friedland.id.au' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.friedland.id.au/feeds/2836265369205071734/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://blog.friedland.id.au/2009/03/packaging-grizzled-library-for-fedora.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1895238826710454512/posts/default/2836265369205071734'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1895238826710454512/posts/default/2836265369205071734'/><link rel='alternate' type='text/html' href='http://blog.friedland.id.au/2009/03/packaging-grizzled-library-for-fedora.html' title='Packaging the Grizzled Library for Fedora'/><author><name>Jason Friedland</name><uri>http://www.blogger.com/profile/00183680637848117317</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1895238826710454512.post-1430965096261226019</id><published>2009-03-25T11:48:00.011+10:00</published><updated>2009-07-27T19:22:45.089+10:00</updated><title type='text'>Installing Mercurial on RHEL/CentOS 3</title><content type='html'>I've recently started using (and am subsequently hooked on) &lt;a href="http://bit.ly/BHqqK"&gt;Mercurial&lt;/a&gt; for version control, both at work, for projects on which I collaborate, and at home as a simple way of isolating development changes to documents and files.&lt;br /&gt;&lt;br /&gt;It was a simple case of doing a &lt;pre&gt;yum install mercurial&lt;/pre&gt; on my Fedora 10 workstation, however I ran into some trouble when it came time to install Mercurial on one of the number of RHEL/CentOS 3 management servers we still operate and support, mainly due to Mercurial's requirement of a Python version &gt;= 2.4.&lt;br /&gt;&lt;br /&gt;RHEL 3 ships with Python 2.2 and as anyone who's attempted to upgrade the installed system version of Python on a RHEL-based system will attest, it's typically an operation fraught with danger.&lt;br /&gt;&lt;br /&gt;A custom install of Python 2.5 to an alternate location is a safer option and extremely easy to achieve.&lt;br /&gt;&lt;br /&gt;Here's how I did it.&lt;br /&gt;&lt;br /&gt;Fetch and extract sources:&lt;br /&gt;&lt;pre&gt;wget http://www.python.org/ftp/python/2.5.4/Python-2.5.4.tgz&lt;br /&gt;wget http://www.selenic.com/mercurial/release/mercurial-1.2.1.tar.gz&lt;br /&gt;tar zxvf mercurial-1.2.1.tar.gz&lt;br /&gt;tar zxvf Python-2.5.4.tgz&lt;/pre&gt;Configure and build Python using /opt - you could use /usr/local or similar but I preferred to keep it out of my $PATH:&lt;br /&gt;&lt;pre&gt;cd Python-2.5.4&lt;br /&gt;./configure --prefix=/opt&lt;br /&gt;make&lt;br /&gt;su -c "make install"&lt;/pre&gt;Test Python installed properly:&lt;br /&gt;&lt;pre&gt;/opt/bin/python&lt;br /&gt;Python 2.5.4 (r254:67916, Mar 25 2009, 12:16:36)&lt;br /&gt;[GCC 3.2.3 20030502 (Red Hat Linux 3.2.3-56)] on linux2&lt;br /&gt;Type "help", "copyright", "credits" or "license" for more information.&lt;/pre&gt;Build Mercurial, using your Python 2.5:&lt;br /&gt;&lt;pre&gt;cd ../mercurial-1.2.1&lt;br /&gt;su -c "make install PYTHON=/opt/bin/python PREFIX=/opt"&lt;/pre&gt;Test Mercurial installed properly:&lt;br /&gt;&lt;pre&gt;/opt/bin/hg --version&lt;br /&gt;Mercurial Distributed SCM (version 1.2.1)&lt;br /&gt;Copyright (C) 2005-2009 Matt Mackall and others&lt;/pre&gt;You may wish to symlink hg from somewhere in your $PATH:&lt;br /&gt;&lt;pre&gt;su -c "ln -s /opt/bin/hg /usr/local/bin/hg"&lt;/pre&gt;Obviously you'll need a C compiler and associated development tools installed. You may find that the Python configure command complains of missing libraries, such as zlib-devel which can be installed via yum if required.&lt;br /&gt;&lt;br /&gt;Good luck and refer to the &lt;a href="http://bit.ly/aes7Z"&gt;install instructions on Mercurial's site&lt;/a&gt; if you get stuck.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1895238826710454512-1430965096261226019?l=blog.friedland.id.au' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.friedland.id.au/feeds/1430965096261226019/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://blog.friedland.id.au/2009/03/installing-mercurial-on-rhelcentos-3.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1895238826710454512/posts/default/1430965096261226019'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1895238826710454512/posts/default/1430965096261226019'/><link rel='alternate' type='text/html' href='http://blog.friedland.id.au/2009/03/installing-mercurial-on-rhelcentos-3.html' title='Installing Mercurial on RHEL/CentOS 3'/><author><name>Jason Friedland</name><uri>http://www.blogger.com/profile/00183680637848117317</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry></feed>
