Operating System - HP-UX
1831136 Members
2459 Online
110020 Solutions
New Discussion

PERL scripting help needed

 
SOLVED
Go to solution
Chern Jian Leaw
Regular Advisor

PERL scripting help needed

Hi,
I have a PERL script attached in this message which reads the contents of several input files having the format:

addtogroup:ken_lee:grpA:rick_hyun:ken_lee
These input files containing the above formatted data all begin with the name "spool" i.e:
spool.groupnameADD.userToAdd.group.PID
e.g:
spool.grpAADD.rick_hyun.grpA.12434

The script attached basically takes the output above, which is generated from another PERL script. It then tokenizes ken_lee, grpA and rick_hyun and passes them into
another script called edgrp.

The script edgrp takes the tokenized elements and adds them into the group grpA, where ken_lee is the group owner and rick_hyun is the person to be added in. The edgrp script then pushes these changes to the NIS group file to all of its maps.
edgrp script is invoked the following way:
# edgrp < passwd_file
# edgrp < passwd_file
passwd_file is the file containing the user-name of the group leader and its passwd of the format:
ken_lee
z768v!plQ

However, there is an issue of concurrency with the script - If there is >1 person invoking this script, then the data to be added is not consistent, i.e. same person gets added into same group twice.

The edgrp script by itself adds and deletes users from the NIS groups properly, when invoked with one the purpose of adding
or removing 1 user at a time.

I was wondering if anyone could provide some guide on how I could implement some kind of "thread" or synchronization mechanism
in PERL which would provide some concurrency control over the script whenever the sub-routine add() or remove() is called?
Or perhaps some other modification to the script that would ensure concurrency?

The subroutines add() and remove() calls the script edgrp with the proper parameters to perform the "real" work of adding or
deleting users from a NIS group.

Could anyone kindly help me out?

Thanks
5 REPLIES 5
Vincent Stedema
Esteemed Contributor

Re: PERL scripting help needed

Hi,

You could of course use a temporary lock file (e.g. /tmp/edgrp.lck). Let edgrp check for the lock file and only add() or remove() a user if the file doesn't exist;

There are some articles over at the Perl Journal (www.tpj.com) that discuss resource locking. This article uses semaphores: http://www.samag.com/documents/s=4075/sam1013019385270/sam0203i.htm

This one is especially about resource locking over networks: http://www.samag.com/documents/s=7178/sam0206j/

Hope this helps.

Regards,

Vincent
Chern Jian Leaw
Regular Advisor

Re: PERL scripting help needed

Vincent,

I was wondering if you could show me how I could implement the temporary lock file for this purpose?

I'm rather a newbie in the area of concurrency access with PERL - would greatly appreciate it if you could provide some guidlines as to how I can implement the locking mechanism.

Thanks
Robin Wakefield
Honored Contributor

Re: PERL scripting help needed

Create a subroutine, pidlock - this will check the LOCKFILE exists, and if it does, that the pid it contains is still running. If it is, it returns 0. If it isn't, the LOCKFILE is created and it returns 1:

sub pidlock{
my($LOCKFILE) = @_;
if(-s "$LOCKFILE"){
die "Cannot open lock file $LOCKFILE, $!\n" unless open LOCK, "$LOCKFILE";
my $pid=;
chomp $pid;
if ( $pid =~ m#([\d]+)$# ) {
my $n=kill 0, $1;
return 0 if($n >0);
}
close LOCK;
die "Cannot remove $LOCKFILE, $!\n" unless unlink("$LOCKFILE");
}
die "Cannot open lock file $LOCKFILE, $!\n" unless open LOCK, ">$LOCKFILE";
print LOCK "$$\n";
close LOCK;
return 1;
}

Then early in your script, call:

$LOCKFILE="/tmp/edgrp.lock";
die "edgrp already running\n" unless pidlock($LOCKFILE);

Rgds, Robin
Chern Jian Leaw
Regular Advisor

Re: PERL scripting help needed

Robin,
what should the LOCKFILE contain? Will it contain the PID of the current process invoking the edgrp script to perform add() or delete()?

Could you tell me where should I call the subroutine pidlock()? when should the lock be released?

Sorry I'm rather a newbie to the area of resource locking and semaphores.

Greatly appreciate it if you explain a little bit more.

Thanks

Vincent Stedema
Esteemed Contributor
Solution

Re: PERL scripting help needed

Hi,

Robin's subroutine checks whether a lock file ('/tmp/edgrp.lock') exists. If it does exist, it checks whether the process that created the lock file is still running. If this is not the case, or when there is no lock file, edgrp can be executed. It writes its own PID to /tmp/edgrp.lock and returns a boolean true value.

If the lock file exists and the process that created it is still running, it will do nothing and return a boolean false value.

You would best incorporate this subroutine at the beginning of your script:

my $lockfile = '/tmp/edgrp.lock';
foreach $i (@spoolList){
print "\$i = $i \n";
my @tokens = &tokenizeElements($i);
$action = $tokens[0];
$owner = $tokens[1];
$grpName = $tokens[2];
$user = $tokens[3];

print "\$action is $action \n";
print "\$owner is $owner \n";
print "\$grpName is $grpName \n";
print "\$user is $user \n";

die "Another instance of edgrp is already running" unless &pidlock($lockfile);
&processReq($action, $owner, $grpName, $user);
system("rm -rf $i");

}

Regards,

Vincent