Operating System - HP-UX
1820336 Members
2906 Online
109623 Solutions
New Discussion юеВ

Invoking another PERL script within a PERL script

 
SOLVED
Go to solution
Chern Jian Leaw
Regular Advisor

Invoking another PERL script within a PERL script

HI,

I have a PERL script which needs to be invoked within another PERL script.

However, that PERL script(attached in this message) which needs to be invoked within a PERL script does not get invoked.

The line which invokes the other PERL script is as follows:
system("/pgadm1/adm/ken_lee/grpmgr-FM/test/edgrp.pl");

But this line did not call the PERL script edgrp.pl.

I've also tried invoking the script above by:
`/pgadm1/adm/ken_lee/grpmgr-FM/test/edgrp.pl` in the script, but could not work.
Also, in the script attached, I tried accessing the user's passwd field from the NIS passwd entry by doing:

@passwdEntry = `/usr/bin/ypmatch $grpLead passwd`;
for $j (@passwdEntry){
chomp($j);
@passwdField = split(/:/, $j);
}

$passwd = $passwdField[1];
open (owner, ">/pgadm1/adm/cleaw/grpmgr-FM/test/ownerFile");
print owner "$grpLeader \n";
print owner "$passwdField \n";
close(owner);

However, contents of /pgadm1/adm/cleaw/grpmgr-FM/test/ownerFile did not contain the variable $grpLeader.

Could someone kindly help me out on this matter? Any modifications made to the script is most welcome.

Thanks

9 REPLIES 9
harry d brown jr
Honored Contributor

Re: Invoking another PERL script within a PERL script


Does the script run by itself?

live free or die
harry
Live Free or Die
Chern Jian Leaw
Regular Advisor

Re: Invoking another PERL script within a PERL script

Harry,
The script is also capable of running on its own without calling the other PERL script.
The same goes for the invoked PERL script.

Any inputs on how I could solve this problem?

Thanks
John Poff
Honored Contributor

Re: Invoking another PERL script within a PERL script

Hi,

I would suggest trying to grab the return status from your system call in your script to see if the call is unsuccessful. Something like this:

$sys_status = system("/pgadm1/adm/ken_lee/grpmgr-FM/test/edgrp.pl");

print "After system call - status is $sys_status\n";


That might give you a clue about what is happening with the system call.

JP


John Poff
Honored Contributor
Solution

Re: Invoking another PERL script within a PERL script

Hi again,

After looking at your script, I thought of one other thing. According to your code you are creating the 'edgrp' file, chmod'ing it to be executable, trying to execute it, and then closing it:

print edgrpFile "/usr/local/bin/edgrp add $userName $grpName \n";
system("chmod 755 /pgadm1/adm/cleaw/grpmgr-FM/test/editgrpFile");
system("/pgadm1/adm/cleaw/grpmgr-FM/test/editgrpFile");
close(edgrpFile);

I'd try writing to the 'edgrp' file, closing it, and then chmod'ing it and executing it. There might be a problem with executing it while it is still open as the contents of the file may not have been written out when you do your system call?

JP
John Poff
Honored Contributor

Re: Invoking another PERL script within a PERL script

Hi,

I can confirm what I wrote in my last post. I wrote a small Perl script that opens a file, prints a single line of text that does an echo command, and then tries to chmod the file and execute it. Without closing the file, the system call to execute it returns a -1, but if I close the file first the system call is successful.

open (edgrpFile,">/home/users/jpoff/scripts/perl/runit");
print edgrpFile "echo \"Here we are in runit\"";
close(edgrpFile);

$sys_status1 = system("chmod 755 /home/users/jpoff/scripts/perl/runit");
print "Returned from chmod system call with status of $sys_status1\n";

$sys_status2 = system("/home/users/jpoff/scripts/perl/runit");
print "Returned from system call with status of $sys_status2\n";



Now, if I comment out the close(edgrpFile); line, I get these results:

Returned from chmod system call with status of 0
Returned from system call with status of -1


But with the close() in place:

Returned from chmod system call with status of 0
Here we are in runit
Returned from system call with status of 0



The trick is that Perl does not support unbuffered output. Take a look at 'man perlfaq5' [I'm running Perl 5.8.0]. The beginning of that faq explains how Perl buffers output and a flag to force Perl to flush the buffers after every printf() or write(), but the easy and clean way to do it is to close the file before executing it.

Thanks for making me learn something new today. That was pretty cool!

JP

H.Merijn Brand (procura
Honored Contributor

Re: Invoking another PERL script within a PERL script

Why call another perl script with system ()? This is a shipload of unneeded overhead.

use 'do "script";' instead. The parser will read the script and execute it.

If you also want it to be executed only once, but to allow multiple calls (for which all suubsequent ones are ignored), use 'require "script";' which will `remember' that it has been loaded and run. In this mode, end your script with a `true' value, something like '1;'
Enjoy, Have FUN! H.Merijn
Scott Corzine
Advisor

Re: Invoking another PERL script within a PERL script

Hi,

It looks like the problem in your sample script is that you refer to the variable as $grpLead on the ypmatch line, and $grpLeader on the print statement.

Also, I haven't tested it under HP-UX (works under most others), but perl has a built-in getpwnam() function, which under it's definition should follow the same rules (check NIS, /etc/passwd, etc) your system does in locating passwd entries. That would cut 5 lines down to 1.

-Scott-
John Poff
Honored Contributor

Re: Invoking another PERL script within a PERL script

Merijn is correct, if the script you are calling is a Perl script. The do 'script' function handles it much better.

When I looked at the sample code the author supplied, I couldn't tell if the script being called was a Perl script or not, so I used the system call and made my example call a shell script, which won't work with the 'do' function.

JP


Ralph Grothe
Honored Contributor

Re: Invoking another PERL script within a PERL script

Hi,
couldn't resist to take up the thread.

First listen to what procura posted, and run other Perl code by a do, or require statement.
Better yet, put reusable code bits in a Perl module (aka package within a file of same name ending with suffix .pm), and import it by either "use" or "require" (though require doesn't import anything into your namespace)

Don't call external executables for which there exist Perl built-ins.
Perl has almost all of the Unix syscalls implemented as built-in functions.
The rest that isn't available immediately is covered most of the time by additional CPAN modules (which of course need prior installation).

Find out about Perl's already built-in functions/syscalls by reading the respective POD (aka Plain Old Documentation).
Start for instance with

perldoc perl
perldoc perlintro
perldoc perlsyn
perldoc perlop


To give you an example of a redundant externel executable you used,
the

system "chmod $modbits $file_list_string";

is wasteful (and can be perilious).
Better call Perl's built-in chmod().
Read about it's usage

perldoc -f chmod

Further, to access password data (or any of the other notorious Unix system data files), there are Perl namesakes of the libc functions
e.g. read their POD (someone mentioned them already)

perldoc getpwnam
perldoc perlfunc

Then read what is said in the POD of system() and exec().

perldoc -f system
perldoc -f exec

especially what is said about the possible interaction of these calls with the shell, and the treatment of shell tokens and meta characters (viz. single string argument vs. list of args)

There it also says that in order to get the real return code of an externally called executable you have to right shift the return value of system() by 8 bits.

Beware, exec() never returns to your script.
So its usual usage is within the child's block after a fork.

If you want to read from or write to an external program's output/input (or even both at the same time) use a fork() and exec()

perldoc perlipc

Finally, get used to check the successful execution of open(), <>, close() calls (be it regular files, pipes, sockets or whatever)




Madness, thy name is system administration