AlanDev1989
AlanDev1989

Reputation: 85

Run Perl Code (which includes file paths) from anywhere

I am creating a daemon using perl and I am having trouble getting the script to run from anywhere (as desired). The script writes the process id in a file and also logs the output. The code which works is below, if i try to change this, for example get pwdand insert this before my folder names the error i get is that there is no file or directory, e.g. i say $dir = pwdand then set my pid file for example to $dir/pid/conductor_daemon_test.pid. Any ideas how to get this to run regardless of location?

#!/usr/bin/perl

use POSIX qw(setsid);
my $proc;
my $error;
my $file="conductor.pl";
my $pidfile=">./home/perl_daemon/conductor/pid/conductor_daemon_test.pid";
my$pid2check="/home/perl_daemon/conductor/pid/conductor_daemon_test.pid";
my $pid;

#Make it a daemon
$proc = Daemonize();

if(!$error){
    LogMessage("$file:PID $proc: Begin");
}

#Write Pid Information
if(!$error){
    if(-e $pid2check){
            LogMessage("$file : PID File $pid2check already exists. Exiting..");
            exit(0);
    }
    else {
            unless(open(FILE, $pidfile)){
                    $error = "Error opening file for writing ".$!;
            }
    }
    }
    if(!$error) {
    LogMessage("$file: PID $proc: Writing pid information to $pidfile");
    print FILE $proc ."\n";
    close(FILE);
     }

   my $EXIT = 0;
   $SIG{TERM} = sub{ LogMessage("Caught exit signal!\n");$EXIT=1};

   #Main loop of the Daemon
   while (!$error){

    sleep(100);
    LogMessage("Hello World");


    do { LogMessage("Graceful exit!\n"); exit } if $EXIT;

    }
    if($error){
    LogMessage("$file:PID $proc:Error $error");
    }

    LogMessage ("$file: PID $proc: END");enter code here

     exit(0);

     #
     #Subs
     #
     #####################################

     #       Daemonize
     #
     #####################################
     #
     #       Used to make this program a daemon
     #       Also to redirect STDIN, STDERR, STDOUT
    #       Returns PID
    #
    ########

sub Daemonize {
    #Ensure that the current directory is the working directory
    unless(chdir '/'){
            $error = "Can't chdir to /:$!";
    }
    #Ensure that the file mode mask is changed
    unless(umask 0){
            $error="Unable to umask 0";
    }
    #Ensure the STDIN is closed
    unless(open STDIN, '/dev/null'){
            $error="Can't read /dev/null:$!";
    }
    #All print statements will now be sent to our log file
    unless(open STDOUT, '>> /home/perl_daemon/conductor/log/conductor_daemon_test.log'){
            $error="Can't read /home/perl_daemon/conductor/log/conductor_daemon_test.log:$!";
    }
#All error messages will now be sent to our log file
    unless(open STDERR, '>>/home/perl_daemon/conductor/log/conductor_daemon_test.log'){
            $error="Can't write to /home/perl_daemon/conductor/log/conductor_daemon_test.log:$!";
    }

#Fork off the parent process
defined($pid = fork);
#Exit if $pid exists(parent)
exit(0) if $pid;

#As Child
#Create a new SID for the child process
setsid();
$proc = $$;
return($proc);
}


####
#
#       Log Message
#
#       Used to log messages
#
######

sub LogMessage {
    my $message = $_[0];
    print localtime()." $message\n";
 }

Upvotes: 0

Views: 79

Answers (2)

carlosn
carlosn

Reputation: 433

Using FindBin that is a core module you can easily find the location of your script:

DESCRIPTION

Locates the full path to the script bin directory to allow the use of paths relative to the bin directory.

My suggestion is you could create a pattern for your script so you can put everything in the same folder like:

daemon/script.pl
daemon/pid/ <- pid files
daemon/log/ <- logs 

So your code would be like this:

use FindBin qw($RealBin);

my $pidfile=">.$RealBin/pid/conductor_daemon_test.pid";
my $pid2check="$RealBin/pid/conductor_daemon_test.pid";

You can export the variables below:

EXPORTABLE VARIABLES

 $Bin         - path to bin directory from where script was invoked
 $Script      - basename of script from which perl was invoked
 $RealBin     - $Bin with all links resolved
 $RealScript  - $Script with all links resolved

And then I guess you will not have any problems with location anymore.

Upvotes: 1

SREagle
SREagle

Reputation: 251

It seems you didn't create the 'pid' subdirectory when trying to use pwd. Create it before trying to create the pid file.

Also: Please use lexical file handles and the 3-argument form of open: open (my $fh, '>', $filename) instead of GLOBs (FILE) and '>filename.pid'

Upvotes: 0

Related Questions