Posts tagged "linux"

Getting to know Logical Volume Manager on Ubuntu Precise

Notes

You can use LVM for /boot, /, and any other filesystem. GRUB in lucid and later supports booting from LVM.

You don't need to partition disks to use them with LVM. In fact, this is usually just annoying and not useful. Use pvcreate directly on the block devices.

Directly using the block devices also overcomes the MBR format's limit of 2.1 terabytes. LVM supports PVs on block devices up to who knows how big.

  • For 32-bit CPUs on 2.6 kernels, the maximum LV size is 16TB. That'll do you.

  • For 64-bit CPUs on 2.6 kernels, the maximum LV size is 8EB.

See also:

TLDP: http://tldp.org/HOWTO/LVM-HOWTO/lvm2faq.html#AEN407

Now, let's start playing around with LVM.

Setup a KVM with some extra block devices to use as an LVM sandbox

I've installed 64-bit Precise Server into a VM called precise-x64. I've added the block devices as SCSI devices

    #!/bin/bash

    VM="precise-x64"

    for i in {a..f}; do  
      sudo qemu-img create -f qcow2 /var/lib/libvirt/images/${VM}_vd${i}.img 4G
      sudo virsh attach-disk ${VM}  /var/lib/libvirt/images/${VM}_vd${i}.img vd${i} --type disk --subdriver qcow2 --persistent
    done

    sudo virsh start ${VM}
    #EOF
  • Setting up LVM inside the VM

    $ sudo vgcreate vg_lvm_test /dev/vd{a..f}
      No physical volume label read from /dev/vda
      Physical volume "/dev/vda" successfully created
      [...]
      Volume group "vg_lvm_test" successfully created
    
    $ sudo lvcreate -n "lv_lvm_test" -L 5G vg_lvm_test
      Logical volume "lv_lvm_test" created
    

The Basics

  • pvs: show physical volumes:

    $ sudo pvs
      PV         VG          Fmt  Attr PSize PFree
      /dev/vda   vg_lvm_test lvm2 a-   4.00g 4.00g
      /dev/vdb   vg_lvm_test lvm2 a-   4.00g 4.00g
      /dev/vdc   vg_lvm_test lvm2 a-   4.00g 4.00g
      /dev/vdd   vg_lvm_test lvm2 a-   4.00g 4.00g
      /dev/vde   vg_lvm_test lvm2 a-   4.00g 4.00g
      /dev/vdf   vg_lvm_test lvm2 a-   4.00g 4.00g
    
  • vgs: volume groups

    $ sudo vgs
      VG          #PV #LV #SN Attr   VSize  VFree 
      vg_lvm_test   6   1   0 wz--n- 23.98g 18.98g
    

PV: Number of physical volumes in this group

SN: Snapshots

Attributes: See man vgs for the attributes columns

Notice "VSize" and "VFree". It's always a nice feeling to have a bit of free space in your volume groups.

  • lvs: show logical volumes

    $ sudo lvs
      LV          VG          Attr   LSize Origin Snap%  Move Log Copy%  Convert
      lv_lvm_test vg_lvm_test -wi-a- 5.00g
    

Filesystem resizing

Resizing filesystems on LVM is almost trivial.

Resize the LV into your VG's free space (add free space with vgextend if there is none in the VG).

    $ sudo vgs
      VG              #PV #LV #SN Attr   VSize  VFree
      vg_lvm_test       4   1   0 wz--n- 15.98g 5.98g

    $ sudo mkfs.ext4 /dev/vg_lvm_test/lv_lvm_test
    ...
    $ sudo mount /dev/vg_lvm_test/lv_lvm_test /mnt/

    Filesystem                           Size  Used Avail Use% Mounted on
    /dev/sda1                            7.0G  1.1G  5.6G  17% /
    udev                                 490M  4.0K  490M   1% /dev
    tmpfs                                200M  304K  199M   1% /run
    none                                 5.0M     0  5.0M   0% /run/lock
    none                                 498M     0  498M   0% /run/shm
    /dev/mapper/vg_lvm_test-lv_lvm_test  5.0G  204M  4.6G   5% /mnt

