<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:openSearch="http://a9.com/-/spec/opensearch/1.1/" xmlns:georss="http://www.georss.org/georss" xmlns:gd="http://schemas.google.com/g/2005" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" gd:etag="W/&quot;DkEEQ387eCp7ImA9WxNUGUk.&quot;"><id>tag:blogger.com,1999:blog-2100126952066830960</id><updated>2009-11-11T03:03:22.100-10:00</updated><title>TuxCoder</title><subtitle type="html">A place for random code postings, tips, and how-tos for Linux.</subtitle><link rel="http://schemas.google.com/g/2005#feed" type="application/atom+xml" href="http://blog.tuxcoder.com/feeds/posts/default" /><link rel="alternate" type="text/html" href="http://blog.tuxcoder.com/" /><link rel="hub" href="http://pubsubhubbub.appspot.com/" /><author><name>Casey</name><uri>http://www.blogger.com/profile/01605425478146974127</uri><email>noreply@blogger.com</email></author><generator version="7.00" uri="http://www.blogger.com">Blogger</generator><openSearch:totalResults>10</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><link rel="self" href="http://feeds.feedburner.com/tuxcoder" type="application/atom+xml" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com" /><entry gd:etag="W/&quot;A0EAQHc4fCp7ImA9WxJQFUs.&quot;"><id>tag:blogger.com,1999:blog-2100126952066830960.post-3906583942866463485</id><published>2009-05-24T22:44:00.033-10:00</published><updated>2009-05-28T18:00:41.934-10:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-05-28T18:00:41.934-10:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="bittornado" /><category scheme="http://www.blogger.com/atom/ns#" term="screen" /><category scheme="http://www.blogger.com/atom/ns#" term="bttrack" /><category scheme="http://www.blogger.com/atom/ns#" term="bittorrent" /><category scheme="http://www.blogger.com/atom/ns#" term="lighttpd" /><category scheme="http://www.blogger.com/atom/ns#" term="rtorrent" /><title>Share Files Over BitTorrent Using a Local Tracker and Client in Linux</title><content type="html">&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_GCbh8lju5Fo/ShzTwgiwhRI/AAAAAAAAANs/gFv3ZHHCSDo/s1600-h/188820_portable_bittorrent_612_build_13422.png"&gt;&lt;img style="float:right; margin:0 0 10px 10px;cursor:pointer; cursor:hand;width: 200px; height: 200px;" src="http://1.bp.blogspot.com/_GCbh8lju5Fo/ShzTwgiwhRI/AAAAAAAAANs/gFv3ZHHCSDo/s320/188820_portable_bittorrent_612_build_13422.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5340376088477467922" /&gt;&lt;/a&gt;

&lt;p&gt;Everyone has heard of the &lt;a href="http://en.wikipedia.org/wiki/BitTorrent_(protocol)"&gt;BitTorrent&lt;/a&gt; protocol. It's widely used to quickly distribute large files with a low-bandwidth connection. There are also a lot of other features in BitTorrent that make it superior to either HTTP or FTP. For example, pseudo archives, built-in checksums, partial-download resumes, and send/receive bandwidth capping.&lt;/p&gt;

&lt;p&gt;This post will show you how to share your personal files using BitTorrent tools that come standard with Ubuntu Linux (Jaunty 9.04). This article will cover the following steps:
&lt;ol&gt;
&lt;li&gt;Configuring and running a local "tracker" server.&lt;/li&gt;
&lt;li&gt;Building torrent files from your personal file(s) you wish to share.&lt;/li&gt;
&lt;li&gt;Auto-seed and share your active torrent files.&lt;/li&gt;
&lt;/ol&gt;&lt;/p&gt;
&lt;span class="fullpost"&gt;
&lt;h2&gt;Configure a Local BitTorrent Tracker Server&lt;/h2&gt;

&lt;p&gt;Before creating a torrent file, you should have an active tracker server configured and running. It is perfectly acceptable to use a public tracker, but running a personal tracker lets your clients connect over a private network (192.168.*). Also, if your torrent files are for commercial use, you likely do not want trust the reliability of your service to a third party.&lt;/p&gt;

&lt;p&gt;The BitTorrent tracker server must be accessible to all your clients. Also, it must have either a static DNS or IP address so your clients can always contact it.&lt;/p&gt;

&lt;p&gt;From the command line, install Bittornado, start the tracker, and verify it is running:&lt;/p&gt;

&lt;pre&gt;$ sudo apt-get install bittornado
$ bttrack --port 6969 --dfile ~/.bttrack/dstate --logfile ~/.bttrack/tracker.log --nat_check 0 --scrape_allowed full
$ firefox http://localhost:6969&lt;/pre&gt;

&lt;p&gt;The &lt;code&gt;bttrack&lt;/code&gt; command will start a tracker that allows clients behind NAT connections. Connecting to the tracker port in FireFox will display a page with known torrents and status of each one.&lt;/p&gt;

&lt;p&gt;Finally, be aware that with this configuration, the server will register all torrent files it is notified of. So, potentially someone could use this tracker for their own torrents. If you are on private network this may not be an issue, or you can use additional options to restrict the torrents allowed on the tracker:&lt;/p&gt;

&lt;pre&gt;--allowed_dir $HOME/btfiles --parse_dir_interval 10 --allow_get 1&lt;/pre&gt;

These additional arguments to &lt;code&gt;bttrack&lt;/code&gt; will force the tracker to only use files located the the &lt;code&gt;~HOME/btfiles&lt;/code&gt; directory. Remember, if you use these options, your torrents must be manually copied into this directory before the tracker will accept seeding requests.&lt;/p&gt;

&lt;h3&gt;Advanced Bttrack Config and Settings&lt;/h3&gt;
&lt;p&gt;Simplify the tracker startup with a simple shell script:&lt;/p&gt;
&lt;pre&gt;$ cat &lt;&lt;EOF &gt; bin/bttrack.sh 
#!/bin/bash

PORT=6969
DFILE="$HOME/.bttrack/dstate"
LFILE="$HOME/.bttrack/tracker.log"
# GET="--allowed_dir $HOME/btfiles --allow_get 1 --parse_dir_interval 10"
OPTS="--nat_check 0 --scrape_allowed full"

mkdir -p $HOME/.bttrack
bttrack --port $PORT --dfile $DFILE --logfile $LFILE $GET $OPTS
EOF

$ chmod 755 bin/bttrack.sh&lt;/pre&gt;

&lt;p&gt;You may want to add &lt;code&gt;bttrack&lt;/code&gt; to your systems &lt;code&gt;init.d&lt;/code&gt; startup scripts. Start with a copy of the default service skeleton file from &lt;code&gt;/etc/init.d/skeleton&lt;/code&gt;&lt;/p&gt;
&lt;pre&gt;$ sudo cp /etc/init.d/skeleton /etc/init.d/bttrack
$ sudo vi /etc/init.d/bttrack&lt;/pre&gt;

&lt;p&gt;Replace the top section of the &lt;code&gt;/etc/init.d/bttrack&lt;/code&gt; file using the example code below. Notice that the &lt;code&gt;--dstate&lt;/code&gt; and &lt;code&gt;--logfile&lt;/code&gt; values have been changed to a more standard location.&lt;/p&gt;
&lt;pre&gt;PATH=/usr/sbin:/usr/bin:/sbin:/bin
DESC="BitTorrent protocol tracker"
NAME=bttrack
DAEMON=/usr/bin/$NAME
DAEMON_ARGS="--dfile /var/run/$NAME/dstate --logfile /var/log/$NAME.log
   --port 6969 --nat_check 0 --scrape_allowed full"
PIDFILE=/var/run/$NAME.pid
SCRIPTNAME=/etc/init.d/$NAME

do_start()
{
 start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON --test &gt; /dev/null \
  || return 1
 start-stop-daemon --start --background --make-pidfile --quiet --pidfile $PIDFILE \
      --exec $DAEMON -- $DAEMON_ARGS \
  || return 2
}&lt;/pre&gt;


&lt;h2&gt;Create a Torrent File&lt;/h2&gt;

&lt;p&gt;The next step is to create one or more torrents files to provide the necessary information to begin seeding files inside of a &lt;a href="http://en.wikipedia.org/wiki/Bittorrent_client"&gt;BitTorrent client&lt;/a&gt;. The following command is not the only method you can use. The other options for creating torrents is using a graphical client, such as &lt;a href="http://en.wikipedia.org/wiki/Deluge_(software)"&gt;Deluge&lt;/a&gt; or &lt;a href="http://en.wikipedia.org/wiki/Transmission_(BitTorrent_client)"&gt;Transmission&lt;/a&gt;. I prefer the command line, since it is more concise:

&lt;pre&gt;$ sudo apt-get install bittornado
$ btmakemetafile --piece_size_pow2 SIZE http://URL.COM:PORT/announce SOURCE --target OUTPUT.torrent&lt;/pre&gt;

&lt;dl style="background-color:#b8cfe7; padding:15px; border-style:solid;"&gt;
&lt;dt&gt;&lt;strong&gt;SIZE&lt;/strong&gt; [OPTIONAL]&lt;/dt&gt;
&lt;dd&gt;The torrent's "piece" size as a power of 2, where a "piece" is the smallest transferable unit of data. For example, 512KB (19) and 1MB (20). If not defined, this value is selected automatically. For fast connections, use a larger value such as 4MB (22).&lt;/dd&gt;

&lt;dt&gt;&lt;strong&gt;http://URL.COM:PORT/announce&lt;/strong&gt;&lt;/dt&gt;
&lt;dd&gt;The address of the tracker and port number. The address can either be a DNS name or IP number.&lt;/dd&gt;

&lt;dt&gt;&lt;strong&gt;SOURCE&lt;/strong&gt;&lt;/dt&gt;
&lt;dd&gt;The location of source directory or list of file(s) to add to the torrent.&lt;/dd&gt;

&lt;dt&gt;&lt;strong&gt;OUTPUT.torrent&lt;/strong&gt; [OPTIONAL]&lt;/dt&gt;
&lt;dd&gt;The output name of the torrent file. Changing the name after creating the torrent file will break some BitTorrent clients, so set the name hear. If you leave this value empty, the torrent file will be named using the &lt;strong&gt;SOURCE&lt;/strong&gt; name.&lt;/dd&gt;

&lt;dt&gt;&lt;strong&gt;--announce_list LIST&lt;/strong&gt; [OPTIONAL]&lt;/dt&gt;
&lt;dd&gt;If your tracker has more than one DNS or IP, use this optional argument to set all tracker addresses. Make sure to duplicate the primary announce address, &lt;strong&gt;http://URL.COM:PORT/announce&lt;/strong&gt;, in this list as well. The list can be "&lt;code&gt;,&lt;/code&gt;" separated for equal tiered trackers, or use "&lt;code&gt;|&lt;/code&gt;" separator to indicate secondary trackers. See the &lt;a href="http://www.linux.gr/cgi-bin/man/man2html?btmakemetafile+1"&gt;man page&lt;/a&gt; for more details.&lt;/dd&gt;
&lt;/dl&gt;

&lt;h2&gt;Seeding and Sharing Torrent Files&lt;/h2&gt;
&lt;p&gt;After you've created the torrent files for seeding, the final step is to start them from any BitTorrent client. If you need to seed files for an extended period of time, I recommend using &lt;a href="http://libtorrent.rakshasa.no/"&gt;rTorrent&lt;/a&gt; inside of a &lt;a href="http://www.gnu.org/software/screen/"&gt;screen&lt;/a&gt; session. This allows you to run the client in the background, and pull-up the text-based GUI at any time.&lt;/p&gt;

&lt;p&gt;The following steps will create an rTorrent configuration file that will automatically load torrents from a target directory and begin seeding:&lt;/p&gt;

