Open filehandle not working under mod_perl ModPerl::PerlRun - perl

I'm at my first attempt to use mod_perl. I'm totally new to it. I opted for ModPerl::PerlRun because I don't want to make any modification to the scripts I already have
I followed the instructions in Installing Apache2/Modperl on Ubuntu 12.04
I uploaded script.pl to /perl, and the script looks like it's running fine except for this
open(my $fh, '<:encoding(UTF-8)', 'page_template.htm') or die $!;
It won't open the file and dies with the message
No such file or directory at /var/www/perl/script.pl

Update
Note that the documentation for ModPerl::PerlRun has this to say
META: document that for now we don't chdir() into the script's dir, because it affects the whole process under threads.
so it is probably not workable to simply do a chdir in your program's code, and the second option below should be used
Original*
The current working directory of your CGI program isn't what you think. It is most likely to tbe the root directory /
You can either use chdir to set the working directory of the script
use File::Basename 'dirname';
chdir dirname(__FILE__);
or simply add the full path to the name of the file that you want to open, for instance
open my $fh, '<:encoding(UTF-8)', '/perl/page_template.htm' or die $!;
Note that you can't use FindBin, as your program is being run as a subroutine of Apache's main mod_perl process, so $FindBin::Bin will be equal to the directory of the Apache executable httpd and not of your own program file

Related

perl novice, need assistance with handling file script

Very new to Perl. Running Perl on Padre and Windows 10 OS.
The script from my book is written for Unix. I don't know how to correct it so that it works with Windows.
Here is the script as written in my book (FOR UNIX):
use warnings;
#write to a file with a filehandle. Sriptname: file.handle
my $file="/home/jody/ellie/perl/newfile";
open(my $fh, ">", $file) || die "Can't open newfile: $!\n";
print $fh "hello world.\n";
print $fh "hello world again.\n";
At the command line
$perl file.handle
$cat newfile
the output should be looking like this:
hello world.
hello world again.
I made the following changes but with no success
use warnings;
#Write to a file with a filehandle. Scriptname: file.handle
my $file='C:\newfile.txt';
open (my $fh, ">", $file) || die "Can't open newfile: $!\n";
print $fh "hello world.\n";
print $fh "hello world again.\n";
When I run script I get the following output:
can't open newfile: permission denied**
When I run the script with debug I get the following information:
uncaught exception for user code
can't open newfile: permission denied
at handlingfiles.pl line 5
press any key to continue
What am i doing wrong?
As #choroba mentioned in a comment, C:\newfile.txt will [try to] write to the Windows root directory (e.g. C:\). So, you probably want just newfile.txt.
Cygwin: If you're using the perl that comes with cygwin, you can probably use /home/jody/newfile.txt as this perl supports the POSIX file syntax. If you installed cygwin at (e.g.) D:\cygwin, then the /home directory will end up in D:cygwin\home. Note you do ls /home to see what users have been defined.
Otherwise, if you want a full path, what is the full path for your .pl script. Obviously, you could write to that directory.
Side note: I've been writing perl for many years and on those rare occasions when I do use it on Windows, I vastly prefer using the cygwin version [that also has many scripts, tools, etc. and functions like a POSIX environment]. YMMV
Perl is asked to open the file for writing, so that is what it does. On Windows, normal users cannot write to the root directory of a drive, and Windows rejects its request. Try something like C:\Users\User\My Documents\newfile.txt.

Build array of the contents of the working directory in perl