OK, we've got a 5.0G filesystem mounted at /mnt. Let's give him a couple more megabytes.

    $ sudo lvextend vg_lvm_test/lv_lvm_test -L +2G
      Extending 2 mirror images.
      Extending logical volume lv_lvm_test to 7.00 GiB
      Logical volume lv_lvm_test successfully resized

    $ sudo resize2fs /dev/vg_lvm_test/lv_lvm_test

    $ sudo resize2fs /dev/vg_lvm_test/lv_lvm_test
    resize2fs 1.42 (29-Nov-2011)
    Filesystem at /dev/vg_lvm_test/lv_lvm_test is mounted on /mnt; on-line
    resizing required
    old_desc_blocks = 1, new_desc_blocks = 1
    Performing an on-line resize of /dev/vg_lvm_test/lv_lvm_test to 1835008 (4k)
    blocks.

    $ df -h
    Filesystem                           Size  Used Avail Use% Mounted on
    /dev/sda1                            7.0G  1.1G  5.6G  17% /
    udev                                 490M  4.0K  490M   1% /dev
    tmpfs                                200M  304K  199M   1% /run
    none                                 5.0M     0  5.0M   0% /run/lock
    none                                 498M     0  498M   0% /run/shm
    /dev/mapper/vg_lvm_test-lv_lvm_test  7.0G  205M  6.5G   4% /mnt

You can do this with mounted filesystems, even the root filesystem.

Mirroring

We're going to mirror the logical volume that we just created, lv_lvm_test, using the lvconvert command:

    $ sudo lvconvert -m1 vg_lvm_test/lv_lvm_test
      vg_lvm_test/lv_lvm_test: Converted: 0.0%
      vg_lvm_test/lv_lvm_test: Converted: 4.9%

You can ^C this process and it will continue in the background. Check its progress with the "lvs" command.

    $ sudo lvs
      LV          VG          Attr   LSize Origin Snap%  Move Log Copy%  Convert
      lv_lvm_test vg_lvm_test mwi-a- 5.00g lv_lvm_test_mlog       16.02

The mirrored volume has 3 components: 2 mirror copies and the disklog. The disklog tracks changes and keeps the volumes in sync.

You can see the different components, and their physical locations, using the pvs command.

    $ sudo pvs -o lv_name,pv_name
      LV                     PV        
      [lv_lvm_test_mimage_0] /dev/vda  
      [lv_lvm_test_mimage_0] /dev/vdb  
      [lv_lvm_test_mlog]     /dev/vdb  
                             /dev/vdb  
      [lv_lvm_test_mimage_1] /dev/vdc  
      [lv_lvm_test_mimage_1] /dev/vdd  
                             /dev/vdd  
                             /dev/vde  
                             /dev/vdf

Note that the mirrored segments are named $LVNAME_mimage_0 and $LVNAME_mimage_1. The logical volume is 5GB, which is bigger than the physical volumes, which are all 4GB. The 5GB segments are split across a couple of physical volumes each. LVM will try to "do the right thing" and prevent mimage segments from occupying the same physical devices.

There's a third part, the disklog, named $LVNAME_mlog. In this example, part of mimage_0 and mlog are on the same physical volume, vdb.

Corelog

When you create a mirror, you can also use "corelog" instead of disklog. This keeps the mirror log in RAM instead of on a disk. This way, you don't need to have a disklog segment.

The downside is that the mirror will have to be synchronized at every boot.

    $ sudo pvs -o +lv_name
    [sudo] password for eric: 
      PV         VG          Fmt  Attr PSize PFree LV                    
      /dev/vda   vg_lvm_test lvm2 a-   4.00g    0  [lv_lvm_test_mimage_0]
      /dev/vdb   vg_lvm_test lvm2 a-   4.00g 2.99g [lv_lvm_test_mimage_0]
      /dev/vdb   vg_lvm_test lvm2 a-   4.00g 2.99g [lv_lvm_test_mlog]    
      /dev/vdb   vg_lvm_test lvm2 a-   4.00g 2.99g                       
      /dev/vdc   vg_lvm_test lvm2 a-   4.00g    0  [lv_lvm_test_mimage_1]
      /dev/vdd   vg_lvm_test lvm2 a-   4.00g 2.99g [lv_lvm_test_mimage_1]
      /dev/vdd   vg_lvm_test lvm2 a-   4.00g 2.99g                       
      /dev/vde   vg_lvm_test lvm2 a-   4.00g 4.00g                       
      /dev/vdf   vg_lvm_test lvm2 a-   4.00g 4.00g