&lt;pre&gt;$ cat &lt;&lt;EOF &gt; ~/.rtorrent.rc
check_hash = no
session = ~/.rtorrent
directory = /data/torrents
schedule = watch_directory,5,5,load_start=/data/torrents/autostart/*.torrent
schedule = untied_directory,5,5,stop_untied=
EOF
$ sudo apt-get install rtorrent screen
$ screen rtorrent&lt;/pre&gt;

&lt;p&gt;rTorrent should be running in the current terminal. If you are not familiar with &lt;code&gt;screen&lt;/code&gt;, here are a few keyboard shortcuts for navigation:&lt;/p&gt;
&lt;dl style="background-color:#b8cfe7; padding:15px; border-style:solid;"&gt;
&lt;dt&gt;&lt;strong&gt;&amp;lt;Ctrl-a&amp;gt; ?&lt;/strong&gt;&lt;/dt&gt;
&lt;dd&gt;Show screen's help&lt;/dd&gt;
&lt;dt&gt;&lt;strong&gt;&amp;lt;Ctrl-a&amp;gt; d&lt;/strong&gt;&lt;/dt&gt;
&lt;dd&gt;Detach the screen session&lt;/dd&gt;
&lt;dt&gt;&lt;strong&gt;&amp;lt;Ctrl-a&amp;gt; k&lt;/strong&gt;&lt;/dt&gt;
&lt;dd&gt;Kill current screen session&lt;/dd&gt;
&lt;dt&gt;&lt;strong&gt;&amp;lt;Ctrl-a&amp;gt; c&lt;/strong&gt;&lt;/dt&gt;
&lt;dd&gt;Create a new shell window in screen&lt;/dd&gt;
&lt;dt&gt;&lt;strong&gt;&amp;lt;Ctrl-a&amp;gt; n&lt;/strong&gt;&lt;/dt&gt;
&lt;dd&gt;Show next window&lt;/dd&gt;
&lt;dt&gt;&lt;strong&gt;&amp;lt;Ctrl-a&amp;gt; p&lt;/strong&gt;&lt;/dt&gt;
&lt;dd&gt;Show previous window&lt;/dd&gt;
&lt;/dl&gt;
&lt;p&gt;If you close the screen session, you can reconnect with the command "&lt;code&gt;screen -r&lt;/code&gt;".&lt;/p&gt;

&lt;p&gt;After launching rTorrent, it is now possible to start seeding the torrents.&lt;/p&gt;
&lt;ol&gt;&lt;li&gt;Move (or create a symbolic link to) the torrent data into rTorrent's "download" directory. The default download directory is defined in the &lt;code&gt;rtorrent.rc&lt;/code&gt; file.&lt;/li&gt;
&lt;li&gt;Notice that in the &lt;code&gt;rtorrent.rc&lt;/code&gt; file, it also specified the "watch" directory. &lt;strong&gt;Place the new torrent files in the "watch" directory, and they will be picked-up by rTorrent.&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Go back to the rTorrent GUI, and verify that the torrent is being re-hashed and seeded properly.&lt;/li&gt;
&lt;li&gt;Copy or e-mail the &lt;code&gt;*.torrent&lt;/code&gt; files you have created to anyone that you want to share your files with&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;Advanced Torrent File Sharing&lt;/h3&gt;
&lt;p&gt;Instead of manually sending &lt;code&gt;*.torrent&lt;/code&gt; files to your family and friends, a better option is to run a public web server where the torrents can be made available 24/7:&lt;/p&gt;

&lt;pre&gt;$ sudo apt install lighttpd
$ cd /etc/lighttpd
$ sudo bash -c 'cat &lt;&lt;EOF &gt; conf-available/40-site-torrent.conf
SERVER["socket"] == ":88" {
   server.document-root    = "/data/torrents/autostart"
}
EOF'
$ sudo /etc/init.d/lighttpd restart&lt;/pre&gt;

&lt;p&gt;This command creates a local web server running on port 88. The source directory can be mapped directly to the "watch" directory of your BitTorrent client. This is where all the active torrent files are stored while the torrents are active. Once enabled, the torrent files can be accessed from &lt;a href="http://localhost:88"&gt;http://localhost:88&lt;/a&gt;.&lt;/p&gt;

&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2100126952066830960-3906583942866463485?l=blog.tuxcoder.com'/&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/tuxcoder/~4/AVjfBFKP6Zo" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.tuxcoder.com/feeds/3906583942866463485/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://blog.tuxcoder.com/2009/05/share-files-over-bittorrent-using-local.html#comment-form" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2100126952066830960/posts/default/3906583942866463485?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2100126952066830960/posts/default/3906583942866463485?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/tuxcoder/~3/AVjfBFKP6Zo/share-files-over-bittorrent-using-local.html" title="Share Files Over BitTorrent Using a Local Tracker and Client in Linux" /><author><name>Casey</name><uri>http://www.blogger.com/profile/01605425478146974127</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="02436649480923296246" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://1.bp.blogspot.com/_GCbh8lju5Fo/ShzTwgiwhRI/AAAAAAAAANs/gFv3ZHHCSDo/s72-c/188820_portable_bittorrent_612_build_13422.png" height="72" width="72" /><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">1</thr:total><feedburner:origLink>http://blog.tuxcoder.com/2009/05/share-files-over-bittorrent-using-local.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DkEESXoyfyp7ImA9WxJSE0U.&quot;"><id>tag:blogger.com,1999:blog-2100126952066830960.post-1815730641654411630</id><published>2009-05-02T12:10:00.018-10:00</published><updated>2009-05-03T11:03:28.497-10:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-05-03T11:03:28.497-10:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="mdadm" /><category scheme="http://www.blogger.com/atom/ns#" term="raid" /><category scheme="http://www.blogger.com/atom/ns#" term="lvm" /><category scheme="http://www.blogger.com/atom/ns#" term="mount" /><title>Mounting Unknown RAID+LVM Volumes Step-by-Step</title><content type="html">&lt;p&gt;Every time your system boots, startup scripts will handle all disk mounting tasks. This is good, yet unfortunate if you ever run in to problems, because you're going to need to know how to get things up without the help of the scripts. On my systems, I run a combination of &lt;a href="http://http://en.wikipedia.org/wiki/Logical_Volume_Manager_(Linux)"&gt;LVM volumes&lt;/a&gt; on top of multiple &lt;a href="http://en.wikipedia.org/wiki/RAID"&gt;RAID&lt;/a&gt; arrays. This provides data integrity and future flexibility to add more space as needed, and makes recovery very complicated.&lt;/p&gt;

&lt;p&gt;There are two cases where you will eventually need to know how this all works. The most likely case is recovering from a boot failure, in which you are relatively familiar with the configuration. An even more difficult case is mounting a set of unknown drives with a RAID/LVM configuration. Keep reading and I'll explain how you can handle even the hardest case like a pro.&lt;/p&gt;
&lt;span class="fullpost"&gt;
&lt;p style="background-color:#e0b2b2; padding:15px; border-style:solid;"&gt;If there is a chance you will be mounting two or more &lt;span style="font-weight:bold;"&gt;LVM Volume Groups with identical names&lt;/span&gt;, then read the warning at end before continuing.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;After installing all the drives into the system, verify they are detected in &lt;code&gt;/dev/sd*&lt;/code&gt;:
&lt;pre&gt;
$ ls /dev/sd*
/dev/sda   /dev/sdb   /dev/sdc   /dev/sdd   /dev/sde   /dev/sdf   /dev/sdf3
/dev/sda1  /dev/sdb1  /dev/sdc1  /dev/sdd1  /dev/sde1  /dev/sdf1  /dev/sdf4
/dev/sda2  /dev/sdb2  /dev/sdc2  /dev/sdd2  /dev/sde2  /dev/sdf2
&lt;/pre&gt;
&lt;/li&gt;

&lt;li&gt;Find out which partitions of those are mounted:
&lt;pre&gt;
$ df -lhx tmpfs 
Filesystem            Size  Used Avail Use% Mounted on
/dev/mapper/lvm_vg0-root
                       10G  3.7G  6.4G  37% /
/dev/mapper/lvm_vg0-home
                      160G   83G   78G  52% /home
/dev/md0               99M   16M   79M  17% /boot
&lt;/pre&gt;
This output doesn't directly indicate what partitions are being used. Instead it indicates two LVM volumes; &lt;code&gt;/dev/mapper/lvm_vg0-root&lt;/code&gt;, &lt;code&gt;/dev/mapper/lvm_vg0-home&lt;/code&gt; and one RAID array; &lt;code&gt;/dev/md0&lt;/code&gt;. The next steps will reduce this info to the physical partitions.
&lt;/li&gt;

&lt;ol&gt;
&lt;li&gt;Lookup the two LVM volumes &lt;code&gt;lvm_vg0-root&lt;/code&gt; and &lt;code&gt;lvm_vg0-home&lt;/code&gt; to determine the LVM volume group (VG):
&lt;pre&gt;
$ sudo lvdisplay | grep 'VG Name'
  VG Name                lvm_vg0
  VG Name                lvm_vg0
&lt;/pre&gt;
&lt;/li&gt;

&lt;li&gt;The LVM VG, &lt;code&gt;lvm_vg0&lt;/code&gt;, maps to one ore more physical volumes:
&lt;pre&gt;
$ sudo pvdisplay
  --- Physical volume ---
  PV Name               /dev/md1
  VG Name               lvm_vg0
  PV Size               297.99 GB / not usable 3.25 MB
  Allocatable           yes 
  PE Size (KByte)       4096
  Total PE              76285
  Free PE               32765
  Allocated PE          43520
  PV UUID               mD6jat-SvPv-dOop-P3qZ-T7zC-r8ke-xSYRSj
&lt;/pre&gt;
This output shows us that the LVM pysical volume (PV) is using &lt;code&gt;/dev/md1&lt;/code&gt;.
&lt;/li&gt;

&lt;li&gt;Now, lookup &lt;code&gt;md0&lt;/code&gt; (from the top step) and &lt;code&gt;md1&lt;/code&gt; devices:
&lt;pre&gt;
$ cat /proc/mdstat
Personalities : [linear] [multipath] [raid0] [raid1] [raid6] [raid5] [raid4] [raid10] 
md1 : active raid10 sde2[0] sdd2[1]
      312466688 blocks 64K chunks 2 far-copies [2/2] [UU]

md0 : active raid1 sde1[0] sdd1[1]
      104320 blocks [2/2] [UU]
&lt;/pre&gt;
OK, so the final answer is that &lt;code&gt;md1&lt;/code&gt; is using partitions: &lt;code&gt;sde2&lt;/code&gt;, &lt;code&gt;sdd2&lt;/code&gt; and array &lt;code&gt;md0&lt;/code&gt; is using partitions: &lt;code&gt;sde1&lt;/code&gt;, &lt;code&gt;sdd1&lt;/code&gt;.
&lt;/li&gt;
&lt;/ol&gt;

&lt;li&gt;Now, create list of unmounted partitions, by filtering out the mounted partitions:
&lt;pre&gt;
$ ls --color=none /dev/sd* | grep [0-9] | egrep -v 'sde2|sdd2|sde1|sdd1'
/dev/sda1
/dev/sda2
/dev/sdb1
/dev/sdb2
/dev/sdc1
/dev/sdc2
/dev/sdf1
/dev/sdf2
/dev/sdf3
/dev/sdf4
&lt;/pre&gt;
&lt;/li&gt;

&lt;li&gt;To find RAID partitions, every device can be scanned for volume UUID value:
&lt;pre&gt;
$ mdadm --examine /dev/sda1 | grep UUID
           UUID : ae9a1594:27fc3cec:ceff8456:d50a26a6
&lt;/pre&gt;
With a little more work, all the unmounted devices can be scanned in a single pass:
&lt;pre&gt;
$ ls --color=none /dev/sd* | grep [0-9] | egrep -v 'sde2|sdd2|sde1|sdd1' | xargs -i sh -c 'sudo mdadm --examine {} | grep -H --label={} UUID'
/dev/sda1:           UUID : ae9a1594:27fc3cec:ceff8456:d50a26a6
/dev/sda2:           UUID : cd72d060:e1139a47:8d379926:979de13e
/dev/sdb1:           UUID : ae9a1594:27fc3cec:ceff8456:d50a26a6
/dev/sdb2:           UUID : 2eb0a293:e7705a2f:8d379926:979de13e
mdadm: No md superblock detected on /dev/sdc1.
/dev/sdc2:           UUID : 29d74ba3:2dff5d1d:e1635e97:4ded1971
mdadm: No md superblock detected on /dev/sdf1.
/dev/sdf2:           UUID : 29d74ba3:2dff5d1d:e1635e97:4ded1971
/dev/sdf3:           UUID : 2eb0a293:e7705a2f:8d379926:979de13e
/dev/sdf4:           UUID : cd72d060:e1139a47:8d379926:979de13e
&lt;/pre&gt;
It looks like every device is part of a RAID array except &lt;code&gt;/dev/sdc1&lt;/code&gt; and &lt;code&gt;/dev/sdf1&lt;/code&gt;.
&lt;/li&gt;

&lt;li&gt;Manually sort the list in the last step by the UUID values. Every matching UUID value indicates a single RAID array. Here is what your list should look like:
&lt;pre&gt;
/dev/sda1:           UUID : ae9a1594:27fc3cec:ceff8456:d50a26a6
/dev/sdb1:           UUID : ae9a1594:27fc3cec:ceff8456:d50a26a6
-----
/dev/sda2:           UUID : cd72d060:e1139a47:8d379926:979de13e
/dev/sdf4:           UUID : cd72d060:e1139a47:8d379926:979de13e
-----
/dev/sdb2:           UUID : 2eb0a293:e7705a2f:8d379926:979de13e
/dev/sdf3:           UUID : 2eb0a293:e7705a2f:8d379926:979de13e
-----
/dev/sdc2:           UUID : 29d74ba3:2dff5d1d:e1635e97:4ded1971
/dev/sdf2:           UUID : 29d74ba3:2dff5d1d:e1635e97:4ded1971
&lt;/pre&gt;
Using these value, assemble each RAID array. The &lt;code&gt;/dev/md*&lt;/code&gt; is not important as long as you choose a value that does not currently exists in the system.
&lt;pre&gt;
$ sudo mdadm --assemble /dev/md2 /dev/sda1 /dev/sdb1 
mdadm: /dev/md2 has been started with 2 drives.

$ sudo mdadm --assemble /dev/md3 /dev/sda2 /dev/sdf4 
mdadm: /dev/md3 has been started with 2 drives.

$ sudo mdadm --assemble /dev/md4 /dev/sdb2 /dev/sdf3 
mdadm: /dev/md4 has been started with 2 drives.

$ sudo mdadm --assemble /dev/md5 /dev/sdc2 /dev/sdf2 
mdadm: /dev/md5 has been started with 2 drives.
&lt;/pre&gt;
Now check that all the previous steps by printing the &lt;code&gt;mdstat&lt;/code&gt; file:
&lt;pre&gt;
$ cat /proc/mdstat 
Personalities : [linear] [multipath] [raid0] [raid1] [raid6] [raid5] [raid4] [raid10] 
md5 : active raid10 sdc2[0] sdf2[1]
      488281984 blocks 64K chunks 2 far-copies [2/2] [UU]

md4 : active raid10 sdb2[0] sdf3[1]
      244094080 blocks 64K chunks 2 far-copies [2/2] [UU]

md3 : active raid10 sda2[0] sdf4[1]
      244094080 blocks 64K chunks 2 far-copies [2/2] [UU]

md2 : active raid1 sdb1[0] sda1[1]
      104320 blocks [2/2] [UU]

md1 : active raid10 sde2[0] sdd2[1]
      312466688 blocks 64K chunks 2 far-copies [2/2] [UU]

md0 : active raid1 sde1[0] sdd1[1]
      104320 blocks [2/2] [UU]

unused devices: &lt;none&gt;
&lt;/pre&gt;
&lt;/li&gt;

&lt;li&gt;When you are happy with the device mappings, update the &lt;code&gt;/etc/mdadm/mdadm.conf&lt;/code&gt; file:
&lt;pre&gt;
$ sudo sh -c 'mdadm --detail --scan &gt;&gt; /etc/mdadm/mdadm.conf'
&lt;/pre&gt;
After this step, edit the file to remove any old entries. &lt;span style="color:red"&gt;Because of a bug in mdadm, change the "&lt;code&gt;metadata&lt;/code&gt;" version from "&lt;code&gt;00.90&lt;/code&gt;" to "&lt;code&gt;0.90&lt;/code&gt;".&lt;/span&gt;
&lt;/li&gt;

&lt;li&gt;Now, with the RAID arrays active, scan for LVM volumes. First the physical volumes (PV):
&lt;pre&gt;
$ sudo pvscan
  PV /dev/md4   VG lvm_vg0   lvm2 [232.79 GB / 0    free]
  PV /dev/md3   VG lvm_vg0   lvm2 [232.79 GB / 956.00 MB free]
  PV /dev/md5   VG lvm_vg0   lvm2 [465.66 GB / 274.60 GB free]
  PV /dev/md1   VG lvm_vg0   lvm2 [297.99 GB / 127.99 GB free]
  Total: 4 [1.20 TB] / in use: 4 [1.20 TB] / in no VG: 0 [0   ]
&lt;/pre&gt;
Next the volume groups (VG):
&lt;pre&gt;
$ sudo vgdisplay 
  --- Volume group ---
  VG Name               lvm_vg0
  System ID             
  Format                lvm2
  Metadata Areas        3
  Metadata Sequence No  58
  VG Access             read/write
  VG Status             resizable
  MAX LV                0
  Cur LV                3
  Open LV               1
  Max PV                0
  Cur PV                3
  Act PV                3
  VG Size               931.23 GB
  PE Size               4.00 MB
  Total PE              238395
  Alloc PE / Size       167859 / 655.70 GB
  Free  PE / Size       70536 / 275.53 GB
  VG UUID               yLjVr3-BKkp-BW33-QIsh-rpZX-byL7-bzF2Xg

  --- Volume group ---
  VG Name               lvm_vg0
  System ID             
  Format                lvm2
  Metadata Areas        1
  Metadata Sequence No  3
  VG Access             read/write
  VG Status             resizable
  MAX LV                0
  Cur LV                2
  Open LV               2
  Max PV                0
  Cur PV                1
  Act PV                1
  VG Size               297.99 GB
  PE Size               4.00 MB
  Total PE              76285
  Alloc PE / Size       43520 / 170.00 GB
  Free  PE / Size       32765 / 127.99 GB
  VG UUID               138ikB-v1Z0-381g-Qvi8-dWN2-pgJ7-namuLh
&lt;/pre&gt;

&lt;p style="background-color:#e0b2b2; padding:15px; border-style:solid;"&gt;&lt;span style="font-weight:bold;"&gt;Be very careful if your system indicates identically named LVM Volume Groups&lt;/span&gt; (shown above). LVM will NOT let you mount the volumes from one or all of the groups. You must resolve the name conflict before continuing.&lt;br&gt;&lt;br&gt;Additionally, you will not be able to rename LVM VGs if either the old or new VG has mounted logical volumes! If one of your VG's LV's is the &lt;span style="font-weight:bold;"&gt;root&lt;/span&gt; volume, you will have to resort to a live-boot CD.&lt;/p&gt;
A VG can be renamed with the following command:
&lt;pre&gt;
$vgrename vg0-old vg0-new
&lt;/pre&gt;
&lt;/li&gt;


&lt;li&gt;Finally, mount the new volumes and update your &lt;code&gt;/etc/fstab&lt;/code&gt; like normal.
&lt;/li&gt;
&lt;/ol&gt;
&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2100126952066830960-1815730641654411630?l=blog.tuxcoder.com'/&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/tuxcoder/~4/rztyDCZDYus" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.tuxcoder.com/feeds/1815730641654411630/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://blog.tuxcoder.com/2009/05/step-by-step-mounting-unknown-raidlvm.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2100126952066830960/posts/default/1815730641654411630?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2100126952066830960/posts/default/1815730641654411630?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/tuxcoder/~3/rztyDCZDYus/step-by-step-mounting-unknown-raidlvm.html" title="Mounting Unknown RAID+LVM Volumes Step-by-Step" /><author><name>Casey</name><uri>http://www.blogger.com/profile/01605425478146974127</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="02436649480923296246" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://blog.tuxcoder.com/2009/05/step-by-step-mounting-unknown-raidlvm.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DEUBRX4yeip7ImA9WxVVE04.&quot;"><id>tag:blogger.com,1999:blog-2100126952066830960.post-8356723568664252748</id><published>2009-03-05T21:16:00.043-10:00</published><updated>2009-03-06T00:44:14.092-10:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-03-06T00:44:14.092-10:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="greasemonkey" /><category scheme="http://www.blogger.com/atom/ns#" term="keyboard shortcuts" /><category scheme="http://www.blogger.com/atom/ns#" term="google" /><title>Better Google Keyboard Shortcuts using Greasemonkey</title><content type="html">&lt;p&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_GCbh8lju5Fo/SbDPG9rR8cI/AAAAAAAAAHc/voMf5XL9nUk/s1600-h/google_keyboard.jpg"&gt;&lt;img style="float:right; margin:0 0 10px 10px;cursor:pointer; cursor:hand;width: 308px; height: 243px;" src="http://3.bp.blogspot.com/_GCbh8lju5Fo/SbDPG9rR8cI/AAAAAAAAAHc/voMf5XL9nUk/s320/google_keyboard.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5309971679212073410" /&gt;&lt;/a&gt;I used to be one of those "simple" folk using &lt;a href="http://www.google.com"&gt;Google&lt;/a&gt; the &lt;span style="font-style:italic;"&gt;normal&lt;/span&gt; way. This has got to be one of the most aggravating experiences. Even more so when looking for answers on an obscure topic. This is because Google is tricky to use, and getting results always takes multiple attempts. Even with a good search, it's likely the best match is buried a few pages in. The action of typing, scrolling, mousing, then clicking a few links, only to "&lt;span style="font-style:italic;"&gt;rinse and repeat&lt;/span&gt;" 15 seconds later is enough to inflame my wrist with an &lt;a href="http://en.wikipedia.org/wiki/Repetitive_strain_injury"&gt;RSI&lt;/a&gt; in under 20 minutes. After a full day of work, this becomes hazardous to your health.&lt;/p&gt;

&lt;p&gt;You might be thinking that this kind of thing doesn't bother you. Well, just wait until you try Google with optimized keyboard shortcuts. You will never want to go back, I promise!&lt;/p&gt;
&lt;span class="fullpost"&gt;
&lt;p&gt;Since sometime back in 2008, I have been using the &lt;a href="http://www.google.com/experimental/"&gt;Google Experimental Keyboard Search&lt;/a&gt; feature to the point that it is almost second nature. With it, I can bring up a search and get 10 result pages loading in the background, in under 5 seconds. The speed comes from the fact that you can search and open selected results without ever having to leave the keyboard. &lt;a href="http://www.google.com/search?q=rattlesnake&amp;esrch=BetaShortcuts"&gt;Try it out for yourself.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="http://www.google.com/experimental/"&gt;You can easily enable this feature&lt;/a&gt;, but there are a few minor annoyances you have to deal with:&lt;/p&gt;
&lt;ol&gt;&lt;li&gt;The "stickiness" of the feature is tricky and I frequently find that the Google search page eventually resets back to the default mode. The only way to solve this it seems is to go back and re-join the experiment.&lt;/li&gt;
&lt;li&gt;There is no way to skip forward or back in the search results. Essentially you are stuck to the first page of results. This actually used to not be an issue, but sometime around late 2008 the &lt;span style="font-weight:bold;"&gt;J&lt;/span&gt;/&lt;span style="font-weight:bold;"&gt;K&lt;/span&gt; keys were disabled from jumping to the next and previous result pages.&lt;/li&gt;&lt;/ol&gt;

&lt;h2&gt;Greasemonkey Script&lt;/h2&gt;
&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_GCbh8lju5Fo/SbDWja4f4NI/AAAAAAAAAHk/UIvk0y0EP-U/s1600-h/google_example.jpg"&gt;&lt;img style="float:right; margin:0 0 10px 10px;cursor:pointer; cursor:hand;width: 309px; height: 320px;" src="http://3.bp.blogspot.com/_GCbh8lju5Fo/SbDWja4f4NI/AAAAAAAAAHk/UIvk0y0EP-U/s320/google_example.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5309979864669872338" /&gt;&lt;/a&gt;
&lt;p&gt;Ok, so what is the solution to the bugs? The answer is &lt;a href="http://www.greasespot.net/"&gt;Greasemonkey&lt;/a&gt;. If you haven't heard of Greasemonkey, it is an &lt;a href="https://addons.mozilla.org/en-US/firefox/addon/748"&gt;add-on for Firefox&lt;/a&gt; users (&lt;span style="font-style:italic;"&gt;you do use Firefox right?&lt;/span&gt;) to tweak any web page you download with custom JavaScript code.&lt;/p&gt;

&lt;p&gt;I wrote a custom Greasemonkey script that will always enable the Google Experimental Keyboard Search feature. This script also solves the other two bugs listed above.&lt;/p&gt;

&lt;h2&gt;Setup&lt;/h2&gt;
&lt;p&gt;Using Greasemonkey and user scripts is easy.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;If you do not have Greasemonkey, &lt;a href="https://addons.mozilla.org/en-US/firefox/addon/748"&gt;install it from the Mozilla Add-on page&lt;/a&gt;. Restart Firefox.&lt;/li&gt;
&lt;li&gt;Install my &lt;a href="http://userscripts.org/scripts/show/43131"&gt;"Google Search Enhanced Keyboard Navigation"&lt;/a&gt; user script with the install button:

&lt;style type="text/css"&gt;
#install_script {
display: inline;
position: relative;
top: 10px;
}
#install_script a.userjs {
background:#333333 none repeat scroll 0 0;
border:1px solid #888888;
color:#FFFFFF;
font-size:1em;
font-weight:bold;
padding:3px 6px;
text-decoration:none;
margin-left: auto;
margin-right: auto;
}
#install_script a.userjs:hover {
background:#000000 none repeat scroll 0 0;
border-color:#333333;
color:#FF8800;
}
&lt;/style&gt;

&lt;div id="install_script"&gt;
&lt;table style="border-style:none;"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style="border-style:none;"&gt;
&lt;a class="userjs" href="http://userscripts.org/scripts/source/43131.user.js"&gt;Click To Install&lt;/a&gt;
&lt;/tbody&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;Usage&lt;/h2&gt;
&lt;p&gt;After the script is installed, the Google search result page will have a selection arrow on the left-hand side. The arrow indicates the active link that can be opened.&lt;/p&gt; 

&lt;p&gt;The following keyboard commands can control the page navigation:&lt;/p&gt;

&lt;style type="text/css"&gt;
th { 
text-align:center;
border: 1px solid;
}

thead { background-color: #DDDDDD; }
&lt;/style&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;&lt;th class="center"&gt;Key&lt;/th&gt;&lt;th&gt;Action&lt;/th&gt;&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;&lt;th&gt;H&lt;/th&gt;      &lt;td&gt;Opens the previous results page.&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;th&gt;J&lt;/th&gt;      &lt;td&gt;Selects the next result.&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;th&gt;K&lt;/th&gt;      &lt;td&gt;Selects the previous result.&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;th&gt;L&lt;/th&gt;      &lt;td&gt;Opens the next results page.&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;th&gt;O&lt;/th&gt;      &lt;td&gt;Opens the selected result.&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;th&gt;&amp;lt;Enter&amp;gt;&lt;/th&gt;  &lt;td&gt;Opens the selected result.&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;th&gt;/&lt;/th&gt;      &lt;td&gt;Puts the cursor in the search box.&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;th&gt;&amp;lt;Esc&amp;gt;&lt;/th&gt;    &lt;td&gt;Removes the cursor from the search box.&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;Happy Googling!&lt;/p&gt;
&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2100126952066830960-8356723568664252748?l=blog.tuxcoder.com'/&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/tuxcoder/~4/sXYuuJ24sVU" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.tuxcoder.com/feeds/8356723568664252748/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://blog.tuxcoder.com/2009/03/better-google-keyboard-shortcuts-using.html#comment-form" title="6 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2100126952066830960/posts/default/8356723568664252748?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2100126952066830960/posts/default/8356723568664252748?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/tuxcoder/~3/sXYuuJ24sVU/better-google-keyboard-shortcuts-using.html" title="Better Google Keyboard Shortcuts using Greasemonkey" /><author><name>Casey</name><uri>http://www.blogger.com/profile/01605425478146974127</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="02436649480923296246" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://3.bp.blogspot.com/_GCbh8lju5Fo/SbDPG9rR8cI/AAAAAAAAAHc/voMf5XL9nUk/s72-c/google_keyboard.jpg" height="72" width="72" /><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">6</thr:total><feedburner:origLink>http://blog.tuxcoder.com/2009/03/better-google-keyboard-shortcuts-using.html</feedburner:origLink></entry><entry gd:etag="W/&quot;C04FRX84cCp7ImA9WxVWGEw.&quot;"><id>tag:blogger.com,1999:blog-2100126952066830960.post-6985449489889158972</id><published>2009-02-08T16:29:00.046-10:00</published><updated>2009-02-27T23:05:14.138-10:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-02-27T23:05:14.138-10:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="expect" /><category scheme="http://www.blogger.com/atom/ns#" term="bash" /><category scheme="http://www.blogger.com/atom/ns#" term="ssh" /><category scheme="http://www.blogger.com/atom/ns#" term="rsync" /><category scheme="http://www.blogger.com/atom/ns#" term="cron" /><title>Automated File Synchronization with Rsync, Expect, and Cron</title><content type="html">&lt;b&gt;- Easy Backup / Synchronize / Share Files Between Multiple PCs&lt;/b&gt;

&lt;p&gt;If you're like me, you probably have two or more Linux system that you frequently switch between throughout the day. It's common to have multiple desk/lab systems at work, while at home manage a server, laptop, and media center.&lt;/p&gt;

&lt;p&gt;In a multi-machine, multi-network environment, each system gets customized with unique settings, scripts, documents, and code that need to be manually duplicated across every system.  With no easy way to do this, most
people resort to manually copying files or making gradual ad-hoc changes on every system, and eventually making
typos that linger undetected.&lt;/p&gt;

&lt;p&gt;If this sounds familiar to you, then this post is the solution.&lt;/p&gt;

&lt;span class="fullpost"&gt;
&lt;p&gt;After going through this tedium for a few weeks, I implemented a simple way to easily keep multiple Linux machines in sync, and it can also be used to quickly bootstrap a new machine with all of your customized
settings. An added benefit is that no 3rd-party software or background process are required, such as the case with &lt;a
href="http://www.getdropbox.com"&gt;DropBox&lt;/a&gt; (however if you feel DropBox will work in your situation, it might be the best option). &lt;/p&gt;

&lt;h2&gt;Overview&lt;/h2&gt;
&lt;p&gt; The automated file synchronization works as follows:
&lt;ol&gt;
&lt;li&gt;All files to sync are moved into a new directory (e.g. &lt;code&gt;~/rsync/&lt;/code&gt;) under the home path.&lt;/li&gt;
&lt;li&gt;Original file locations are replaced with symbolic links to the new location.&lt;/li&gt;
&lt;li&gt;A script synchronizes files in the sync sub-directory to an online server using rsync and SSH.&lt;/li&gt;
&lt;li&gt;Any changes to the local files, are eventually uploaded to the server. Also any newer files on the server will replace the out-of-date files on the local systems.&lt;/li&gt;
&lt;li&gt;The rsync command does not handle merging multiple changes, so some care may be needed to make sure any changes are made to freshly updated files. This can be accomplished by manually running the sync script.&lt;/li&gt;
&lt;li&gt;Lastly, to simplify "syncing" a fresh machine, a setup script can be used to quickly create all custom symlinks.&lt;/li&gt;
&lt;/ol&gt; &lt;/p&gt;

&lt;h2&gt;Online Server Storage&lt;/h2&gt;
&lt;p&gt;A file server is used as the repository to store and retrieve all data. Ideally the server must be accessible over the Internet and available 24/7. One could designate a local server, if every machine resides on the same network. The only requirements are that the machine allows for SSH logins and has enough storage space to meet your needs.&lt;/p&gt;

&lt;p&gt;In my case, I use an online web-hosting company called &lt;a href="https://www.nearlyfreespeech.net"&gt;NearlyFreeSpeech.net&lt;/a&gt;.  NFS is very unique in that there are no sign-up fees, and you are &lt;a href="https://www.nearlyfreespeech.net/services/hosting.php#pricing"&gt;only billed for the amount of services you use&lt;/a&gt;, such as storage space and transfer amounts. For my setup, the cost is somewhere around &lt;b&gt;$0.02 to $0.05 per month&lt;/b&gt;.  Assuming you have only a few megabytes of data you wish to synchronize, their prices are extremely low.

&lt;h2&gt;Synchronization Script&lt;/h2&gt;
&lt;p&gt;Now for the interesting part. The synchronization script requires &lt;a href="http://samba.anu.edu.au/rsync/"&gt;rsync&lt;/a&gt; and &lt;a href="http://expect.nist.gov/"&gt;Expect&lt;/a&gt; to login to the remote server and perform any file updates. Expect automates the SSH login process so it works without user interaction. Another method to automate SSH logins is to use shared keys, but some web-hosts do not enable this feature. Since this &lt;a href="http://www.google.com/search?&amp;q=passwordless+ssh+login"&gt; method is very common&lt;/a&gt;, I will not cover it here. If you are using NFS hosting, then you should stick with the default method.&lt;/p&gt;

&lt;p&gt;Ensure you have the required dependencies for the script.&lt;/p&gt;
&lt;pre&gt;sudo apt-get install rsync expect&lt;/pre&gt;

&lt;p&gt;Save the script to the &lt;code&gt;~/bin&lt;/code&gt; or &lt;code&gt;/usr/local/bin&lt;/code&gt;
directory.&lt;/p&gt;

&lt;div class="indent"&gt;&lt;div class="scroll"&gt;
&lt;table class="file"&gt;
&lt;thead&gt;&lt;tr&gt;&lt;td&gt;&lt;b&gt;File:&lt;/b&gt; sync.sh&lt;/td&gt;&lt;/tr&gt;&lt;/thead&gt;
&lt;tr&gt;&lt;td&gt;
&lt;pre&gt;&lt;span style='color:#696969; '&gt;#!/bin/bash&lt;/span&gt;

ROOT&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#40015a; '&gt;/home/private&lt;/span&gt;&lt;span style='color:#40015a; '&gt;/&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;
SITE&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"ssh.phx.nearlyfreespeech.net"&lt;/span&gt;
USER&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"my_user_name"&lt;/span&gt;
PASSWORD&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"my_password"&lt;/span&gt;
RSYNC_OPTS&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"-e &lt;/span&gt;&lt;span style='color:#0f69ff; '&gt;\\&lt;/span&gt;&lt;span style='color:#0f69ff; '&gt;\"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;ssh -o &lt;/span&gt;&lt;span style='color:#0000e6; '&gt;StrictHostKeyChecking&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;no&lt;/span&gt;&lt;span style='color:#0f69ff; '&gt;\\&lt;/span&gt;&lt;span style='color:#0f69ff; '&gt;\"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt; -azuv"&lt;/span&gt;

auto_rsync&lt;span style='color:#808030; '&gt;()&lt;/span&gt; &lt;span style='color:#800080; '&gt;{&lt;/span&gt;
   expect &lt;span style='color:#44aadd; '&gt;-c&lt;/span&gt; &lt;span style='color:#0000e6; '&gt;"eval spawn -noecho rsync --exclude .*.swp &lt;/span&gt;&lt;span style='color:#0000e6; '&gt;$RSYNC_OPTS&lt;/span&gt;&lt;span style='color:#0000e6; '&gt; &lt;/span&gt;&lt;span style='color:#0000e6; '&gt;$1&lt;/span&gt;&lt;span style='color:#0000e6; '&gt; &lt;/span&gt;&lt;span style='color:#0000e6; '&gt;$2&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;&lt;/span&gt;
&lt;span style='color:#0000e6; '&gt;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;match_max 10000k&lt;/span&gt;
&lt;span style='color:#0000e6; '&gt;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;expect &lt;/span&gt;&lt;span style='color:#0f69ff; '&gt;\"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;*?assword:*&lt;/span&gt;&lt;span style='color:#0f69ff; '&gt;\"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;&lt;/span&gt;
&lt;span style='color:#0000e6; '&gt;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;send -- &lt;/span&gt;&lt;span style='color:#0f69ff; '&gt;\"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;$PASSWORD&lt;/span&gt;&lt;span style='color:#0f69ff; '&gt;\r&lt;/span&gt;&lt;span style='color:#0f69ff; '&gt;\"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;&lt;/span&gt;
&lt;span style='color:#0000e6; '&gt;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;expect eof"&lt;/span&gt;
&lt;span style='color:#800080; '&gt;}&lt;/span&gt;

sync&lt;span style='color:#808030; '&gt;()&lt;/span&gt; &lt;span style='color:#800080; '&gt;{&lt;/span&gt;
   FILE&lt;span style='color:#808030; '&gt;=&lt;/span&gt;$&lt;span style='color:#800080; '&gt;(&lt;/span&gt;basename $1&lt;span style='color:#800080; '&gt;)&lt;/span&gt;
   DEST&lt;span style='color:#808030; '&gt;=&lt;/span&gt;$&lt;span style='color:#800080; '&gt;(&lt;/span&gt;dirname $1&lt;span style='color:#800080; '&gt;)&lt;/span&gt;
   &lt;span style='color:#696969; '&gt;# download remote site file to current location&lt;/span&gt;
   auto_rsync $USER@$SITE&lt;span style='color:#808030; '&gt;:&lt;/span&gt;$ROOT$FILE $DEST
   &lt;span style='color:#696969; '&gt;# update remote site file if newer than backup&lt;/span&gt;
   auto_rsync $1 $USER@$SITE&lt;span style='color:#808030; '&gt;:&lt;/span&gt;$ROOT
&lt;span style='color:#800080; '&gt;}&lt;/span&gt;

&lt;span style='color:#696969; '&gt;# backup specific files&lt;/span&gt;
sync &lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;$HOME&lt;/span&gt;&lt;span style='color:#40015a; '&gt;/rsync&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;/pre&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;span style="color:red; font-weight:bold;"&gt;Note:&lt;/span&gt; Modify the following variables in the script before using:
&lt;table&gt;
&lt;tr&gt;&lt;td&gt;&lt;b&gt;ROOT&lt;/b&gt;&lt;/td&gt;&lt;td&gt;remote directory location to store all files&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;b&gt;SITE&lt;/b&gt;&lt;/td&gt;&lt;td&gt;remote SSH server hostname&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;b&gt;USER&lt;/b&gt;&lt;/td&gt;&lt;td&gt;remote SSH user name&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;b&gt;PASSWORD&lt;/b&gt;&lt;/td&gt;&lt;td&gt;remote SSH password&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;

&lt;h3&gt;How To Use the Sync.sh Script&lt;/h3&gt;
&lt;p&gt;The last line of the script defines the local directory/file to backup to the remote SSH site. The command &lt;code&gt;sync "$HOME/rsync"&lt;/code&gt; tells the script that all files in the &lt;code&gt;~/rsync/&lt;/code&gt; directory should be copied to the remote site. If a newer version exists on the remote site it will not be updated, but instead copied to the local machine.&lt;/p&gt;

&lt;p&gt;I find that it is easiest to move all synchronized files under the &lt;code&gt;~/rsync/&lt;/code&gt; directory so that the script will automatically manage them. Another method would be to add additional directives to specific individual file names. Some users might find this method to be better suited for their needs. Keep in mind that you can not have duplicate filenames on the server in the &lt;code&gt;ROOT&lt;/code&gt; directory, and that each directive line
initiates a new SSH login (i.e. connection setup overhead).&lt;/p&gt;

&lt;h2&gt;Symlink Generator Script&lt;/h2&gt;
&lt;p&gt;If you wish to synchronize common environment files, then a symbolic link must be used in the path to link back to a file synchronized in &lt;code&gt;~/rsync/&lt;/code&gt;. To simplify the management of system files stored in the &lt;code&gt;~/rsync/&lt;/code&gt; directory, there is a second script to auto-generate symbolic links. First the script:&lt;/p&gt;

&lt;div class="indent"&gt;&lt;div class="scroll"&gt;
&lt;table class="file"&gt;
&lt;thead&gt;&lt;tr&gt;&lt;td&gt;&lt;b&gt;File:&lt;/b&gt; ~/rsync/install.sh&lt;/td&gt;&lt;/tr&gt;&lt;/thead&gt;
&lt;tr&gt;&lt;td&gt;
&lt;pre&gt;&lt;span style='color:#696969; '&gt;#!/bin/bash&lt;/span&gt;

RSYNC&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;$HOME&lt;/span&gt;&lt;span style='color:#40015a; '&gt;/rsync&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;

ln -sf $RSYNC&lt;span style='color:#40015a; '&gt;/&lt;/span&gt;&lt;span style='color:#800000; font-weight:bold; '&gt;.&lt;/span&gt;bashrc            ~&lt;span style='color:#40015a; '&gt;/&lt;/span&gt;
ln -sf $RSYNC&lt;span style='color:#40015a; '&gt;/&lt;/span&gt;&lt;span style='color:#800000; font-weight:bold; '&gt;.&lt;/span&gt;bash_aliases      ~&lt;span style='color:#40015a; '&gt;/&lt;/span&gt;
ln -sf $RSYNC&lt;span style='color:#40015a; '&gt;/&lt;/span&gt;&lt;span style='color:#800000; font-weight:bold; '&gt;.&lt;/span&gt;vim               ~&lt;span style='color:#40015a; '&gt;/&lt;/span&gt;
ln -sf $RSYNC&lt;span style='color:#40015a; '&gt;/&lt;/span&gt;&lt;span style='color:#800000; font-weight:bold; '&gt;.&lt;/span&gt;gvimrc            ~&lt;span style='color:#40015a; '&gt;/&lt;/span&gt;
ln -sf $RSYNC&lt;span style='color:#40015a; '&gt;/&lt;/span&gt;&lt;span style='color:#800000; font-weight:bold; '&gt;.&lt;/span&gt;vimrc             ~&lt;span style='color:#40015a; '&gt;/&lt;/span&gt;
ln -sf $RSYNC&lt;span style='color:#40015a; '&gt;/&lt;/span&gt;&lt;span style='color:#800000; font-weight:bold; '&gt;.&lt;/span&gt;forward           ~&lt;span style='color:#40015a; '&gt;/&lt;/span&gt;
ln -sf $RSYNC&lt;span style='color:#40015a; '&gt;/passwordmaker&lt;/span&gt;&lt;span style='color:#800000; font-weight:bold; '&gt;.&lt;/span&gt;rdf  ~&lt;span style='color:#40015a; '&gt;/&lt;/span&gt;

mkdir &lt;span style='color:#44aadd; '&gt;-p&lt;/span&gt; ~&lt;span style='color:#40015a; '&gt;/bin&lt;/span&gt;
ln -sf $RSYNC&lt;span style='color:#40015a; '&gt;/bin/sync&lt;/span&gt;&lt;span style='color:#800000; font-weight:bold; '&gt;.&lt;/span&gt;sh  ~&lt;span style='color:#40015a; '&gt;/bin&lt;/span&gt;&lt;span style='color:#40015a; '&gt;/&lt;/span&gt;&lt;/pre&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;/div&gt;&lt;/div&gt;

&lt;p style="color:red"&gt;&lt;b&gt;Warning:&lt;/b&gt; This script will replace any destination files that already exist. Be sure that you have saved copies of any files you do not wish to erase.&lt;/p&gt;

&lt;p&gt;This script lists many of the files in my home directory that I synchronize across machines. I store the script in the &lt;code&gt;~/rsync/&lt;/code&gt; directory, so that it is synchronized across each machine for easy execution. Before running the script for the first time on a new machine, make sure you have a backup of any files with localized changes you want to keep.&lt;/p&gt;

&lt;p&gt;Notice that &lt;code&gt;.vim&lt;/code&gt; is actually a directory. All the files and sub-directories stored in &lt;code&gt;.vim&lt;/code&gt; will work correctly with this single symlink.&lt;/p&gt;

&lt;p&gt;Another interesting feature is that the &lt;code&gt;sync.sh&lt;/code&gt; script is actually stored in &lt;code&gt;$RSYNC/bin/sync.sh&lt;/code&gt;. By doing this, the script can be quickly updated across all of the systems.&lt;/p&gt;

&lt;h2&gt;Cron Setup&lt;/h2&gt;

&lt;p&gt;To automate the synchronization process, a cron command can be added to each machine. The example defines a bi-hourly update of your files. You can increase or decrease the frequency as needed. Edit your crontab file with the command below:&lt;/p&gt;

&lt;pre&gt;crontab -e&lt;/pre&gt;

&lt;p&gt;Then add the following line to the end of the file:&lt;/p&gt;
&lt;pre&gt;36 */2 * * *     ~/bin/sync.sh &gt; /dev/null&lt;/pre&gt;

