Posts tagged "linux"
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.
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!
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:
- Install BBB
- Upgrade from 0.7a to 0.8beta
- Upgrade Ruby
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.
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.
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.
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.
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}
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.

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.

Voila, usable Expose.

Why are there monkeys?