Since /dev/vde and /dev/vdf don't have any LV segments on them, we'll take them out of vg_lvm_test with the vgreduce command, and put them into a new volume group, vg_corelog_test.

    $ sudo vgreduce vg_lvm_test /dev/vde /dev/vdf
      Removed "/dev/vde" from volume group "vg_lvm_test"
      Removed "/dev/vdf" from volume group "vg_lvm_test"

    $ sudo vgcreate vg_corelog_test /dev/vde
      Volume group "vg_corelog_test" successfully created

Create the LV:

    $ sudo lvcreate -n lv_corelog -l 100%FREE vg_corelog_test
      Logical volume "lv_corelog" created

    $ sudo vgs
      VG              #PV #LV #SN Attr   VSize  VFree
      vg_corelog_test   1   1   0 wz--n-  4.00g    0
      vg_lvm_test       4   1   0 wz--n- 15.98g 5.98g

Now we double the amount of space in the VG by adding another PV, /dev/vdf:

    $ sudo vgextend vg_corelog_test /dev/vdf
      Volume group "vg_corelog_test" successfully extended

    $ sudo vgs
      VG              #PV #LV #SN Attr   VSize  VFree
      vg_corelog_test   2   1   0 wz--n-  7.99g 4.00g
      vg_lvm_test       4   1   0 wz--n- 15.98g 5.98g

We convert the volume to be mirrored:

    $ sudo lvconvert -m1 vg_corelog_test/lv_corelog
      Insufficient suitable allocatable extents for logical volume : 1023 more required
      Unable to allocate extents for mirror(s).

We don't have enough room for the mirror in our volume group, since it requires a disklog by default.

    $ sudo lvconvert -m1 vg_corelog_test/lv_corelog --corelog
      vg_corelog_test/lv_corelog: Converted: 0.0%
      vg_corelog_test/lv_corelog: Converted: 7.2%
      vg_corelog_test/lv_corelog: Converted: 14.3%
      vg_corelog_test/lv_corelog: Converted: 21.4%

Moving PVs around with pvmove

Let's make room by getting rid of our corelog thing.

    $ sudo vgremove vg_corelog_test
    Do you really want to remove volume group "vg_corelog_test" containing 1
    logical volumes? [y/n]: y
    Do you really want to remove active logical volume lv_corelog? [y/n]: y
      Logical volume "lv_corelog" successfully removed
      Volume group "vg_corelog_test" successfully removed

Now we'll add the old PVs back into the volume group, vg_lvm_test.

    $ sudo vgextend vg_lvm_test /dev/vde /dev/vdf
    $ sudo pvs
      PV         VG          Fmt  Attr PSize PFree   
      /dev/vda   vg_lvm_test lvm2 a-   4.00g       0 
      /dev/vdb   vg_lvm_test lvm2 a-   4.00g 1012.00m
      /dev/vdc   vg_lvm_test lvm2 a-   4.00g       0 
      /dev/vdd   vg_lvm_test lvm2 a-   4.00g 1016.00m
      /dev/vde   vg_lvm_test lvm2 a-   4.00g    4.00g
      /dev/vdf   vg_lvm_test lvm2 a-   4.00g    4.00g

Let's say that we've got the sick feeling that /dev/vdb is about to die on us. Let's move it over to the much newer /dev/vde.

    $ sudo pvmove /dev/vdb /dev/vde
      Skipping mirror LV lv_lvm_test
      Skipping mirror log LV lv_lvm_test_mlog
      Skipping mirror image LV lv_lvm_test_mimage_0
      Skipping mirror image LV lv_lvm_test_mimage_1
      All data on source PV skipped. It contains locked, hidden or non-top level
      LVs only.
      No data to move for vg_lvm_test

