Haiyuan Zhang
Haiyuan Zhang

Reputation: 42792

how to run piece of code just before the exit of perl script

In my script, I need to load some info from disk file and during the run of script the info might be changed.To keep the consistence of the file in disk and it's in memory copy I need to write back the info to disk whenever the info is changed in memory or periodically write them back to disk or just write them back at the time of the script exit, which is the preferred one, because it will save lots of IO time and make the script responsive.

So just as the title, my question is does perl has some mechanism that will meet my needs?

Upvotes: 12

Views: 11923

Answers (3)

Oleksandr Tsurika
Oleksandr Tsurika

Reputation: 980

to handle Control-C you need to handle signals (no END block is triggered). It could be done next:

$SIG{INT}  = \&signal_handler;
$SIG{TERM} = \&signal_handler;

sub signal_handler {
    #implement here pre exit logic
    die "\n";
}

Upvotes: 3

Cosimo
Cosimo

Reputation: 3011

There's two different ways to do this, depending on what you're looking for.

  • The END block is executed when the interpreter is shut down. See the previous answer for more details :)
  • The DESTROY block/sub, that is executed when your object goes out of scope. That is, if you want to embed your logic into a module or class, then you can use DESTROY.

Take a look at the following example (it's a working example, but some details like error checking, etc.. are omitted):

#!/usr/bin/env perl

package File::Persistent;

use strict;
use warnings;
use File::Slurp;

sub new {
    my ($class, $opt) = @_;

    $opt ||= {};

    my $filename = $opt->{filename} || "./tmpfile";
    my $self = {
        _filename => $filename,
        _content => "",
    };

    # Read in existing content
    if (-s $filename) {
        $self->{_content} = File::Slurp::read_file($filename);
    }

    bless $self, $class;
}

sub filename {
    my ($self) = @_;
    return $self->{_filename};
}

sub write {
    my ($self, @lines) = @_;
    $self->{_content} .= join("\n", @lines);
    return;
}

sub DESTROY {
    my ($self) = @_;
    open my $file_handle, '>', $self->filename
        or die "Couldn't save persistent storage: $!";
    print $file_handle $self->{_content};
    close $file_handle;
}

# Your script starts here...
package main;

my $file = File::Persistent->new();

$file->write("Some content\n");

# Time passes...
$file->write("Something else\n");

# Time passes...
$file->write("I should be done now\n");

# File will be written to only here..

Upvotes: 9

Amadan
Amadan

Reputation: 198324

I think you're looking for END block:

END {
    # cleanup
}

An END code block is executed as late as possible, that is, after perl has finished running the program and just before the interpreter is being exited, even if it is exiting as a result of a die() function. (But not if it's morphing into another program via exec, or being blown out of the water by a signal--you have to trap that yourself (if you can).) You may have multiple END blocks within a file--they will execute in reverse order of definition; that is: last in, first out (LIFO). END blocks are not executed when you run perl with the -c switch, or if compilation fails.

Upvotes: 30

Related Questions