&lt;p&gt;The first number should be a random value between 0 and 59. This defines the minute of each even hour to connect to the remote SSH server. Using a random value prevents multiple systems from trying to update the SSH server at the same time.&lt;/p&gt;
&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2100126952066830960-6985449489889158972?l=blog.tuxcoder.com'/&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/tuxcoder/~4/SSJE1wnaFng" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.tuxcoder.com/feeds/6985449489889158972/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://blog.tuxcoder.com/2009/02/automated-file-synchronization-with.html#comment-form" title="7 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2100126952066830960/posts/default/6985449489889158972?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2100126952066830960/posts/default/6985449489889158972?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/tuxcoder/~3/SSJE1wnaFng/automated-file-synchronization-with.html" title="Automated File Synchronization with Rsync, Expect, and Cron" /><author><name>Casey</name><uri>http://www.blogger.com/profile/01605425478146974127</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="02436649480923296246" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">7</thr:total><feedburner:origLink>http://blog.tuxcoder.com/2009/02/automated-file-synchronization-with.html</feedburner:origLink></entry><entry gd:etag="W/&quot;A0cMRnoyfyp7ImA9WxVXEEo.&quot;"><id>tag:blogger.com,1999:blog-2100126952066830960.post-5256299786629676967</id><published>2009-01-24T23:09:00.020-10:00</published><updated>2009-02-07T21:44:47.497-10:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-02-07T21:44:47.497-10:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="iec958" /><category scheme="http://www.blogger.com/atom/ns#" term="xbmc" /><category scheme="http://www.blogger.com/atom/ns#" term="alsa" /><category scheme="http://www.blogger.com/atom/ns#" term="spdif" /><title>Solving Digital Audio Playback Issues in Linux</title><content type="html">&lt;p&gt;Today I spent hours debugging the digital audio output on my XBMC system running Ubuntu 8.10 (Intrepid Ibex). It turned out the fix was a simple one line command to set the mode of the IEC958 port. In this post I wanted to document a simple set of steps to debug audio output problems in Linux for anyone in a similar situation.&lt;/p&gt;