D'oh! It's our mirror. We'll have to break it first.

    $ sudo lvconvert -m0 vg_lvm_test/lv_lvm_test

    $ sudo pvmove /dev/vdb /dev/vde
      /dev/vdb: Moved: 0.0%

You can ^C this. You can check back on the move at any time by just running pvmove:

    $ sudo pvmove
      /dev/vdb: Moved: 9.5%
      /dev/vdb: Moved: 18.7%

pvmove works by temporarily mirroring the source and target PVs. Check the output of dmsetup ls --tree:

    $ sudo dmsetup ls --tree
    vg_lvm_test-lv_lvm_test (252:0)
     ├─vg_lvm_test-pvmove0 (252:1)
     │  ├─ (253:64)
     │  └─ (253:16)
     └─ (253:0)

Even if the machine crashes in the middle of a pvmove, it won't affect it. It will just pick up where it left off when the machine gets rebooted.

pvmove works on online devices and mounted filesystems, including the root filesystem. Cool!

Running Big Blue Button with Drupal on Ubuntu 10.04

Our goal here is the following:

  • have BBB running on Ubuntu

  • Use Launchpad SSO to control access

  • Organize multiple web meetings easily

We're going to be using Drupal, Apache, and Big Blue Button.

Installing the server

Big Blue Button instructions are pretty straightforward. If you're going to be using the Drupal integration bit (see below) stick with 0.7.

If you're running in an LXC instance

First, setup an lxc instance on your local machine:

sudo lxc-create -t ubuntu -n bbb -f /etc/lxc/lxc-veth.conf -- -r lucid

Chroot into /var/lib/lxc/ and setup your environment, adding a sudo user, etc. Then, startup the instance.

After the machine is up and running, add the -updates repo to /etc/apt/sources.list.

sudo lxc-start -n bbb

Login to the instance and update it. Due to a bug in lxc's stuff, you'll need to umount /usr/lib/init/fstab before it will run.

You probably also want to edit /var/lib/lxc/bbb/config and set a static hardware address. Otherwise, your IP address will change between boots and break the BBB server's configuration.

If you're running in an Amazon cloud

After the installation finishes, you'll need to set the BBB configuration to use external IP of the instance.

bbb-conf --setip ec2-107-21-198-130.compute-1.amazonaws.com

Then add the hostname to /etc/hosts with the private IP address.

For all machines

Now, just follow the steps in:

http://code.google.com/p/bigbluebutton/wiki/InstallationUbuntu

Once you're done, you should be able to login to your bbb server and test it.

Using with Drupal

For some reason, the BBB developers decided that apache wasn't good enough for them, and went with nginx. Drupal will probably work with nginx, but it's not trivial to setup. And that's what we want: Trivial.

Change BBB's listening port to 81:

sudo bbb-conf --setip bigbluebutton.mydomain.org:81
sudo bbb-conf --clean

Check now to make sure that /etc/nginx/sites-available/bigbluebutton has been updated with the new port number.

Change nginx's ports to 81 in /etc/nginx/sites-available/default

Restart nginx, and test http://bbb.local:81/ . It should give you the full big blue button experience.

Now let's install Drupal6:

sudo apt-get install drupal6

In your browser, go to http://bbb.local/drupal6/install.php and make it so.

Grab the BBB Drupal module:

cd /usr/share/drupal6/modules/
sudo wget http://ftp.drupal.org/files/projects/bbb-6.x-1.x-dev.tar.gz
sudo tar zxvf bbb-6.x-1.x-dev.tar.gz
sudo rm bbb-6.x-1.x-dev.tar.gz

Go to Administration -> Site Building -> Modules, and enable the BBB module

Once enabled, go to Site Configuration -> Big Blue Button meetings and configure the API connection.

Base URL: http://bbb.local:81/bigbluebutton/api/

Don't forget the :81 (like I always do).

Security salt:  value beans.dynamicConferenceService.securitySalt from

/var/lib/tomcat6/webapps/bigbluebutton/WEB-INF/classes/bigbluebutton.properties

Using with Launchpad OpenID and Drupal (Optional)