I am working on a script which utilizes files in surrounding directories using a path such as
"./dir/file.txt"
This works fine, as long as the working directory is the one containing the script. However the script is going out to multiple users and some people may not change their working directory and run the script by typing its entire path like this:
./path/to/script/my_script.pl
This poses a problem as when the script tries to access ./dir/file.txt it is looking for the /dir directory in the home directory, and of course, it can't fine it.
I am trying to utilize readdir and chdir to correct the directory if it isn't the right one, here is what I have so far:
my $working_directory = $ENV{PWD};
print "Working directory: $working_directory\n"; #accurately prints working directory
my #directory = readdir $working_directory; #crashes script
if (!("my_script.pl" ~~ #directory)){ #if my_script.pl isnt in #directoryies, do this
print "Adjusting directory so I work\n";
print "Your old directory: $ENV{PWD}\n";
chdir $ENV{HOME}; #make the directory home
chdir "./path/to/script/my_script.pl"; #make the directory correct
print "Your new directory: $ENV{PWD}\n";
}
The line containing readdir crashes my script with the following error
Bad symbol for dirhandle at ./path/to/script/my_script.pl line 250.
which I find very strange because I am running this from the home directory which prints out properly right beforehand and contains nothing to do with the "bad symbol"
I'm open to any solutions
Thank you in advance
The readdir operates with a directory handle, not a path on a string. You need to do something like:
opendir(my $dh, $working_directory) || die "can't opendir: $!";
my #directory = readdir($dh);
Check perldoc for both readdir and opendir.
I think you're going about this the wrong way. If you're looking for a file that's travelling with your script, then what you probably should consider is the FindBin module - that lets you figure out the path to your script, for use in path links.
So e.g.
use FindBin;
my $script_path = $FindBin::Bin;
open ( my $input, '<', "$script_path/dir/file.txt" ) or warn $!;
That way you don't have to faff about with chdir and readdir etc.

How to run set of .exe files in a folder through .bat file using perl script

I am beginner to Perl and I have to create a .pl file and I have folder containing near about 30 exe files(inside Folder1 in G:\Folder1). All of them must be executed by click to the .pl file.
My try is :
use strict; use warnings;
use autodie; # automatic error handling
while (defined(my $file = glob 'C:\shekhar_Axestrack_Intern*.exe'))
{
open my $fh, "<", $file; # lexical file handles, automatic error handling
while (defined( my $line = <$fh> )) {
do system $fh ;
}
close $fh;
}
Please let me know if my logic correct ? Could some one please correct me if i am wrong ?
Use system to execute an exe:
while (my $file = glob 'C:\shekhar_Axestrack_Intern\*.exe') {
system $file;
}
In addition, I have the feeling that you meant to write 'C:\shekhar_Axestrack_Intern*.exe'
instead of 'C:\shekhar_Axestrack_Intern*.exe'.
I think pl2bat may help you. It allows you to wrap Perl code into a batch file.
BTW why are you using echo in your Perl script? You should use print.
Edit: You have edited your question and now you want to know how to run all exe files from a folder using Perl?
Use the system command to run the exe files providing the full path.
See: How to run an executable file using Perl on Windows XP?
Edit 2: do system $fh ; This is not how you do it, please get a book (I'd suggest Beginning Perl by Ovid) and start learning Perl.

Perl: How to go to the root directory from a script

I want to go to a directory, print in some files, then go back to the root directory.
So, I did this :
chdir "corpus";
open (OUTFILE, ">para$i") or die "Impossible d'ouvrir le fichier\n";
print OUTFILE $tab[$i];
close OUTFILE;
`cd /`;
But it obviously does not work (the cd / part). How do I go back to the root directory once I moved to the child directory in a Perl script?
Thanks a lot :).
Ok, now I have an other issue with this :
for (my $i=0; $i<$number_para;$i++){
open (OUTFILE, ">", "para$i.txt") or die ;
print OUTFILE $tab[$i];
}
worked fine, but when I added the chdir:
for (my $i=0; $i<$number_para;$i++){
chdir "corpus"
open (OUTFILE, ">", "para$i.txt") or die ;
print OUTFILE $tab[$i];
chdir "/"
}
It says "print() on closed filehandle OUTFILE". I don't understand why, since it worked fine before...
chdir "/"
will work just fine. Or if you have a set directory in a variable:
chdir $dir or die $!;
Or as Miller says, you can refer to ... However, you should be aware that you do not have to change directory. If you want to open a file in another directory, you can supply the relative path to it:
open (my $out, ">", "Corpus/para$i") or die $!;
Note that you should use three argument open, with explicit mode, and lexical file handle.
You say root directory, but it looks like you actually just want the parent directory.
To go to the parent directory, use '..';
chdir "..";
Or if you want to be paranoid about cross platform compatability:
use File::Spec;
chdir File::Spec->updir();
To actually go the root directory, just use chdir like you did the first time:
chdir '/';
or once again being paranoid about cross platform compatability:
use File::Spec;
chdir File::Spec->rootdir();
It might be worth pointing out why using cd in backticks didn't work.
Running a command in backticks starts up a completely new shell environment for the command. That new environment starts with a copy of all of the environment variables from the environment that your program is running in. The current directory is one of those environment variables (it's in $ENV{PWD}).
You new environment starts up. The first (and only) thing that it does is to change directory. So the value of $ENV{PWD} in the new environment is changed. But the value in your original environment stays the same as it was.
Your new environment then closes down as its job is done. All of the environment variables that it has are removed from memory. And control returns to the original environment. Which still has the original value for the current directory.
A child environment cannot change the environment variables in its parent environment. So any attempt to change directory using an external program is doomed to failure.
But changing directory using Perl's built-in function chdir works just fine. Because that changes the value in the current environment.
Hope that's helpful.

How to open multiple files in Perl

Guys im really confused now. Im new to learning Perl. The book ive read sometimes do Perl codes and sometimes do Linux commands.
Is there any connection between them? (Perl codes and linux commands)
I want to open multiple files using Perl code, i know how to open a single file in Perl using:
open (MYFILE,'somefileshere');
and i know how to view multiple files in Linux using ls command.
So how to do this? can i use ls in perl? And i want to open certain files only (perl files) which dont have file extension visible (I cant use *.txt or etc. i guess)
A little help guys
Use system function to execute linux command, glob - for get list of files.
http://perldoc.perl.org/functions/system.html
http://perldoc.perl.org/functions/glob.html
Like:
my #files = glob("*.h *.m"); # matches all files with a .h or .m extension
system("touch a.txt"); # linux command "touch a.txt"
Directory handles are also quite nice, particularly for iterating over all the files in a directory. Example:
opendir(my $directory_handle, "/path/to/directory/") or die "Unable to open directory: $!";
while (my $file_name = <$directory_handle>) {
next if $file_name =~ /some_pattern/; # Skip files matching pattern
open (my $file_handle, '>', $file_name) or warn "Could not open file '$file_name': $!";
# Write something to $file_name. See <code>perldoc -f open</code>.
close $file_handle;
}
closedir $directory_handle;