How to find number of CPUs on unix system

Newer processors are multi-core and could have hyper-threading enabled. So there are time when user may need to know how many cores (virtual) processors are available and how many Physical (real) processors are installed. CPU information can be retrieved via /usr/sbin/psrinfo on SunOS while it is available in /proc/cpuinfo on Linux. /proc/cpuinfo on Linux contains information about each available core. Following command combinations can be used to retrieve the number of CPUs.

OS Physical Processors Cores available
SunOS /usr/sbin/psrinfo -p /usr/sbin/psrinfo | wc -l
Linux grep “^physical id” /proc/cpuinfo | awk ‘{print $NF}’ | sort -u | wc -l grep processor /proc/cpuinfo | wc -l
IRIX hinv | grep -i processor | head -n1 | cut -d’ ‘ -f1

Update: Thanks Matias for tip on IRIX.

bash : Signal Handling

A script could have lock file or is producing temporary files which need to be renamed before exiting. What if the script receives a signal and quits in the middle leaving temporary files scattered around? Bash provides “trap” function to trap a signal and right a signal handler.

if [ ! -e $lockfile ]; then
        # Arm the handler
        trap "rm -f $lockfile; exit" INT TERM EXIT
        touch $lockfile
        critical-section
        rm $lockfile
        # Disarm the handler
        trap - INT TERM EXIT
fi

Or you can write a function like below.

Handle_Exit_Safely()
{
        rm -f $lockfile
        exit
}
if [ ! -e $lockfile ]; then
        # Arm the handler
        trap Handle_Exit_Safely INT TERM EXIT
        touch $lockfile
        critical-section
        rm $lockfile
        # Disarm the handler
        trap - INT TERM EXIT
fi

perl : Extract filename from full path

To extract the name of the file the quick way is to use substr and rindex commands to strip the path from filename as shown below.

#!/usr/bin/perl

my $path='/path/to/search/filename';
my $fname= substr($path, rindex($path,"/")+1, length($path)-rindex($path,"/")-1);
print "$fnamen";

If you have the luxury of using Perl Packages, then use following solution which is very clean.

#!/usr/bin/perl

use File::Basename;
my $path='/path/to/search/filename';
my $fname = basename($path);
print "$fnamen";

perl : Read filenames from a Directory

Perl provides built in glob function which can be used to read the list of files in a directory.

@files = </path/to/search/pattern_to_search>;

Here is working code example that prints all filenames from current directory, one per line. The glob happens when the <> characters pulls the filenames into the @files array.

#!/usr/bin/perl
@files = <*>;
foreach $file (@files) {
        print "$filen";
}

So if you were to find all php files in your webserver directory use

@files = </var/www/htdocs/*.php>

find broken symlinks

If you have a big project with multiple shared libraries, there is a chance to run into soft links that are no longer pointing anywhere. Here are couple of ways to find those dangling soft links that no longer point to any real file using the Unix find command.

These are in preferred order.

find /path/to/search -type l | (while read FN ; do /usr/bin/test -e "$FN" || echo "$FN"; done)
find /path/to/search -type l ! -exec /usr/bin/test -r {} ; -print
find -L /path/to/search -type l

So here is how these can be used to clean out those dangling soft links (again in preferred order). We use rm to ensure that any aliases don’t kick in. First one is the best way which is portable to most Unix platforms.

find /path/to/search -type l | (while read FN ; do /usr/bin/test -e "$FN" || rm -f "$FN"; done)
find -L /path/to/search -type l -exec rm -f {} ;
find -L /path/to/search -type l -delete

Note: When using in script, make sure to escape the properly.

Interoperability Issues between SunOS and Linux

-delete is not supported on SunOS find. It is available on GNU findutils. So using -exec to invoke rm command would be portable. As well as the test for existence /usr/bin/test -e is portable. Make sure to use /usr/bin/test instead of shell built in test because on sh the flag -e is not available.

Update (2011-08-12) : /usr/bin/test should be used for interoperability.

bash : Automate add/modify/delete of cron jobs from a script

If you have auto installing packages there could be times when a cron job needs to be added. So the script has to be able to create new cron entries or delete old ones. One solution is to create temporary files in between to hold the other unaffected cron entries that are currently installed, add the new entry and then install this file using crontab. Creating of temporary files should be avoided in between as there are risks. So here is an elegant solution which uses piping in the output of multiple commands.

To remove already existing cron job (rdate for user unixite in example below) use a syntax like

crontab -l -u unixite | grep -v rdate | crontab -u unixite -

This pipe chain lists the existing crontab entries, removes any containing the string rdate, then reloads the resulting data by piping it back to crontab of user unixite. “-” is for reading from the stream or terminal (see Note below). No useless temporary file, no security risk.

To add new crontab entries Continue reading “bash : Automate add/modify/delete of cron jobs from a script”

BlackBerry : Play PAC-MAN

Here is a tip on 30th birthday of PAC-MAN. Go to Google today to play right on the website.

UPDATE: April 6, 2011

Download for BlackBerry from Benny Chow is no longer available. All the best things come to an end and Namco who owns the Pac-Man no longer wants it to be free. Come on Namco!!! Grow up. You already got all the money you want. Do you want us to pay every time we even say Pac-Man?

It was available for download on your BlackBerry. Thanks to Benny Chow. It was at http://bennychow.com/blackberry.shtml which no longer exists. The latest info from Benny is at http://bennychow.com/?tag=pacman.

Here is a screenshot from my Blackberry Curve 8310.
PAC-MAN on BlackBerry

bash : run command on find results

Unix find command allows user to execute a command on the results by using -exec command. For example see below. {} get replaced by filename, Make sure to escape {} and ;.

find . -type f -exec ls -l {} ;

This triggers ls -l on all the files that were found. I used this with -maxdepth (how deep directory structure to examine) and -mtime (last modified time) to cleanup old files as below.

find /var/log -type f -mtime +30 -maxdepth 0 -exec rm -f {} ;

Continue reading “bash : run command on find results”