First off, grab the Launchpad OpenID extensions from here:

https://code.launchpad.net/~canonical-isd-hackers/drupal-launchpad/6.x-trunk
bzr branch lp:drupal-launchpad/6.x
mv 6.x openid-launchpad  # this needs to come after "openid", due to
               # hackage
tar fcz openid-launchpad.tar.gz openid-launchpad

Then unpack that so that you have /usr/share/drupal6/modules/openid-launchpad.

Go into Site Building -> Modules, and enable "Launchpad OpenID".

Now, go into Site Building -> Blocks, and remove the usual login screen, and add the OpenID launchpad login button somewhere where the users can find it.

Set authorized users' permissions so that they can attend meetings, create content.

If everything is working at this point, you might want to upgrade your BBB instance to 0.8. There are some improvements to the meeting layout, which is especially good when you have a lot of people's video windows to move around.

The instructions for upgrade are here:

http://code.google.com/p/bigbluebutton/wiki/08InstallationUbuntu#Upgrading_from_BigBlueButton_0.71a

Since we also have Drupal and Apache running, I would advise stopping apache before starting, and telling BBB to overwrite the existing nginx configuration files.

After the upgrade, just run the bbb-conf command again to reset the port to 81:

sudo bbb-conf --setip bigbluebutton.mydomain.org:81

Then restart apache2. It's fairly easy and has worked for me pretty well.

Here are some scripts that may lighten the load a little bit:

  1. Install BBB
  2. Upgrade from 0.7a to 0.8beta
  3. Upgrade Ruby

Windows 7

I finally got around to installing Windows 7 on bare metal this weekend. I've been roped into installing Windows Server occasionally, but always in a VM, and only for testing Linux interoperability with packages like Centrify and Likewise.

It's the first time I've installed Windows on a machine in 6 years. The last time, it was to play Doom 3 and Half-Life 2. The old PowerBook G4 was not up to those mighty titles, so I pressed my (then-)meaty P4 machine into service.

I've always heard good things about Windows 7, even from Mac fanboys. It has a reputation for being light, fast, and pretty.

The Good

Installation wasn't too awkward. I remember Windows XP being annoying and fidgety, especially when installing alongside existing operating systems. Windows 7's installation asks few questions and then goes about its business. It also managed to not completely blow away my Ubuntu installation, being satisfied with destroying my MBR and rendering my other OS's inaccessible.

The Super+tab switching, which shows the windows stacked up and cycles through them, is pretty slick. I found myself using that more than anything to get around. It's on par with Expose as a productivity enhancer, and Ubuntu's Unity could learn a thing or two from that.

The OS itself is still fairly snappy, even with all the new added bling. Not to say that it's faster than Ubuntu or Mac OS X, but it competes.

The Bad

Having used Mac and Linux exclusively for years, the first thing that hit me is: Windows font-handling is still shit. Apple products are known for their excellent typography, so it's no surprise that it whips Windows on that front. But even Ubuntu beats the shit out of Windows when it comes to font rendering. The choice of fonts and the anti-aliasing tech is so bad, I get a headache trying to read it. I tried monkeying around with the ClearType settings, but was still getting ghosting and blurriness.

I installed Windows 7 on Dell OptiPlex 380 small form-factor machine, which is fairly run-of-the-mill hardware. Windows 7's support for Sandy Bridge is admirable, but the Network driver wasn't there. I had to boot into Ubuntu and download the driver pack from Dell.

I also had trouble burning DVDs. I was able to burn two easily and successfully, but after that, I just got coasters. No big deal, seeing as I have spindles and spindles of blank DVDs that I never thought I'd use anyway, but this is still an area where I figured Windows would shine.

The Ugly

The following are things that I consider to be matters of personal taste. I've always found NT to be a good operating system, with a technologically advanced kernel and a lot of brains architecting it. But I'll be upfront about my dislike of Windows as a user environment.

Windows Aero looks outdated to me. I don't like the gigantic chrome surrounding all the windows, nor the transparency effects. The clicky-bloopy sound effects get old fast. There's a sound hit for virtually every action. Clicking, showing menus, closing windows, logging in, notification bubbles. And when you're listening to music on a nice pair of speakers, you really don't need a 25-watt orchestra hit that tells you that your antivirus just updated itself.