&lt;p&gt;The symptoms of the issue began when all XBMC audio from the digital coax became disabled, with the exception of DVD movie audio (that is AC3/DTS streams only). Getting at least some audio was a helpful start, and it meant the audio kernel module was still loading correctly. Knowing this, I assumed a system setting (either in ALSA or XBMC) had been misconfigured, even though I hadn't made any system changes before the problems.&lt;/p&gt;

&lt;p&gt;Since not everyone will be able to test DVD audio output right away, the process below shows you how to first check the detected audio hardware (if any) in your system. Then it steps through other issues that may be blocking a digital audio output device.&lt;/p&gt;

&lt;span class="fullpost"&gt;

&lt;h2&gt;Step 1: Setup&lt;/h2&gt;
&lt;p&gt;First off, make sure you have the ALSA tools installed to help debug the sound hardware.&lt;/p&gt;
&lt;pre&gt;sudo apt-get install alsa-utils&lt;/pre&gt;

&lt;h2&gt;Step 2: Hardware&lt;/h2&gt;
&lt;p&gt;Test the state of your current sound hardware. A problem in this area indicates either that your ALSA driver is not working, or not installed. Run the command:&lt;/p&gt;
&lt;pre&gt;aplay -l&lt;/pre&gt;
&lt;p&gt;You should see output as shown:&lt;/p&gt;
&lt;pre&gt;**** List of PLAYBACK Hardware Devices ****
card 0: VT82xx [HDA VIA VT82xx], device 0: ALC861 Analog [ALC861 Analog]
  Subdevices: 0/1
  Subdevice #0: subdevice #0
