NReilingh
NReilingh

Reputation: 1919

How does Perl interact with the scripts it is running?

I have a Perl script that runs a different utility (called Radmind, for those interested) that has the capability to edit the filesystem. The Perl script monitors output from this process, so it would be running throughout this whole situation.

What would happen if the utility being run by the script tried to edit the script file itself, that is, replace it with a newer version? Does Perl load the script and any linked libraries at the start of its execution and then ignore the script file itself unless told specifically to mess with it? Or perhaps, would all hell break loose, and executions might or might not fail depending on how the new file differed from the one being run?

Or maybe something else entirely? Apologies if this belongs on SuperUser—seems like a gray area to me.

Upvotes: 6

Views: 1847

Answers (6)

dawg
dawg

Reputation: 103814

Perl scripts are simple text files that are read into memory, compiled in memory, and the text file script is not read again. (Exceptions are modules that come into lexical scope after compilation and do and eval statements in some cases...)

There is a well known utility that exploits this behavior. Look at CPAN and its many versions which is probably in your /usr/bin directory. There is a CPAN version for each version of Perl on your system. CPAN will sense when a new version of CPAN itself is available, ask if you want to install it, and if you say "y" it will download the newer version and respawn itself right where you left off without loosing any data.

The logic of this is not hard to follow. Read /usr/bin/CPAN and then follow the individualized versions related to what $Config::Config{version} would generate on your system.

Cheers.

Upvotes: 0

Axeman
Axeman

Reputation: 29854

As the others said, the script is read into memory, compiled and run. GBacon shows that you can delete the file and it will run. This code below shows that you can change the file and do it and get the new behavior.

use strict;
use warnings;
use English qw<$PROGRAM_NAME>;

open my $ph, '>', $PROGRAM_NAME;
print $ph q[print "!!!!!!\n";];
close $ph;
do $PROGRAM_NAME;

... DON'T DO THIS!!!

Upvotes: 0

Dave Sherohman
Dave Sherohman

Reputation: 46187

It's not quite as simple as pavel's answer states, because Perl doesn't actually have a clean division of "first you compile the source, then you run the compiled code"[1], but the basic point stands: Each source file is read from disk in its entirety before any code in that file is compiled or executed and any subsequent changes to the source file will have no effect on the running program unless you specifically instruct perl to re-load the file and execute the new version's code[2].

[1] BEGIN blocks will run code during compilation, while commands such as eval and require will compile additional code at run-time

[2] Most likely by using eval or do, since require and use check whether the file has been loaded already and ignore it if it has.

Upvotes: 7

Greg Bacon
Greg Bacon

Reputation: 139451

For a fun demonstration, consider

#! /usr/bin/perl

die "$0: where am I?\n" unless -e $0;

unlink $0 or die "$0: unlink $0: $!\n";

print "$0: deleted!\n";
for (1 .. 5) {
  sleep 1;
  print "$0: still running!\n";
}

Sample run:

$ ./prog.pl
./prog.pl: deleted!
./prog.pl: still running!
./prog.pl: still running!
./prog.pl: still running!
./prog.pl: still running!
./prog.pl: still running!

Upvotes: 3

pavel
pavel

Reputation: 3498

Your Perl script will be compiled first, then run; so changing your script while it runs won't change the running compiled code.

Consider this example:

#!/usr/bin/perl

use strict;
use warnings;

push @ARGV, $0;
$^I = '';

my $foo = 42;
my $bar = 56;

my %switch = (
    foo => 'bar',
    bar => 'foo',
);

while (<ARGV>) {
    s/my \$(foo|bar)/my \$$switch{$1}/;
    print;
}

print "\$foo: $foo, \$bar: $bar\n";

and watch the result when run multiple times.

Upvotes: 2

jmz
jmz

Reputation: 5479

The script file is read once into memory. You can edit the file from another utility after that -- or from the Perl script itself -- if you wish.

Upvotes: 0

Related Questions