The main thing I don't like about the Windows interface is that almost everything seems to be excessive. For example, the progress bars have a little lens-flare effect that sweeps across every few seconds. I have no idea what it means. Also, the window chrome blurs whatever's behind it, simulating translucency. But the blur is sever enough that you can't really tell what's behind it, only that something is behind it. They should have just dropped that.

Conclusion

Screw you, Windows. I'll continue to order my PC hardware explicitly without you, and stick to modern operating systems.

Looking under Filesystem Mounts on Linux

Occasionally, you'll need to find stuff on a Linux filesystem that seems to have disappeared. For example, if you're seeing big differences between the output of df and du, and you can't figure out where your disk space went.

You'll eventually need to look under any mounted filesystems, such as /var or /home in many cases, to make sure that no files have been hidden underneat their mount points. Normally, you'll be told to unmount those filesystems.

There's an easier way to do this, though, using bind mounts.

sudo mkdir /root_bind
sudo mount -o bind / /root_bind

cd /root_bind
sudo du -h --max-depth=1 /root_bind

Compare this with the output of "du -h --max-depth=1 /" and see if there's anything that jumps out at you. Oh, and don't forget to unmount /root_bind.

Fixing that Broken Xterm under Compiz and Unity

First off, why Xterm? It's lightweight, it's easy, and it doesn't suffer from trackpad scroll-madness like GNOME Terminal. Whenever I'm using tmux under GNOME Terminal on my laptop, inadvertent scroll-wheel events often cause me to send the wrong commands or write nonsense into IRC.

Unfortunately, Compiz and Xterm do not play well together. Due to how Compiz calculates its textures, Xterm displays tend to get garbled.

Having had my fill of gnome-terminal, I finally got around to figuring out the workaround for this. Just put the following in .Xdefaults:

! Workaround for compiz issues
XTerm*borderWidth: 0

Then xrdb ~/.Xdefaults && xterm, and you're back in old-school business.

Launchd in Ubuntu

In the various flavors of UNIX, you usually have an init or init-like process which wrangles all the sundry system services. Things like your mail server, your ftp server, etc. all have to be started by something.

In Ubuntu, we use Upstart since Lucid. It's a modern, event-based init daemon. Red Hat Enterprise Linux 5 uses the fine old SysVInit system. In RHEL 6, you also have Upstart, but it's being run in a SysVInit-compatibility mode. RHEL's cousin, Fedora, uses systemd.

Under Mac OS X Tiger and later, there's launchd. This not only ditches replaces init, but also cron and a couple of other traditional UNIX facilities.

According to The Book of Knowledge

The Ubuntu Linux distribution considered using launchd in 2006. However, launchd was rejected as an option because it was released under the Apple Public Source License – which at the time was described as an "inescapable licence problem".

In August 2006, Apple relicensed launchd under the Apache License, Version 2.0 in an effort to make adoption by other open source developers easier.

I'm not so convinced that licensing was the main reason that launchd was passed over. I wasn't around Ubuntu or Canonical at the time, and I've heard conflicting accounts from various Canonical employees on the matter.

With as much time and effort as we've put into Upstart in the meanwhile, it's turned out to be pretty good solution.

People complain about the upstart configuration file syntax. If you compare it aginast the property list approach, though, it's like writing hot buttered biscuits and bacon.

For comparison, here's a property list for postfix (stolen from Macworld):

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
        <key>Label</key>
        <string>org.postfix.master</string>
        <key>Program</key>
        <string>/usr/libexec/postfix/master</string>
        <key>ProgramArguments</key>
        <array>
                <string>master</string>
        </array>
</dict>
</plist>

Postfix isn't upstartified in Ubuntu (yet), but here's a comparable rsyslog upstart config:

# rsyslog - system logging daemon
#
# rsyslog is an enhanced multi-threaded replacement for the traditional
# syslog daemon, logging messages from applications

description     "system logging daemon"

start on filesystem
stop on runlevel [06]

expect fork
respawn