card 0: VT82xx [HDA VIA VT82xx], device 1: ALC861 Digital [ALC861 Digital]
  Subdevices: 1/1
  Subdevice #0: subdevice #0&lt;/pre&gt;

&lt;p&gt;The output above tells me that I have two(2) devices, labeled "ALC861 Analog" and "ALC861 Digital". We are only interested in the digital device for now. If you have no devices, or no digital device, than there is something wrong with your ALSA driver.&lt;/p&gt;

&lt;p&gt;One item of note, are the "card" and "device" values. If you would like to explicitly access the device then use these values in the form, &lt;code&gt;hw:&amp;lt;CARD,DEVICE&amp;gt;&lt;/code&gt;. For example, the digital device on my system would be &lt;code&gt;hw:0,1&lt;/code&gt;&lt;/p&gt;

&lt;h3&gt;Problem: No device listed&lt;/h3&gt;
&lt;p&gt;In this case your best bet is to find out what audio hardware you have and either search &lt;a href="http://www.google.com"&gt;Google&lt;/a&gt; or the &lt;a href="http://www.alsa-project.org"&gt;ALSA website&lt;/a&gt;. Your audio hardware can be found with the command:&lt;/p&gt;
&lt;pre&gt;lspci -v | grep Audio&lt;/pre&gt;

&lt;h3&gt;Problem: Only analog device listed&lt;/h3&gt;
&lt;p&gt;If you have an analog device, and no digital device. Then its possible that adding an argument when loading the audio driver module will resolve this. In the case of my ALC861 device driver module, it accepts the argument "&lt;code&gt;model=3stack-dig&lt;/code&gt;". More information on this step can be found in the &lt;a href="http://www.mjmwired.net/kernel/Documentation/sound/alsa/ALSA-Configuration.txt"&gt;ALSA Configuration Guide&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;Step 3: Mixer Setup / IEC958 Setup&lt;/h2&gt;
&lt;p&gt;Assuming the last step worked, now make sure the mixer settings are correctly set. The easiest way to do this is to run:&lt;/p&gt;
&lt;pre&gt;alsamixer&lt;/pre&gt;
&lt;p&gt;Make sure that the output devices are unmuted including the IEC958 device. A picture of my settings are shown:&lt;/p&gt;

&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_GCbh8lju5Fo/SXzv11sAkEI/AAAAAAAAAG0/c49I2wST8ps/s1600-h/htpc-alsa-settings.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 108px;" src="http://2.bp.blogspot.com/_GCbh8lju5Fo/SXzv11sAkEI/AAAAAAAAAG0/c49I2wST8ps/s320/htpc-alsa-settings.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5295370970104631362" /&gt;&lt;/a&gt;

&lt;p&gt;Second, you must verify the state of the IEC958 (digital out) device using the command:&lt;/p&gt; 
&lt;pre&gt;iecset&lt;/pre&gt; 

&lt;p&gt;which will produce the output:&lt;/p&gt;
&lt;pre&gt;Mode: consumer
Data: audio
Rate: 48000 Hz
Copyright: permitted
Emphasis: none
Category: PCM coder
Original: original
Clock: 1000 ppm&lt;/pre&gt;

&lt;p&gt;Verify that the &lt;code&gt;Data&lt;/code&gt; value is set to &lt;code&gt;audio&lt;/code&gt;. If it is not set, then run the command:&lt;/p&gt;
&lt;pre&gt;iecset audio on&lt;/pre&gt;

&lt;p style="color:red"&gt;My ultimate problem was that this value was not set correctly. Somehow it had switched to &lt;code&gt;non-audio&lt;/code&gt;, make sure you check this!&lt;/p&gt;

&lt;h2&gt;Step 4: Asound.conf&lt;/h2&gt;
&lt;p&gt;ALSA allows for a set of configuration files to create/modify plugins to the audio hardware layer. These plugins can perform rate conversion and add multi-source mixing capabilities. For now, I will recommend disabling then, as they could introduce unknown problems for now. The ALSA configuration files should either be removed or renamed on your system, until you can verify that the audio hardware is working. The locations of these files are:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;/etc/asound.conf&lt;/li&gt;
&lt;li&gt;~/.asoundrc&lt;/li&gt;&lt;/ul&gt;

&lt;h2&gt;Step 5: Test Audio Playback&lt;/h2&gt;
&lt;p&gt;This is the final step to verify your IEC958/spdif/Digital audio output is working. Before running these commands, it would help (though not required) to stop any processes that could be using the sound hardware. If you hear sound after this point, then you are likely done (or very close). You can use any of these commands to test for sound output:&lt;/p&gt;

&lt;pre&gt;aplay -D default /usr/share/sounds/alsa/Front_Center.wav
aplay -D plug:spdif /usr/share/sounds/alsa/Front_Center.wav
aplay -D plug:iec958 /usr/share/sounds/alsa/Front_Center.wav
aplay -D hw:0,1 /usr/share/sounds/alsa/Front_Center.wav&lt;/pre&gt;

&lt;h2&gt;Step 6: Playback Software Setup&lt;/h2&gt;
&lt;p&gt;I am including this section to cover the settings I am using for Digtal Audio in XBMC. Simply navigate to &lt;b&gt;Settings&lt;/b&gt;-&gt;&lt;b&gt;Systems&lt;/b&gt;-&gt;&lt;b&gt;Audio Hardware&lt;/b&gt;:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;Audio Ougput -&gt; &lt;code&gt;Digital&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Dolby Digital AC3 Capable Receiver -&gt; &lt;code&gt;ON&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;DTS Capable Receiver -&gt; &lt;code&gt;ON&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Audio Output Device -&gt; &lt;code&gt;default&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Passthrough Output Device -&gt; &lt;code&gt;iec958&lt;/code&gt;&lt;/li&gt;&lt;/ul&gt;

&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2100126952066830960-5256299786629676967?l=blog.tuxcoder.com'/&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/tuxcoder/~4/vNNRoHkYmGI" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.tuxcoder.com/feeds/5256299786629676967/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://blog.tuxcoder.com/2009/01/solving-digital-audio-playback-issues.html#comment-form" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2100126952066830960/posts/default/5256299786629676967?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2100126952066830960/posts/default/5256299786629676967?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/tuxcoder/~3/vNNRoHkYmGI/solving-digital-audio-playback-issues.html" title="Solving Digital Audio Playback Issues in Linux" /><author><name>Casey</name><uri>http://www.blogger.com/profile/01605425478146974127</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="02436649480923296246" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://2.bp.blogspot.com/_GCbh8lju5Fo/SXzv11sAkEI/AAAAAAAAAG0/c49I2wST8ps/s72-c/htpc-alsa-settings.png" height="72" width="72" /><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">1</thr:total><feedburner:origLink>http://blog.tuxcoder.com/2009/01/solving-digital-audio-playback-issues.html</feedburner:origLink></entry><entry gd:etag="W/&quot;A0QBSXg8fip7ImA9WxVXEUg.&quot;"><id>tag:blogger.com,1999:blog-2100126952066830960.post-1394860639599646955</id><published>2008-12-11T12:32:00.038-10:00</published><updated>2009-02-08T20:02:38.676-10:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-02-08T20:02:38.676-10:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="restructuredtext" /><category scheme="http://www.blogger.com/atom/ns#" term="vim" /><category scheme="http://www.blogger.com/atom/ns#" term="sphinx" /><title>Vim ReStructureText Macros</title><content type="html">&lt;p&gt;This post is about a great new document generator call &lt;a href="http://sphinx.pocoo.org/"&gt;Sphinx&lt;/a&gt;. It was created with the goal of simplifying document creation for Python projects, but can be used for much more. Using a simple text mark-up called &lt;a href="http://en.wikipedia.org/wiki/ReStructuredText"&gt;reStructuredText&lt;/a&gt;, it will output beautiful HTML and PDF documents such as books, manuals, journals, etc.&lt;/p&gt;

&lt;p&gt;Writing reStructuredText is extremely easy, however there are a few tweaks we can add to Vim to make adding reStructureText mark-up easier than using MS Word.&lt;/p&gt;

&lt;span class="fullpost"&gt;

&lt;p&gt;An example of reStructuredText from &lt;a href="http://docs.python.org/tutorial/stdlib.html"&gt;docs.python.org&lt;/a&gt; is shown below:&lt;/p&gt;

&lt;pre&gt;
**********************************
Brief Tour of the Standard Library
**********************************

.. _tut-os-interface:

Operating System Interface
==========================

The :mod:`os` module provides dozens of functions for interacting with the
operating system::

&gt;&gt;&gt; import os
&gt;&gt;&gt; os.system('time 0:02')
0
&gt;&gt;&gt; os.getcwd()      # Return the current working directory
'C:\\Python26'
&gt;&gt;&gt; os.chdir('/server/accesslogs')

Be sure to use the ``import os`` style instead of ``from os import *``.  This
will keep :func:`os.open` from shadowing the builtin :func:`open` function which
operates much differently.
&lt;/pre&gt;

&lt;p&gt;&lt;span style="font-weight:bold;"&gt;Section Macros&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;You will notice there are a few simple ways to denote sections of text. The most basic method is to underline text to indicate the start of a new section or sub-section. Because this is such a common operation when writing reStructureText, we can easily simplify these steps using macros in the &lt;a href="http://www.vim.org/"&gt;Vim&lt;/a&gt; text editor.&lt;/p&gt;

&lt;p&gt;Simply add the following macros to your &lt;span style="font-weight:bold;"&gt;~/.vimrc&lt;/span&gt; file to easily turn any line of text into a reStructuredText section heading.&lt;/p&gt;

&lt;pre&gt;
&lt;font color="#008000"&gt;&amp;quot; Restructured Text&lt;/font&gt;
&lt;font color="#008000"&gt;&amp;quot; #########################&lt;/font&gt;
   &lt;font color="#008000"&gt;&amp;quot; Ctrl-u 1:    underline Parts w/ #'s&lt;/font&gt;
   &lt;font color="#2040a0"&gt;noremap&lt;/font&gt;  &amp;lt;&lt;font color="#2040a0"&gt;C&lt;/font&gt;-&lt;font color="#2040a0"&gt;u&lt;/font&gt;&amp;gt;&lt;font color="#FF0000"&gt;1&lt;/font&gt; &lt;font color="#2040a0"&gt;yyPVr&lt;/font&gt;#&lt;font color="#2040a0"&gt;yyjp&lt;/font&gt;
   &lt;font color="#2040a0"&gt;inoremap&lt;/font&gt; &amp;lt;&lt;font color="#2040a0"&gt;C&lt;/font&gt;-&lt;font color="#2040a0"&gt;u&lt;/font&gt;&amp;gt;&lt;font color="#FF0000"&gt;1&lt;/font&gt; &amp;lt;&lt;font color="#2040a0"&gt;esc&lt;/font&gt;&amp;gt;&lt;font color="#2040a0"&gt;yyPVr&lt;/font&gt;#&lt;font color="#2040a0"&gt;yyjpA&lt;/font&gt;
   &lt;font color="#008000"&gt;&amp;quot; Ctrl-u 2:    underline Chapters w/ *'s&lt;/font&gt;
   &lt;font color="#2040a0"&gt;noremap&lt;/font&gt;  &amp;lt;&lt;font color="#2040a0"&gt;C&lt;/font&gt;-&lt;font color="#2040a0"&gt;u&lt;/font&gt;&amp;gt;&lt;font color="#FF0000"&gt;2&lt;/font&gt; &lt;font color="#2040a0"&gt;yyPVr&lt;/font&gt;*&lt;font color="#2040a0"&gt;yyjp&lt;/font&gt;
   &lt;font color="#2040a0"&gt;inoremap&lt;/font&gt; &amp;lt;&lt;font color="#2040a0"&gt;C&lt;/font&gt;-&lt;font color="#2040a0"&gt;u&lt;/font&gt;&amp;gt;&lt;font color="#FF0000"&gt;2&lt;/font&gt; &amp;lt;&lt;font color="#2040a0"&gt;esc&lt;/font&gt;&amp;gt;&lt;font color="#2040a0"&gt;yyPVr&lt;/font&gt;*&lt;font color="#2040a0"&gt;yyjpA&lt;/font&gt;
   &lt;font color="#008000"&gt;&amp;quot; Ctrl-u 3:    underline Section Level 1 w/ ='s&lt;/font&gt;
   &lt;font color="#2040a0"&gt;noremap&lt;/font&gt;  &amp;lt;&lt;font color="#2040a0"&gt;C&lt;/font&gt;-&lt;font color="#2040a0"&gt;u&lt;/font&gt;&amp;gt;&lt;font color="#FF0000"&gt;3&lt;/font&gt; &lt;font color="#2040a0"&gt;yypVr&lt;/font&gt;=
   &lt;font color="#2040a0"&gt;inoremap&lt;/font&gt; &amp;lt;&lt;font color="#2040a0"&gt;C&lt;/font&gt;-&lt;font color="#2040a0"&gt;u&lt;/font&gt;&amp;gt;&lt;font color="#FF0000"&gt;3&lt;/font&gt; &amp;lt;&lt;font color="#2040a0"&gt;esc&lt;/font&gt;&amp;gt;&lt;font color="#2040a0"&gt;yypVr&lt;/font&gt;=&lt;font color="#2040a0"&gt;A&lt;/font&gt;
   &lt;font color="#008000"&gt;&amp;quot; Ctrl-u 4:    underline Section Level 2 w/ -'s&lt;/font&gt;
   &lt;font color="#2040a0"&gt;noremap&lt;/font&gt;  &amp;lt;&lt;font color="#2040a0"&gt;C&lt;/font&gt;-&lt;font color="#2040a0"&gt;u&lt;/font&gt;&amp;gt;&lt;font color="#FF0000"&gt;4&lt;/font&gt; &lt;font color="#2040a0"&gt;yypVr&lt;/font&gt;-
   &lt;font color="#2040a0"&gt;inoremap&lt;/font&gt; &amp;lt;&lt;font color="#2040a0"&gt;C&lt;/font&gt;-&lt;font color="#2040a0"&gt;u&lt;/font&gt;&amp;gt;&lt;font color="#FF0000"&gt;4&lt;/font&gt; &amp;lt;&lt;font color="#2040a0"&gt;esc&lt;/font&gt;&amp;gt;&lt;font color="#2040a0"&gt;yypVr&lt;/font&gt;-&lt;font color="#2040a0"&gt;A&lt;/font&gt;
   &lt;font color="#008000"&gt;&amp;quot; Ctrl-u 5:    underline Section Level 3 w/ ^'s&lt;/font&gt;
   &lt;font color="#2040a0"&gt;noremap&lt;/font&gt;  &amp;lt;&lt;font color="#2040a0"&gt;C&lt;/font&gt;-&lt;font color="#2040a0"&gt;u&lt;/font&gt;&amp;gt;&lt;font color="#FF0000"&gt;5&lt;/font&gt; &lt;font color="#2040a0"&gt;yypVr&lt;/font&gt;^
   &lt;font color="#2040a0"&gt;inoremap&lt;/font&gt; &amp;lt;&lt;font color="#2040a0"&gt;C&lt;/font&gt;-&lt;font color="#2040a0"&gt;u&lt;/font&gt;&amp;gt;&lt;font color="#FF0000"&gt;5&lt;/font&gt; &amp;lt;&lt;font color="#2040a0"&gt;esc&lt;/font&gt;&amp;gt;&lt;font color="#2040a0"&gt;yypVr&lt;/font&gt;^&lt;font color="#2040a0"&gt;A&lt;/font&gt;
