Random Perl Snippet

Something that I get to do occasionally at work is review old code to fix some random bug. I actually enjoy doing this because I rarely get to program anymore (since I have never been a developer) and it’s nice to brush up on it again. The other day, I ran into some code I hadn’t seen before, that is valid Perl, but is much more C like:

return ($n < 0) ? 0 : $n;

The biggest problem with trying to figure out what this does if you’ve never seen it before is that you have no idea what to search for. Do you look up “?:”, no, because that actually means something else. Google Code Search has been my friend in the past on things like this, because it can handle all the special characters. I highly recommend trying it out. This time I figured out it was an old C construct, so I just went over and asked a developer what it meant.

So, for those who didn’t know already, this is what it means:

($n < 0) – this is the statement that is being checked (like in an if statement).

The part between the ? and the : is what is returned if the statement is true. The part after the : is what is returned if the statement is false.

So in this case, the author was making sure that the number returned was positive. If $n was less than zero (or negative), it would return zero. If it was zero or some positive number, it just returned that number.

Now, why would you do this? Well, it would all depend on how the variable was derived in the subroutine above it. In my case, the author was using a creative method to find the total number of a specific character in a string (in this case the slash):

my $str = shift(@_);
my $n = split('/', $str) - 1;

Now, although this works, Perl will complain about it because you are clobbering the array @_ and consequently your subroutine arguments. So I ended up changing the code to use the translate command “tr”, which returns the number of matches:

my $n = ($str =~ tr////);

Of course, now the return code is irrelevant, but not causing any harm…

Find open ports in Solaris 9

In many operating systems, you can find the connection between a specific process and an open port using lsof as I mentioned here. What if you don’t have lsof, like in Solaris 9? Well, if you have pfiles, you can do the same thing by looping through the current processes and checking what port they have open:

for i in `ps -A | grep -v PID | awk '{print $1}'`; do echo PID:$i; pfiles $i | grep port; done

To break it down:

This gives you all the PIDs of running processes:

ps -A | grep -v PID | awk '{print $1}'

Loop through them with the for loop, and then print the PID and the open ports of that PID to the screen:

echo PID:$i; pfiles $i | grep port;

Updated design

I got tired of the small width columns of the original template that I used to build this blog, so I finally went in and modified the CSS to make the columns bigger. This should make it so that the code is easier to read and copy. According to Google Analytics, 99.7% of my visitors have a wider screen then 800 pixels, so I felt safe expanding it a bit. Let me know if something doesn’t look right with the new layout.

Solaris 8: Bad Superblock at block 16

This weekend I got the joy of rebuilding a Solaris 8 server from scratch with backups. I had another server of the same hardware available to use for the restore, except it had Solaris 9 mirrored across 2 hard drives. Someday, I’ll go through and document the whole process, but basically I broke the mirror, repartitioned the second drive, mounted the new partitions inside of the Solaris 9 environment, restored the data and rebooted off the drive with the restored data.

The interesting thing that I found that I wanted to post about was the corruption of the Solaris 8 superblock that was caused by mounting the partitions within Solaris 9. There were changes made in fsck on Solaris 9 that made the superblock incompatible with Solaris 8. When you boot off of a Solaris 8 partition that has been mounted by Solaris 9, you’ll get the following errors:

The / file system (/dev/rdsk/c0t2d0s0) is being checked.
/dev/rdsk/c0t2d0s0: BAD SUPERBLOCK AT BLOCK 16: BAD VALUES IN SUPER BLOCK
/dev/rdsk/c0t2d0s0: USE AN ALTERNATE SUPERBLOCK TO SUPPLY NEEDED INFORMATION;
/dev/rdsk/c0t2d0s0: e.g. fsck [-F ufs] -o b=# [special …]
/dev/rdsk/c0t2d0s0: where # is the alternate super block. SEE fsck_ufs(1M).

/dev/rdsk/c0t2d0s0: UNEXPECTED INCONSISTENCY; RUN fsck MANUALLY.

WARNING – Unable to repair the / filesystem. Run fsck
manually (fsck -F ufs /dev/rdsk/c0t2d0s0). Exit the shell when
done to continue the boot process.

Of course, the drive path may be different, etc. The solution to this is simple, run fsck and restore the superblock from one of it’s backups – in this case I restored from block 32:

fsck -F ufs -y -o b=32 /dev/rdsk/c0t2d0s0

Run this on each of the affected partitions (all the partitions that you mounted) and you are good to go.

Postfix fails to shutdown on Linux VM

So I had a problem with a RHEL5 clone (OEL5) Linux VM that would not shutdown postfix correctly on either a powerdown or on a reboot. Here’s the error I saw:

Dec 15 16:43:01 testvm postfix[3160]: fatal: could not find any active network interfaces
Dec 15 16:44:04 testvm postfix/postfix-script: starting the Postfix mail system
Dec 15 16:44:04 testvm postfix/master[1995]: daemon started — version 2.3.3, configuration /etc/postfix

The first trick was realizing that the error was being generated during the shutdown and not during startup. I had checked through my main.cf and verified my /etc/hosts several times thinking that I had some configuration problem within Postfix itself. A virtual machine reboots so fast it’s very easy to miss a reboot within the timestamps.

This VM had the VMware Tools installed and apparently when you install the tools, it sets the priority on shutdown of the tools to be 08. The VMware Tools shutdown the network interfaces and a priority of 08 is way too early to be shutting down the network interfaces. Postfix is set to shutdown at 30 and normal Linux network interfaces are shutdown at 90. So, to fix this issue I simply changed the priority of the VMware Tools shutdown to 89:

mv /etc/rc0.d/K08vmware-tools /etc/rc0.d/K89vmware-tools
mv /etc/rc6.d/K08vmware-tools /etc/rc6.d/K89vmware-tools

I’m sure there is probably some way to do this through chkconfig or something, but sometimes it’s easier to do it the old fashioned way. Here’s my guess on how you would do it through chkconfig:

chkconfig vmware-tools off
vi /etc/init.d/vmware-tools # change chkconfig line from 08 to 89
chkconfig vmware-tools on

Of course, if you reinstall VMware Tools, it will probably replace the symlinks again with the default. Maybe it will even add a second symlink and then you’ll get more errors. I’ll let you know next time I upgrade the tools.

There are several things wrong with the VMware Tools, including it’s automatic installation of hgfs for folder sharing on a server, which I’ll post something about later. I’m still trying to decide if there is any advantage to installing the tools when there is no GUI, especially with it’s poor configuration setups.