script
    . /etc/default/rsyslog
    exec rsyslogd $RSYSLOGD_OPTIONS
end script

Launchd might be stable, and it's what all the cool BSD kids are running these days, but it breaks one of the commandments: XML is not to be considered human-writable. It's a data format.

Doing variable expansion in Bash, like a boss

I should have called this, how to kick sed off my living room couch, and tell that lazy scumbag to go out and get a job and stop drinking all my beer. But that was too long.

TL;DR

You can do just about anything inside two {}'s; the laws of nature no longer apply in there..

Substrings

$ export MYVAR=/usr/bin/eric.rocks

$ unset NULLVAR

$ echo ${MYVAR:1}
usr/bin/eric.rocks

$ echo ${MYVAR:9}
eric.rocks

$ echo ${MYVAR:9:4}
eric

# variable name wildcards

$ echo ${!MY*}
MYVAR

$ echo ${!DI*}
DIRSTACK DISPLAY

# '##' removes a prefix (accepts wildcards)

$ echo ${MYVAR##/usr}
/bin/eric.rocks

$ pwd
/usr/bin

$ echo ${MYVAR##$( pwd )}
/eric.rocks

# '%' remove the suffix (non-greedy)

$ echo ${MYVAR%.rocks}
/usr/bin/eric

# '%%' removes it greedily

$ echo ${MYVAR%r*}
/usr/bin/eric.

$ echo ${MYVAR%%r*}
/us

$ echo ${MYVAR%%ic}
/usr/bin/eric.rocks

$ echo ${MYVAR%%ic*}
/usr/bin/er

Substitution

${parameter/pattern/string}

# pattern accepts filename-type wildcards

$ echo ${MYVAR/e/f}
/usr/bin/fric.rocks

$ echo ${MYVAR/e*c/f}
/usr/bin/fks

# '#' means match from beginning

$ echo ${MYVAR/#\/*c/f}
fks

# '//' means replace all instances

$ $ echo ${MYVAR/S/e}                                  
ACCEeS DENIED

$ echo ${MYVAR//S/e}                                 
ACCEee DENIED

Transformations

# '^^' uppercases it

$ echo ${MYVAR^^}
/USR/BIN/ERIC.ROCKS

$ echo ${MYVAR^*}
/usr/bin/eric.rocks

$ echo ${TERM^*}
Screen

# ',' and ',,' lowercases it

$ export MYVAR="ACCESS DENIED"

$ echo ${MYVAR,}

aCCESS DENIED

$ echo ${MYVAR,,} 
access denied

Returning Default Values

$ export MYVAR=/usr/bin/eric.rocks

$ unset NULLVAR

# return default "test" if unset

$ echo ${MYVAR:-test}
/usr/bin/eric.rocks

# return default value if unset

$ echo ${NULLVAR:-test}
test

# return, and assign, default value if unset

$ echo ${NULLVAR:=test}
test

$ set |grep NULLVAR
NULLVAR=test

$ unset NULLVAR

# return error message if unset

$ echo ${NULLVAR?aaaaaah}
-bash: NULLVAR: aaaaaah

# return value if set

$ echo ${MYVAR:+$TERM}
screen

# return nothing if unset

$ echo ${NULLVAR:+$TERM}

Getting a Better Expose under Unity

When you enable the Expose-like feature under Unity (Default Super+W), you'll see all of your windows tiled about the screen, allowing you to pick them easily.

The more windows you have open, however, the smaller the preview windows become. The fact that almost all applications have a fairly consistent look and feel might be good for the general desktop experience, but it's not very good for picking out which windows belong to which application.

Without icon overlays

One way to get around this is to overlay the application icon on the window itself. Unfortunately, the Unity itself doesn't have a configuration UI for this, so you'll need to do it at the Compiz level. To do this, install the package compizconfig-settings-manager:

apt-get install compizconfig-settings-manager

Now run the command, either using the launcher or typing "ccsm" into the terminal. Go the conrol panel called "Scale" under "Window Management", and set the "Overlay Icon" option. I personally prefer "Emblem", as it makes it easier to pick out the icon.

With icon overlays

Voila, usable Expose.