Friday 22 June 2012

Don't install VirtualBox on Windows from a network share

Why not, you ask? Well during the installation process, network device drivers are installed (the cause for the several popup warnings about unverified software). These break the network connection temporarily and of course if your installer package is on a network share, your installation stops dead. Duh, stupid me. So install it from a local disk. A USB stick is also ok.


There is actually a longer story in my case. I was upgrading versions. After I realised my mistake I installed from a local drive. But unknown to me damage had already been done. It worked fine for a while. Then one day I decided to do some disk cleaning. Hmm, how come I have both 4.1.14 and 4.1.16 installed? Never mind, I'll blow away 4.1.14. Everything appeared to be still ok afterwards.


Next I needed to enable bridged networking for the Learning Puppet VM. No matter what I did, I could not obtain an interface to bridge. A search turned up this troubleshooting advice in the VirtualBox manual. To paraphrase, one reason for no bridged network adapter is MaxNumFilters is too low. Well, that wasn't it. It was another reason: "The INF cache is corrupt". After I removed %windir%/inf/INFCACHE.1, rebooted and reinstalled VirtualBox, bridged networking became available. It must have been using the driver from the previous release of VirtualBox because I had a partial install of the current version.


So that advice again: Install the VirtualBox package on Windows from a local disk.


Friday 15 June 2012

Expanding an ext3 partition

As has been documented at howtoforgehere and many other places you can find with a search, resize2fs can expand your ext3 filesystem without losing data. (It's actually one case of resizing, you can also shrink.) You have to extend the containing partition first, using parted or the CLI way, by deleting and recreating the partition with a higher cylinder boundary.


I just want to add a few comments. 1. The switching to ext2 and back mentioned in the howtoforge article isn't necessary any more. 2. You can do this on a partition that is not needed for system operation like /home without booting to a rescue disk. This is useful if you have only online access to the server. In fact I did the expansion in parallel with some (tested) RHEL package updates. 3. It works exactly as expected for SAN volumes. It was very nice with a SAN, all the SAN manager had to do when I requested an expansion was to issue a command for the SAN to increase the "disk" size and it finished the task in a few hours.


If you are using logical volume manager, then you have other options too.

Thursday 7 June 2012

Samba, SELinux and the homes share

As has been documented here and many other places, on Redhat, CentOS, Fedora and other distros that come with SELinux enabled, you have to enable the SELinux boolean samba_enable_home_dirs if you export the homes share. I did this but I still could not connect to the share. The usual error message is NT_STATUS_BAD_NETWORK_NAME.


It turns out that you need samba_export_all_ro or more likely, samba_export_all_rw enabled to mount the share. This was on CentOS 5.5. It could be that on this distro and version both come disabled by default.


Make sure though that SELinux is the cause. There are many other reasons for NT_STATUS_BAD_NETWORK_NAME. A quick way to check is to set SELinux to permissive temporarily to attempt the connection.

Saturday 2 June 2012

How to remove the last command line argument in a bash script

In a bash wrapper script I needed to pass a bunch of arguments to the program. No problem, I'll do that with "$@". Then I had a new requirement: if the last argument is of the form *.ppm, I want the stdout of the program to go to this file. But any previous arguments, i.e. options, should be passed to the program. So it boiled down to this:
if nth argument matches *.ppm
  program "1st arg" .. "n-1th arg" > "nth arg"
else
  program "arguments"
To get the last element of an array, you can do ${argv[-1]}. Oops, you cannot do this with ${@[-1]}. So we have to make a copy in a local variable first:
declare -a argv=("$@")
declare file=${argv[-1]}
But we still have to remove the last argument of $@. We can't set it to the empty string, it still exists and will be seen by the program as a empty string. No we can't alter $@, so we have to use unset on argv. But this doesn't work:
unset argv[-1]
Ok, so we have to get the index of the last argument. This is one less than the length of the array, which is ${#argv[@]} (the reason for [@] is the quirky bash syntax for referring to the whole array). So we have to use $(()) to do arithmetic.
declare argc=$((${#argv[@]}-1))
So, putting it all together, the code looks like this:
declare -a argv=("$@")
declare argc=$((${#argv[@]}-1))
declare file=${argv[$argc]}
unset argv[$argc]
Then in the if branch we can write:
program ... ${argv[@]} > "$file" 
Whew!


There is a similar idea in the pop operation here, where we replace the contents of argv with all but the last element, using the subarray notation.