&lt;/pre&gt;


&lt;p&gt;The macro's can be enabled with the following keypress: &lt;span style="font-weight:bold;"&gt;Control-U&lt;/span&gt;, &lt;span style="font-weight:bold;"&gt;#&lt;/span&gt;. '#' must be a number from 1-5. The numbering order of the macro's follow the &lt;a href="http://sphinx.pocoo.org/rest.html#sections"&gt;Sphinx Section Heading mark-up definitions&lt;/a&gt;. For example the text 'MY SECTION HEADING', will be modified in the following manor for each macro.&lt;/p&gt;

&lt;p&gt;&lt;table style="width:50%"&gt;&lt;thead style="text-align:center;font-weight:bold;"&gt;
&lt;tr&gt;&lt;td&gt;Macro Shortcut&lt;/td&gt;&lt;td&gt;Final Output&lt;/td&gt;&lt;/tr&gt;&lt;/thead&gt;

&lt;tr&gt;&lt;td style="border-bottom-width: 1px; border-bottom-style: solid; padding:1em"&gt;Ctrl-U 1&lt;/td&gt;
&lt;td&gt;&lt;pre&gt;##################
MY SECTION HEADING
##################&lt;/pre&gt;&lt;/td&gt;
&lt;tr&gt;&lt;td style="border-bottom-width: 1px; border-bottom-style: solid; padding:1em"&gt;Ctrl-U 2&lt;/td&gt;
&lt;td&gt;&lt;pre&gt;******************
MY SECTION HEADING
******************&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td style="border-bottom-width: 1px; border-bottom-style: solid; padding:1em"&gt;Ctrl-U 3&lt;/td&gt;
&lt;td&gt;&lt;pre&gt;MY SECTION HEADING
==================&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td style="border-bottom-width: 1px; border-bottom-style: solid; padding:1em"&gt;Ctrl-U 4&lt;/td&gt;
&lt;td&gt;&lt;pre&gt;MY SECTION HEADING
------------------&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td style="padding:1em"&gt;Ctrl-U 5&lt;/td&gt;
&lt;td&gt;&lt;pre&gt;MY SECTION HEADING
^^^^^^^^^^^^^^^^^^&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;

&lt;p&gt;&lt;span style="font-weight:bold;"&gt;Stay Tuned ...&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;In the future, I plan on adding any other useful Vim macros for reStructuredText at the end of this post.&lt;/p&gt;

&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2100126952066830960-1394860639599646955?l=blog.tuxcoder.com'/&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/tuxcoder/~4/ncQJ3IMPDGo" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.tuxcoder.com/feeds/1394860639599646955/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://blog.tuxcoder.com/2008/12/vim-restructure-text-macros.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2100126952066830960/posts/default/1394860639599646955?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2100126952066830960/posts/default/1394860639599646955?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/tuxcoder/~3/ncQJ3IMPDGo/vim-restructure-text-macros.html" title="Vim ReStructureText Macros" /><author><name>Casey</name><uri>http://www.blogger.com/profile/01605425478146974127</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="02436649480923296246" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://blog.tuxcoder.com/2008/12/vim-restructure-text-macros.html</feedburner:origLink></entry><entry gd:etag="W/&quot;AkIARnY4fSp7ImA9WxVXEUs.&quot;"><id>tag:blogger.com,1999:blog-2100126952066830960.post-3863338552390431011</id><published>2008-06-05T20:31:00.024-10:00</published><updated>2009-02-08T22:35:47.835-10:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-02-08T22:35:47.835-10:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="tftpd" /><category scheme="http://www.blogger.com/atom/ns#" term="tftp" /><category scheme="http://www.blogger.com/atom/ns#" term="tftpd-hpa" /><category scheme="http://www.blogger.com/atom/ns#" term="ubuntu" /><title>Configure TFTPD Server in Ubuntu</title><content type="html">I recently needed a TFTP server in Ubuntu for PXE booting my MythTV system. Up until now I was using the built-in DnsMasq server, which was great. When I moved my DHCP service to my Linksys router I needed  stand-alone TFTP service. Hopefully this step-by-step HowTo will help someone get up an running quickly.

&lt;span class="fullpost"&gt;
&lt;ol&gt;&lt;li&gt;The first step is to install the TFTP client and server packages on your system. The client, &lt;span style="font-family:courier new;"&gt;tftp-hpa&lt;/span&gt;, is &lt;b&gt;not&lt;/b&gt; necessary, but helps to debug your system if anything goes wrong.
&lt;pre&gt;sudo apt-get install tftp-hpa tftpd-hpa&lt;/pre&gt;&lt;/li&gt;&lt;br&gt;


&lt;li&gt;The default directory location to store your TFTP files is &lt;span style="font-family:courier new;"&gt;/var/lib/tftpboot&lt;/span&gt;. You can chose your own location if you don't want to use the default. For now, setup the directory permissions of the TFTP server root directory:
&lt;pre&gt;sudo mkdir /var/lib/tftpboot
sudo chown nobody.nogroup /var/lib/tftpboot
sudo chmod 777 /var/lib/tftpboot&lt;/pre&gt;&lt;/li&gt;&lt;br&gt;


&lt;li&gt;Edit the TFTP server configuration file, &lt;span style="font-family:courier new;"&gt;/etc/default/tftpd-hpa&lt;/span&gt;, to put the service in daemon mode. Also, if you are using a custom TFTP directory, change &lt;span style="font-family:courier new;"&gt;/var/lib/tftpboot&lt;/span&gt; to the correct directory location.&lt;br&gt;&lt;br&gt;

&lt;div class="indent"&gt;&lt;div class="scroll"&gt;
&lt;table class="file"&gt;
&lt;thead&gt;&lt;tr&gt;&lt;td&gt;/etc/default/tftpd-hpa&lt;/td&gt;&lt;/tr&gt;&lt;/thead&gt;
&lt;tr&gt;&lt;td&gt;
&lt;pre&gt;#Defaults for tftpd-hpa
RUN_DAEMON="yes"
OPTIONS="-l -s /var/lib/tftpboot"&lt;/pre&gt;
&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;br&gt;

&lt;li&gt;Start the TFTP init script.
&lt;pre&gt;sudo /etc/init.d/tftpd-hpa start&lt;/pre&gt;&lt;/li&gt;&lt;br&gt;


&lt;li&gt;There should be an indication that the service started. Also, use netstat to check the port has been opened:
&lt;pre&gt;netstat -a |grep tftp&lt;/pre&gt;&lt;/li&gt;&lt;br&gt;


&lt;li&gt;After adding a file the TFTP server directory, you should be able to access a file using the TFTP client. Assuming the file &lt;span style="font-family:courier new;"&gt;/var/lib/tftpboot/pxelinux.0&lt;/span&gt; exists, try:
&lt;pre&gt;tftp localhost -c get pxelinux.0&lt;/pre&gt;
You will know that everyhing worked if the file &lt;span style="font-family:courier new;"&gt;pxelinux.0&lt;/span&gt; now exists in your current directory.&lt;/li&gt;
&lt;/ol&gt;

&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2100126952066830960-3863338552390431011?l=blog.tuxcoder.com'/&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/tuxcoder/~4/R3WTkwPZz4s" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.tuxcoder.com/feeds/3863338552390431011/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://blog.tuxcoder.com/2008/06/configure-tftp-server-in-ubuntu.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2100126952066830960/posts/default/3863338552390431011?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2100126952066830960/posts/default/3863338552390431011?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/tuxcoder/~3/R3WTkwPZz4s/configure-tftp-server-in-ubuntu.html" title="Configure TFTPD Server in Ubuntu" /><author><name>Casey</name><uri>http://www.blogger.com/profile/01605425478146974127</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="02436649480923296246" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://blog.tuxcoder.com/2008/06/configure-tftp-server-in-ubuntu.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CEcNRngzfCp7ImA9WxVSFUk.&quot;"><id>tag:blogger.com,1999:blog-2100126952066830960.post-3040319995280077811</id><published>2008-03-09T13:40:00.002-10:00</published><updated>2009-01-09T13:01:37.684-10:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-01-09T13:01:37.684-10:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="gedit" /><category scheme="http://www.blogger.com/atom/ns#" term="python" /><category scheme="http://www.blogger.com/atom/ns#" term="programming" /><category scheme="http://www.blogger.com/atom/ns#" term="ubuntu" /><title>Tweak Gedit into a Programmers IDE</title><content type="html">Gedit is a simple text editing program that is installed with many Linux distributions. At first glance it does not appear to have advanced features needed for an IDE, but with a little bit of configuration it can be turned into a really nice code editor supporting Java, Python, C, C++, HTML and many other languages. A sample screen shot of fully configured Gedit is shown.
&lt;br&gt;&lt;br&gt;
&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp3.blogger.com/_GCbh8lju5Fo/R8fPT0eT4CI/AAAAAAAAACU/DimLx86e2us/s1600-h/gedit.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://bp3.blogger.com/_GCbh8lju5Fo/R8fPT0eT4CI/AAAAAAAAACU/DimLx86e2us/s320/gedit.png" alt="" id="BLOGGER_PHOTO_ID_5172330636468543522" border="0" /&gt;&lt;/a&gt;&lt;span class="fullpost"&gt;
Before we begin, here is a quick list of Gedit's features:&lt;ul&gt;&lt;li&gt;Tabbed file view&lt;/li&gt;&lt;li&gt;Syntax highlighting&lt;/li&gt;&lt;li&gt;Inline command shell&lt;/li&gt;&lt;li&gt;Template code insertion&lt;/li&gt;&lt;li&gt;Basic tag browser&lt;/li&gt;&lt;li&gt;Session manager (save/restore windows)&lt;/li&gt;&lt;li&gt;Spell checking&lt;/li&gt;&lt;li&gt;Bracket matching&lt;/li&gt;&lt;li&gt;Auto indenting&lt;/li&gt;&lt;/ul&gt;Unfortunately, there are still a few features missing others might require in an IDE:&lt;ul&gt;&lt;li&gt;Syntax completion
&lt;/li&gt;&lt;li&gt;Integrated debugging environment&lt;/li&gt;&lt;li&gt;Side-by-side window view (i.e. split windows)&lt;/li&gt;&lt;li&gt;Graphical syntax color configuration (text only configuration at this point)
&lt;/li&gt;&lt;/ul&gt;Hopefully, the list above is manageable and may shrink in the future. So lets begin with the configuration.
&lt;br&gt;&lt;br&gt;
&lt;span style="font-weight: bold;"&gt;Basic Setup:&lt;/span&gt;&lt;br&gt;
The first step is to enable some built-in features of Gedit disabled by default. Under &lt;span style="font-weight: bold;font-family:courier new;" &gt;Edit-&gt;Preferences&lt;/span&gt;, configure the &lt;span style="font-weight: bold;font-family:courier new;" &gt;View&lt;/span&gt; and &lt;span style="font-weight: bold;"&gt;&lt;span style="font-family:courier new;"&gt;Edit&lt;/span&gt; &lt;/span&gt;tabs as shown:
&lt;br&gt;&lt;br&gt;
&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp0.blogger.com/_GCbh8lju5Fo/R8fVsEeT4GI/AAAAAAAAAC0/4vzh-XZkZ7c/s1600-h/view_pref.png"&gt;&lt;img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer;" src="http://bp0.blogger.com/_GCbh8lju5Fo/R8fVsEeT4GI/AAAAAAAAAC0/4vzh-XZkZ7c/s320/view_pref.png" alt="" id="BLOGGER_PHOTO_ID_5172337650150137954" border="0" /&gt;&lt;/a&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp1.blogger.com/_GCbh8lju5Fo/R8fVsUeT4HI/AAAAAAAAAC8/0ZkNyOT9SAU/s1600-h/edit_pref.png"&gt;&lt;img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer;" src="http://bp1.blogger.com/_GCbh8lju5Fo/R8fVsUeT4HI/AAAAAAAAAC8/0ZkNyOT9SAU/s320/edit_pref.png" alt="" id="BLOGGER_PHOTO_ID_5172337654445105266" border="0" /&gt;&lt;/a&gt;&lt;div class="clear"&gt;&lt;/div&gt;
The next tab allows you to set the default font and color scheme. For now, &lt;span style="font-weight: bold;"&gt;check the box to use Monospace 10 font&lt;/span&gt; by default. We will come back to the "Color Scheme" options later.
&lt;br&gt;&lt;br&gt;
&lt;span style="font-weight: bold;"&gt;Plugin Setup:&lt;/span&gt;&lt;br&gt;
The rest of changes in Gedit will be enabled by plug-ins. The default &lt;a href="http://live.gnome.org/Gedit/Plugins"&gt;Gedit Plugin Page&lt;/a&gt; is a great place to look for new and 3rd party plugins. Feel free to browse it later, but start with the following ones for now.
&lt;br&gt;&lt;br&gt;
&lt;div style="margin-left: 20px;"&gt;
&lt;span style="font-weight: bold;"&gt;Bracket Completion (Optional)&lt;/span&gt;&lt;br&gt;
Some programmers might like this feature, but usually I leave this one disabled.
&lt;br&gt;&lt;br&gt;
&lt;span style="font-weight: bold;"&gt;Code comment&lt;/span&gt;&lt;br&gt;
This is a really handy feature to comment/un-comment code quickly. Just us Ctrl-M or Ctrl-Shift-M to effectively enable or disable code. It also works on multiple lines.
&lt;br&gt;&lt;br&gt;
&lt;span style="font-weight: bold;"&gt;Color Picker&lt;/span&gt;&lt;br&gt;
For doing HTML programming or any document that needs color hex values, this plugin will bring up a color chooser widget, and insert the hex value after you hit 'ok'.
&lt;span style="font-weight: bold;"&gt;Document Statistics&lt;/span&gt;
I don't use this one too often, but can be handy to see your current line counts and file size.
&lt;br&gt;&lt;br&gt;
&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp0.blogger.com/_GCbh8lju5Fo/R9RkcBHyQqI/AAAAAAAAAEY/ElOpdkJezsQ/s1600-h/gedit-cmd.png"&gt;&lt;img style="float:right; margin:0 0 10px 10px;cursor:pointer; cursor:hand;" src="http://bp0.blogger.com/_GCbh8lju5Fo/R9RkcBHyQqI/AAAAAAAAAEY/ElOpdkJezsQ/s320/gedit-cmd.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5175872304255746722" /&gt;&lt;/a&gt;
&lt;span style="font-weight: bold;"&gt;Embedded Terminal&lt;/span&gt;&lt;br&gt;
Provides you with a terminal window at the bottom of the screen. This is really great for executing your code or looking up man pages quickly.&lt;div class=clear&gt;&lt;/div&gt;
&lt;br&gt;&lt;br&gt;

&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp3.blogger.com/_GCbh8lju5Fo/R9RkExHyQoI/AAAAAAAAAEI/b-awJD2RE-g/s1600-h/gedit_file.png"&gt;&lt;img style="float:right; margin:0 0 10px 10px;cursor:pointer; cursor:hand;" src="http://bp3.blogger.com/_GCbh8lju5Fo/R9RkExHyQoI/AAAAAAAAAEI/b-awJD2RE-g/s320/gedit_file.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5175871904823788162" /&gt;&lt;/a&gt;
&lt;span style="font-weight: bold;"&gt;File Browser Pane&lt;/span&gt;&lt;br&gt;
One of the nicer features, the File Browser will show a tree on the left hand side, so you can quickly open other files in your project.&lt;div class=clear&gt;&lt;/div&gt;
&lt;br&gt;&lt;br&gt;
&lt;span style="font-weight: bold;"&gt;Indent Lines&lt;/span&gt;&lt;br&gt;
Enables Tab (indenet) and Shift-Tab (remove indent) features on selected text. Enough said.
&lt;br&gt;&lt;br&gt;
&lt;span style="font-weight: bold;"&gt;Join/Split Lines&lt;/span&gt;&lt;br&gt;
The join split feature can come in handy when writing code comments. Just write the entire comment on a single line, and it Ctrl-Shift-J to split the line. It will also indent if your selection begins mid-line. Also good for dealing with files that are missing line breaks.
&lt;br&gt;&lt;br&gt;
&lt;span style="font-weight: bold;"&gt;Modelines&lt;/span&gt;&lt;br&gt;
For file that have embedded modelines at the end, this lets Gedit read those value and adjust accordingly. Great if you switch between multiple editors.
&lt;br&gt;&lt;br&gt;
&lt;span style="font-weight: bold;"&gt;Session Saver&lt;/span&gt;&lt;br&gt;
Another must have, this lets you build up project sessions, saving which files are opened. The next time you run Gedit, load your session and all your files are back to where they were.
&lt;br&gt;&lt;br&gt;
&lt;span style="font-weight: bold;"&gt;Smart Spaces&lt;/span&gt;&lt;br&gt;
This is a must have to allow the Backspace key to treat expanded tabs as a single tab character. Otherwise, you will have to delete every space of a "Tab".
&lt;br&gt;&lt;br&gt;
&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp0.blogger.com/_GCbh8lju5Fo/R9RmNBHyQtI/AAAAAAAAAEw/WhTG14fSiCQ/s1600-h/gedit_snippets.png"&gt;&lt;img style="float:right; margin:0 0 10px 10px;cursor:pointer; cursor:hand;" src="http://bp0.blogger.com/_GCbh8lju5Fo/R9RmNBHyQtI/AAAAAAAAAEw/WhTG14fSiCQ/s320/gedit_snippets.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5175874245580964562" /&gt;&lt;/a&gt;
&lt;span style="font-weight: bold;"&gt;&lt;a href="http://live.gnome.org/Gedit/Plugins/Snippets"&gt;Snippets&lt;/a&gt;&lt;/span&gt;&lt;br&gt;
Auto text completion tool. If you learn to use this, it will make your life much easier. Insertions can be done with a keyword-TAB or a keypress command. The defaults install comes with a number of built-in examples. And you can add as many snippets as you want, all divided by language.&lt;div class=clear&gt;&lt;/div&gt;
&lt;br&gt;&lt;br&gt;
&lt;span style="font-weight: bold;"&gt;Spell Checker&lt;/span&gt;&lt;br&gt;
Includes auto-spell check feature, but unfortunately does not restrict checking to just comments. Maybe it can be fixed soon.
&lt;br&gt;&lt;br&gt;
&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp1.blogger.com/_GCbh8lju5Fo/R9RktRHyQrI/AAAAAAAAAEg/t80MzG8H_VI/s1600-h/gedit_symbol.png"&gt;&lt;img style="float:right; margin:0 0 10px 10px;cursor:pointer; cursor:hand;" src="http://bp1.blogger.com/_GCbh8lju5Fo/R9RktRHyQrI/AAAAAAAAAEg/t80MzG8H_VI/s320/gedit_symbol.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5175872600608490162" /&gt;&lt;/a&gt;
&lt;span style="font-weight: bold;"&gt;&lt;a href="http://www.micahcarrick.com/11-14-2007/gedit-symbol-browser-plugin.html"&gt;Symbol Browser&lt;/a&gt;&lt;/span&gt;&lt;br&gt;
This plugin creates a window on the left hand side that provides a quick way to jump between functions an classes of your code. Unfortunately there is no in-editor symbol browser yet.&lt;div class=clear&gt;&lt;/div&gt;
&lt;br&gt;&lt;br&gt;
&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp0.blogger.com/_GCbh8lju5Fo/R9RlaBHyQsI/AAAAAAAAAEo/cmdkKKBJSJU/s1600-h/gedit_tags.png"&gt;&lt;img style="float:right; margin:0 0 10px 10px;cursor:pointer; cursor:hand;" src="http://bp0.blogger.com/_GCbh8lju5Fo/R9RlaBHyQsI/AAAAAAAAAEo/cmdkKKBJSJU/s320/gedit_tags.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5175873369407636162" /&gt;&lt;/a&gt;
&lt;span style="font-weight: bold;"&gt;Tag List&lt;/span&gt;&lt;br&gt;
When modifying HTML or XML files, this plugin provides a tag browser on the left hand side.&lt;div class=clear&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;br&gt;&lt;br&gt;
&lt;span style="font-weight: bold;"&gt;Syntax Color Themes:&lt;/span&gt;&lt;br&gt;
Gedit provides a few built-in color themes, but there is no way to modify the installed color themes other than directly editing the theme files. The current theme files are stored in &lt;span style="font-weight: bold; font-family: courier new;"&gt;/usr/share/gtksourceview-2.0/styles&lt;/span&gt;. You can use these to create your own theme files. Once you have your theme file, you can import it into Gedit using the option &lt;span style="font-weight:bold; font-family: courier new;"&gt;Preferences-&gt;Fonts &amp; Colors-&gt;Add&lt;/span&gt;.
&lt;br&gt;&lt;br&gt;
If you want to find a specific element to change the color of, your best bet is to look into &lt;span style="font-weight: bold; font-family: courier new;"&gt;/usr/share/gtksourceview-2.0/language-specs/*.lang&lt;/span&gt;
&lt;br&gt;&lt;br&gt;
A &lt;a href="http://files.tuxcoder.com/blog/gedit_syntax.xml"&gt;sample syntax file&lt;/a&gt; is shown. 
&lt;pre class=code&gt;
&amp;lt;?xml version="1.0" encoding="UTF-8"?&amp;gt;

&amp;lt;style-scheme id="custom" _name="Custom" version="1.0"&amp;gt;
  &amp;lt;_description&amp;gt;Custom color scheme&amp;lt;/_description&amp;gt;

  &amp;lt;!-- Palette --&amp;gt;
  &amp;lt;color name="blue"       value="#0000FF"/&amp;gt;
  &amp;lt;color name="magenta"    value="#f066f0"/&amp;gt;
  &amp;lt;color name="violet"     value="#9587e9"/&amp;gt;
  &amp;lt;color name="cyan"       value="#00fbff"/&amp;gt;
  &amp;lt;color name="green"      value="#00ff00"/&amp;gt;
  &amp;lt;color name="bordeaux"   value="#d47575"/&amp;gt;
  &amp;lt;color name="orange"     value="#ffa500"/&amp;gt;
  &amp;lt;color name="red"        value="#FF0000"/&amp;gt;
  &amp;lt;color name="yellow"     value="#f1f16e"/&amp;gt;
  &amp;lt;color name="mustard"    value="#b8b86f"/&amp;gt;
  &amp;lt;color name="purple"     value="#bb41ea"/&amp;gt;
  &amp;lt;color name="grey3"      value="#353535"/&amp;gt; 
  &amp;lt;color name="grey4"      value="#4d4d4d"/&amp;gt;
  &amp;lt;color name="grey7"      value="#7f7f7f"/&amp;gt;
  &amp;lt;color name="grey9"      value="#969696"/&amp;gt;
  &amp;lt;color name="greyA"      value="#a7a7a7"/&amp;gt;
  &amp;lt;color name="greyB"      value="#bfbfbf"/&amp;gt;
  &amp;lt;color name="greyE"      value="#e5e5e5"/&amp;gt;

  &amp;lt;!-- Global Settings --&amp;gt;
  &amp;lt;style name="text"                        foreground="#white" background="#black"/&amp;gt;
  &amp;lt;style name="selection"                   background="greyB"/&amp;gt;
  &amp;lt;style name="cursor"                      foreground="#white"/&amp;gt;
  &amp;lt;style name="current-line"                foreground="green" background="grey3"/&amp;gt;
  &amp;lt;style name="line-numbers"                foreground="green" background="grey3"/&amp;gt;

  &amp;lt;!-- Bracket Matching --&amp;gt;
  &amp;lt;style name="bracket-match"               foreground="green" background="#black" bold="true"/&amp;gt;
  &amp;lt;style name="bracket-mismatch"            foreground="red"   background="#black" bold="true"/&amp;gt;

  &amp;lt;!-- Search Matching --&amp;gt;
  &amp;lt;style name="search-match"                foreground="red"   background="mustard" bold="true"/&amp;gt;  
  
  &amp;lt;!-- Comments --&amp;gt;
  &amp;lt;style name="def:comment"                 foreground="greyA" bold="false"/&amp;gt;
  &amp;lt;style name="def:shebang"                 foreground="cyan" bold="false"/&amp;gt;
  &amp;lt;style name="def:doc-comment-element"     italic="true"/&amp;gt;

  &amp;lt;!-- Constants --&amp;gt;
  &amp;lt;style name="def:constant"                foreground="red"/&amp;gt;
  &amp;lt;style name="def:special-constant"        foreground="red"/&amp;gt;
  &amp;lt;style name="def:special-char"            foreground="violet"/&amp;gt;
  &amp;lt;style name="def:decimal"                 foreground="orange"/&amp;gt;
  &amp;lt;style name="def:base-n-integer"          foreground="orange"/&amp;gt;
  &amp;lt;style name="def:floating-point"          foreground="orange"/&amp;gt;
  &amp;lt;style name="def:complex"                 foreground="orange"/&amp;gt;
  &amp;lt;style name="def:character"               foreground="cyan"/&amp;gt;
  &amp;lt;style name="def:string"                  foreground="bordeaux"/&amp;gt;

  &amp;lt;!-- Identifiers --&amp;gt;
  &amp;lt;style name="def:identifier"              foreground="cyan"/&amp;gt;
  &amp;lt;style name="def:function"                foreground="green"/&amp;gt;
  &amp;lt;style name="def:keyword"                 foreground="yellow"/&amp;gt;
  &amp;lt;style name="def:builtin"                 foreground="red"/&amp;gt;

  &amp;lt;!-- Statements --&amp;gt;
  &amp;lt;style name="def:statement"               foreground="yellow" bold="true"/&amp;gt;

  &amp;lt;!-- Types --&amp;gt;
  &amp;lt;style name="def:type"                    foreground="green" bold="true"/&amp;gt;
  &amp;lt;style name="def:boolean"                 foreground="green" bold="true"/&amp;gt;

  &amp;lt;!-- Others --&amp;gt;
  &amp;lt;style name="def:preprocessor"            foreground="magenta"/&amp;gt;
  &amp;lt;style name="def:error"                   background="red" bold="true"/&amp;gt;
  &amp;lt;style name="def:note"                    foreground="blue" background="yellow" bold="true"/&amp;gt;
  &amp;lt;style name="def:underlined"              italic="true" underline="true"/&amp;gt;

  &amp;lt;!-- Language specific styles --&amp;gt;
  &amp;lt;style name="diff:added-line"             foreground="#008B8B"/&amp;gt;
  &amp;lt;style name="diff:removed-line"           foreground="#6A5ACD"/&amp;gt;
  &amp;lt;style name="diff:changed-line"           use-style="def:preprocessor"/&amp;gt;
  &amp;lt;style name="diff:special-case"           use-style="def:constant"/&amp;gt;
  &amp;lt;style name="diff:location"               use-style="def:statement"/&amp;gt;
  &amp;lt;style name="diff:diff-file"              use-style="def:type"/&amp;gt;

  &amp;lt;style name="xml:tags"                    foreground="cyan"/&amp;gt;
  &amp;lt;style name="xml:attribute-name"          foreground="violet"/&amp;gt;
  &amp;lt;style name="xml:namespace"               foreground="green" bold="true"/&amp;gt;

  &amp;lt;style name="js:object"                   foreground="#2E8B57" bold="true"/&amp;gt;
  &amp;lt;style name="js:constructors"             foreground="#008B8B"/&amp;gt;

  &amp;lt;style name="latex:display-math"          foreground="#6A5ACD"/&amp;gt;
  &amp;lt;style name="latex:command"               foreground="#2E8B57" bold="true"/&amp;gt;
  &amp;lt;style name="latex:include"               use-style="def:preprocessor"/&amp;gt;

  &amp;lt;style name="sh:variable1"                foreground="#6A5ACD"/&amp;gt;
  &amp;lt;style name="sh:variable2"                foreground="#008B8B"/&amp;gt;

  &amp;lt;!-- legacy styles for old lang files --&amp;gt;
  &amp;lt;style name="Others"                      foreground="#2E8B57" bold="true"/&amp;gt;
  &amp;lt;style name="Others 2"                    foreground="#008B8B"/&amp;gt;
  &amp;lt;style name="Others 3"                    foreground="#6A5ACD"/&amp;gt;

&amp;lt;!--  &amp;lt;style name="python:string-conversion"    use-style="def:error"/&amp;gt;--&amp;gt;
&amp;lt;!--  &amp;lt;style name="python:module-handler"       foreground="magenta"/&amp;gt;--&amp;gt;
&amp;lt;!--  &amp;lt;style name="python:special-variable"     use-style="def:identifier"/&amp;gt;--&amp;gt;
&amp;lt;!--  &amp;lt;style name="python:builtin-constant"     use-style="def:constant"/&amp;gt;--&amp;gt;
&amp;lt;!--  &amp;lt;style name="python:builtin-object"       use-style="def:type"/&amp;gt;--&amp;gt;
&amp;lt;!--  &amp;lt;style name="python:builtin-function"     use-style="def:function"/&amp;gt;--&amp;gt;
&amp;lt;!--  &amp;lt;style name="python:boolean"              use-style="def:type"/&amp;gt;--&amp;gt;

&amp;lt;/style-scheme&amp;gt;
&lt;/pre&gt;

&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2100126952066830960-3040319995280077811?l=blog.tuxcoder.com'/&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/tuxcoder/~4/EqPhaA1xiLQ" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.tuxcoder.com/feeds/3040319995280077811/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://blog.tuxcoder.com/2008/02/tweak-gedit-into-programmers-ide.html#comment-form" title="3 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2100126952066830960/posts/default/3040319995280077811?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2100126952066830960/posts/default/3040319995280077811?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/tuxcoder/~3/EqPhaA1xiLQ/tweak-gedit-into-programmers-ide.html" title="Tweak Gedit into a Programmers IDE" /><author><name>Casey</name><uri>http://www.blogger.com/profile/01605425478146974127</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="02436649480923296246" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://bp3.blogger.com/_GCbh8lju5Fo/R8fPT0eT4CI/AAAAAAAAACU/DimLx86e2us/s72-c/gedit.png" height="72" width="72" /><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">3</thr:total><feedburner:origLink>http://blog.tuxcoder.com/2008/02/tweak-gedit-into-programmers-ide.html</feedburner:origLink></entry><entry gd:etag="W/&quot;D0MFQ3w5eyp7ImA9WxdQEUg.&quot;"><id>tag:blogger.com,1999:blog-2100126952066830960.post-122049801370810675</id><published>2008-02-21T18:42:00.011-10:00</published><updated>2008-06-10T17:36:52.223-10:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-06-10T17:36:52.223-10:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="metacity" /><category scheme="http://www.blogger.com/atom/ns#" term="keyboard shortcuts" /><title>Modify Ctrl-Alt-Del Keyboard Shortcut in Ubuntu</title><content type="html">The Ubuntu desktop has a simple GUI to modify keyboard shortcuts, but I noticed that any changes to the Ctrl-Alt-Del key combination would not work. The problem was that no matter where I assigned the Ctrl-Alt-Del shortcut, it would always open the "Logout" menu. The workaround for this bug is typed out in this post.&lt;span class="fullpost"&gt;
&lt;br&gt;&lt;br&gt;
1. Make sure to disable the "Log out" action from the Keyboard Shortcuts editor (System-&gt;Preferences-&gt;Keyboard Shortcuts), by highlighting the line and pressing the "Backspace" key.&lt;br&gt;&lt;br&gt;

&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp2.blogger.com/_GCbh8lju5Fo/R75WUu2AX4I/AAAAAAAAAB8/PnjAYyZXu3A/s1600-h/shortcut1.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://bp2.blogger.com/_GCbh8lju5Fo/R75WUu2AX4I/AAAAAAAAAB8/PnjAYyZXu3A/s320/shortcut1.png" alt="" id="BLOGGER_PHOTO_ID_5169664336439828354" border="0" /&gt;&lt;/a&gt;&lt;br&gt;

2. Open the Configuration Editor (System Tools-&gt;Configuration Editor), and disable the metacity Ctrl-Alt-Del binding under &lt;span style="font-weight: bold;"&gt;/apps/metacity/global_keybindings&lt;/span&gt;. Do this by right-clicking the key with the Ctrl-Alt-Del binding (i.e "run_command_1") and selecting "Unset Key"&lt;br&gt;&lt;br&gt;

&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp3.blogger.com/_GCbh8lju5Fo/R75WU-2AX5I/AAAAAAAAACE/C4T0bEYUB4k/s1600-h/conf_edit1.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://bp3.blogger.com/_GCbh8lju5Fo/R75WU-2AX5I/AAAAAAAAACE/C4T0bEYUB4k/s320/conf_edit1.png" alt="" id="BLOGGER_PHOTO_ID_5169664340734795666" border="0" /&gt;&lt;/a&gt;&lt;br&gt;

3. In the same window, go to the next folder&lt;span style="font-weight: bold;"&gt; /apps/metacity/keybinding_commands&lt;/span&gt;. Select the matching command from the previous step (i.e. "command_1") and unset the key in the same manor as step 2. Close the Configuration Editor.&lt;br&gt;&lt;br&gt;

&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp0.blogger.com/_GCbh8lju5Fo/R75WVO2AX6I/AAAAAAAAACM/xmrJrG7qSzA/s1600-h/conf_edit2.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://bp0.blogger.com/_GCbh8lju5Fo/R75WVO2AX6I/AAAAAAAAACM/xmrJrG7qSzA/s320/conf_edit2.png" alt="" id="BLOGGER_PHOTO_ID_5169664345029762978" border="0" /&gt;&lt;/a&gt;&lt;br&gt;

4. Finally, go back to the Keyboard Shortcuts app, and now select the new action for Ctrl-Alt-Del. Everything should work as expected now.&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2100126952066830960-122049801370810675?l=blog.tuxcoder.com'/&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/tuxcoder/~4/qn-6auDWi5k" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.tuxcoder.com/feeds/122049801370810675/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://blog.tuxcoder.com/2008/02/modify-ctrl-alt-del-keyboard-shortcut.html#comment-form" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2100126952066830960/posts/default/122049801370810675?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2100126952066830960/posts/default/122049801370810675?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/tuxcoder/~3/qn-6auDWi5k/modify-ctrl-alt-del-keyboard-shortcut.html" title="Modify Ctrl-Alt-Del Keyboard Shortcut in Ubuntu" /><author><name>Casey</name><uri>http://www.blogger.com/profile/01605425478146974127</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="02436649480923296246" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://bp2.blogger.com/_GCbh8lju5Fo/R75WUu2AX4I/AAAAAAAAAB8/PnjAYyZXu3A/s72-c/shortcut1.png" height="72" width="72" /><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">2</thr:total><feedburner:origLink>http://blog.tuxcoder.com/2008/02/modify-ctrl-alt-del-keyboard-shortcut.html</feedburner:origLink></entry><entry gd:etag="W/&quot;AkEFQXg4cCp7ImA9WxVXEUs.&quot;"><id>tag:blogger.com,1999:blog-2100126952066830960.post-1165535311421115136</id><published>2008-02-09T13:50:00.021-10:00</published><updated>2009-02-08T22:36:50.638-10:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-02-08T22:36:50.638-10:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="bash" /><category scheme="http://www.blogger.com/atom/ns#" term="utility" /><title>Countdown Alarm</title><content type="html">&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://files.tuxcoder.com/blog/countdown.sh"&gt;&lt;img style="margin: 0pt 0pt 10px 10px; float: right; cursor: pointer;" src="http://bp0.blogger.com/_GCbh8lju5Fo/R66j5O2AXyI/AAAAAAAAAA8/f1K1EFWK6Lg/s320/download-now-sm.gif" alt="" id="BLOGGER_PHOTO_ID_5165246026273021730" border="0" /&gt;&lt;/a&gt;

Recently I was looking for a "countdown alarm clock" in Linux and decided to write a Bash script to do the job. The goal was to allow the user to enter a target date and time, then display a clock with the remaining time. An example of the output is below.
&lt;br&gt;&lt;br&gt;

&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp3.blogger.com/_GCbh8lju5Fo/R8jHgkeT4II/AAAAAAAAADE/KFbliMdD2wo/s1600-h/countdown.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://bp3.blogger.com/_GCbh8lju5Fo/R8jHgkeT4II/AAAAAAAAADE/KFbliMdD2wo/s320/countdown.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5172603534395564162" /&gt;&lt;/a&gt;

&lt;span class="fullpost"&gt;
&lt;span style="font-weight: bold;"&gt;Features:&lt;/span&gt;
&lt;ul&gt;
&lt;li&gt;Remaining time stays at top left corner of the screen and continuously updates.&lt;/li&gt;
&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Update!&lt;/span&gt;: Output time inserted in Xterm title bar.&lt;/li&gt;
&lt;li&gt;Target time can be specified using natural language string. (i.e. Feb 21 5PM 2010)&lt;/li&gt;
&lt;li&gt;Remaining time displayed in years, months, days, hours, minutes, and seconds remaining.&lt;/li&gt;
&lt;li&gt;Year, month, and day output is optional depending on the length of the remaining time.&lt;/li&gt;
&lt;/ul&gt;

&lt;span style="font-weight: bold;"&gt;Implementation:&lt;/span&gt;
&lt;br&gt;&lt;br&gt;

It might seem complicated to do this, but the Unix 'date' utility handles almost all of the program logic for us. For example, to convert a generic date string into the number of seconds from Jan 1st, 1970:

&lt;pre&gt;date -d "DATE STRING" +%s&lt;/pre&gt;
&lt;br&gt;

The date command can then easily do the reverse operation, using the output of the first command, where "SECONDS" is number of seconds from Jan 1st, 1970:

&lt;pre&gt;date -d @SECONDS&lt;/pre&gt;
&lt;br&gt;

Some screen drawing tricks were accomplished with special terminal escape commands. These are used to move the cursor out of the way, and clear the line before each update.
&lt;br&gt;&lt;br&gt;

&lt;div class="indent"&gt;&lt;div class="scroll"&gt;
&lt;table class="file"&gt;
&lt;thead&gt;&lt;tr&gt;&lt;td&gt;&lt;b&gt;Code:&lt;/b&gt; countdown.sh&lt;/td&gt;&lt;/tr&gt;&lt;/thead&gt;
&lt;tr&gt;&lt;td&gt;
&lt;pre&gt;#!/bin/bash
BLINK=1
INPUT_DATE=$@
STOP=`date -d "$INPUT_DATE" +%s`
[ $? == 0 ] || exit -1

function print_time
{
   echo -ne "\033]0;$@\007"   # update window title
   echo -ne "$@"              # update terminal
}

clear

while [ 1 ]; do
   NOW=`date +%s`
   TIME=''
   
   if [ $STOP -gt $NOW ]; then
      REMAIN=$[ $STOP - $NOW ]

      YEAR=`date -u -d @$REMAIN +%Y`
      YEAR=$[ $YEAR - 1970 ]
      [ $YEAR -gt 0 ] &amp;&amp; TIME="${TIME}$YEAR year"
      [ $YEAR -gt 1 ] &amp;&amp; TIME="${TIME}s"
      [ $YEAR -gt 0 ] &amp;&amp; TIME="${TIME}, "

      MONTH=`date -u -d @$REMAIN +%_m`
      MONTH=$[ $MONTH - 1 ]
      [ $MONTH -gt 0 ] &amp;&amp; TIME="${TIME}$MONTH month"
      [ $MONTH -gt 1 ] &amp;&amp; TIME="${TIME}s"
      [ $MONTH -gt 0 ] &amp;&amp; TIME="${TIME}, "

      DAY=`date -u -d @$REMAIN +%_d`
      DAY=$[ $DAY - 1 ]
      [ $DAY -gt 0 ] &amp;&amp; TIME="${TIME}$DAY day"
      [ $DAY -gt 1 ] &amp;&amp; TIME="${TIME}s"
      [ $DAY -gt 0 ] &amp;&amp; TIME="${TIME}, "

      TIME="${TIME}`date -u -d @$REMAIN +%T`"
      print_time $TIME
   else
      [ $BLINK -eq 1 ] &amp;&amp; print_time "00:00:00"
      [ $BLINK -eq 0 ] &amp;&amp; print_time ""
      BLINK=$[ $BLINK ^ 1 ]
   fi

   echo -ne "\e[s"            # save cursor position
   echo -ne "\e[1000;1000f"   # move cursor to bottom right of screen

   sleep 0.5 
   echo -ne "\e[u"   # restore cursor position
   echo -ne "\r"     # move cursor to start of line
   echo -ne "\e[0K"  # clear line
done&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;br&gt;

&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://files.tuxcoder.com/blog/countdown.sh"&gt;&lt;img style="cursor: pointer;" src="http://bp1.blogger.com/_GCbh8lju5Fo/R66ihe2AXxI/AAAAAAAAAA0/gXkCJEPb5mY/s320/download-now-sm.gif" alt="" id="BLOGGER_PHOTO_ID_5165244518739500818" border="0" /&gt;&lt;/a&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2100126952066830960-1165535311421115136?l=blog.tuxcoder.com'/&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/tuxcoder/~4/V9rzGvUQL6Q" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.tuxcoder.com/feeds/1165535311421115136/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://blog.tuxcoder.com/2008/02/countdown-alarm.html#comment-form" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2100126952066830960/posts/default/1165535311421115136?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2100126952066830960/posts/default/1165535311421115136?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/tuxcoder/~3/V9rzGvUQL6Q/countdown-alarm.html" title="Countdown Alarm" /><author><name>Casey</name><uri>http://www.blogger.com/profile/01605425478146974127</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="02436649480923296246" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://bp0.blogger.com/_GCbh8lju5Fo/R66j5O2AXyI/AAAAAAAAAA8/f1K1EFWK6Lg/s72-c/download-now-sm.gif" height="72" width="72" /><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">1</thr:total><feedburner:origLink>http://blog.tuxcoder.com/2008/02/countdown-alarm.html</feedburner:origLink></entry></feed>
