I'm looking for a initscript to make usage of perlbrew on a webserver running a nginx as proxy for an perl catalyst application. I'm currently trying to start the app via
source $PERLBREW
execute "perlbrew use perl-5.14.4#devel"
execute "mkdir -p $PID_PATH && $START_ICOS_APP > /dev/null 2>&1 &"
echo "$DESC started"
but it appers it cannot find the local perl installation. $PERLBREW is set to my perlbrew folder.
This is a good step by step guide how to do this, but it is French (but still understandable).
http://www.catapulse.org/articles/view/124
I copied here:
Setup the user which is going to run the catalyst app (www-data in this example)
su - www-data
curl -kL http://install.perlbrew.pl | bash
echo 'source ~/perl5/perlbrew/etc/bashrc' >> .profile
. .profile
perlbrew install perl-5.16.3 -Dusethreads --as perl-5.16.3_WITH_THREADS
perlbrew switch perl-5.16.3_WITH_THREADS
#perlbrew install-cpanm
#cpanm Catalyst Catalyst::Devel
#catalyst.pl myapp
(I assume that your application name is myapp, replace it with yours.)
create /etc/nginx/sites-enabled/myapp
server {
listen 80;
server_name exemple.com *.exemple.com;
client_max_body_size 50m;
location / {
include /etc/nginx/fastcgi_params;
fastcgi_param SCRIPT_NAME '';
fastcgi_param PATH_INFO $fastcgi_script_name;
fastcgi_pass unix:/var/www/myapp/myapp.socket;
}
location /static {
root /var/www/myapp/root;
expires 30d;
}
}
Create /var/www/myapp/myapp.fastcgi.initd
#!/usr/bin/env perl
use warnings;
use strict;
use Daemon::Control;
# 1) create initd file
# ./myapp.fastcgi.initd get_init_file > /etc/init.d/cat-myapp
#
# 3) install to runlevels
# update-rc.d cat-myapp defaults
my $app_home = '/var/www/myapp';
my $perl = 'perl';
my $program = $app_home . '/script/myapp_fastcgi.pl';
my $name = 'myapp';
my $workers = 1;
my $pid_file = $app_home . '/myapp.pid';
my $socket = $app_home . '/myapp.socket';
Daemon::Control->new({
name => $name,
lsb_start => '$nginx',
lsb_stop => '$nginx',
lsb_sdesc => $name,
lsb_desc => $name,
path => $app_home . '/myapp.fastcgi.initd',
user => 'www-data',
group => 'www-data',
directory => $app_home,
program => "$perl $program --nproc $workers --listen $socket",
pid_file => $pid_file,
stderr_file => $app_home . '/myapp.out',
stdout_file => $app_home . '/myapp.out',
fork => 2,
})->run;
Set permission on files and create the proper init file:
$ chmod +x myapp.fastcgi.initd
$ ./myapp.fastcgi.initd get_init_file > /etc/init.d/cat-myapp
Start your application and bounce your webserver:
$ /etc/init.d/cat-myapp start
$ /etc/init.d/nginx restart
Related
I'm working with a Nagios plugin called check_logfiles. a pretty powerful script. I have it working on Unix/Linux and Windows. well, all but 1 feature. the ability to execute a post or pre script hook.
I just can't get a postscript to execute from the check_logfiles.cfg.
I get from check_logfiles protocol file
WARNING Errors in postscript (tag postscript)
cannot execute custom_mail_alert.pl
I tried running it with the -d trace option - no success gettng debug output. ?
I've tried several different implementations seen in config file below. Any help with understanding why a postscript cannot execute in check_logfies I really appreciate it much, thank you.
note: the script check_logfiles executes successfully even if postscript fails - this is OK and Good.
thank you for your help, I'm pulling my hair out :) I can't seem to figure it out.
check_logfiles works
custom_mail_alert.pl works on command line, but not as called from check_logfiles ?
The check_logfiles.cfg:
$scriptpath = 'C:\Program Files (x86)\Nagios\NCPA\contrib';
$protocolsdir = 'C:\Program Files (x86)\Nagios\NCPA\protocols';
$seekfilesdir = 'C:\Program Files (x86)\Nagios\NCPA\seek';
$MACROS = {
LOGS_DIR => 'C:\APMConnect\Logs',
PP_INGESTION_EP => 'C:\APMConnect\AutoDataLoader\Scandir\ManageAPM',
SRC_DIR => '\\win.alphper031.corporate.com\APM_Data_Storage\Zip File Archive',
CL_CMAIL_SMTP_HOST => 'mail.ad.com',
CL_CMAIL_TO => 'gary.l.mills#corp.com',
CL_CMAIL_FROM => 'ALPCTS000000881#alpcts000000881.corp.com',
CL_CMAIL_SUBJECT => 'APM Loader - Upload Failure Notification'
};
#$postscript = 'C:\Program Files (x86)\Nagios\NCPA\contrib\custom_mail_alert.pl';
#$postscript = 'perl custom_mail_alert.pl';
$postscript = 'custom_mail_alert.pl';
$postscriptparams = '-Host $CL_CMAIL_SMTP_HOST$ -To $CL_CMAIL_TO$ -From $CL_CMAIL_FROM$ -Subject "$CL_CMAIL_SUBJECT$" -Body "The APM Loader Upload Failed.\n Please see attached." -Attachment "C:\Program Files (x86)\Nagios\NCPA\seek\check_logfiles.C__APMConnect_Logs_AutoLoader.log.504 Gateway Time-Out" -Send_if_rc_gt $CL_SERVICESTATEID$';
#$postscriptstdin = '$CL_HOSTNAME$\t$CL_SERVICEDESC$\t$CL_SERVICESTATEID$\t$CL_SERVICEOUTPUT$\n';
#searches = (
{
tag => '504 Gateway Time-Out',
logfile => '$LOGS_DIR$\AutoLoader.log',
rotation => 'AutoLoader.log.\d{1,2}',
type => 'rotating',
criticalpatterns => [
'^java.lang.Exception:Method failed: HTTP/1.1 504 Gateway Time-out Please check configuration details and replace or update the file :.*'],
options => 'protocol,perfdata,script,supersmartscript',
script => sub {
use File::Copy;
my $cmd = 'net use E: /delete /y';
my $other_cmd = 'net use E: \\\\win.alphper031.corporate.com\\APM_Data_Storage /USER:logon.ds.com\\lg4274sv xnEDs7UMh3gT /PERSISTENT:YES';
my $other_status = system($other_cmd);
my $_source_dir = $ENV{CHECK_LOGFILES_SRC_DIR};
my $_target_dir = $ENV{CHECK_LOGFILES_PP_INGESTION_EP};
my $sout = $ENV{CHECK_LOGFILES_SERVICEOUTPUT};
my $result = rindex($sout, 'FaultData');
my $_file_name = substr($sout, $result, length($sout));
opendir (dir, $_source_dir);
if( -f "$_source_dir/$_file_name" ) {
copy ("$_source_dir\\$_file_name", "$_target_dir\\$_file_name");
if ( $? ) {
printf 'OK - File Copy Successful!';
printf " Copied File to Refeed APM: $_source_dir\\$_file_name";
return 0;
} else {
printf 'CRITICAL - File Copy Failed!';
printf " - Source dir: $_source_dir\\$_file_name";
return 2;
}
} else {
printf 'CRITICAL - File Copy Failed, File CANNOT be located! Resource may not be Mounted!';
printf " - Source dir: $_source_dir\\$_file_name";
return 2;
}
closedir($dir);
}});
The custom_mail_alert.pl script:
! C:\strawberry\perl\bin\perl -w
use strict;
use warnings;
use Getopt::Long;
my $Host;
my $To;
my $From;
my $Subject;
my $Body;
my $Attachment;
my $Send_if_rc_gt;
GetOptions(
"Host=s" => \$Host,
"To=s" => \$To,
"From=s" => \$From,
"Subject=s" => \$Subject,
"Body=s" => \$Body,
"Attachment=s" => \$Attachment,
"Send_if_rc_gt=i" => \$Send_if_rc_gt
);
printf "host:$Host\n";
printf "to:$To\n";
printf "from:$From\n";
printf "subject:$Subject\n";
printf "body:$Body\n";
printf "attachment:$Attachment\n";
printf "send_if_rc_gt:$Send_if_rc_gt\n";
my #cmd = ('C:\Program Files (x86)\Nagios\NCPA\contrib\cmail.exe');
push #cmd, "-host:$Host";
push #cmd, "-to:$To";
push #cmd, "-from:$From";
push #cmd, "-subject:$Subject";
push #cmd, "-body:$Body";
push #cmd, "-a:$Attachment";
printf "#cmd\n";
if (!defined $Host||!defined $To||!defined $From||!defined $Subject ||!defined $Body){
print "Usage: $0 -Host <host> -To <to> -From <from> -Subject <subject> -Body <mail body=""> -Attachment [--send-if-rc-gt <1-9> ]\n";
exit (-1);
}
require $Attachment;</mail></subject></from></to></host>
if ((defined $state->{'servicestateid'} && defined $Send_if_rc_gt) && ($state->{'servicestateid'} > $Send_if_rc_gt)){
print "$state->{'servicestateid'} was lower than $send_if_rc_gt\n";
exit 0;
}
if ($state->{'serviceoutput'}){
system(#cmd);
}
In the process of writing a Perl-script to submit PBS-jobs, I noticed that the output-files are only usable by the owner (rw-------). After some research, I found that you can put #PBS -W umask=002 in the job-script to make it accessible for others.
Perl:
my $client = PBS::Client->new();
my $wd = $dir_temp;
my $name = "demultiplex";
my $queue = "default";
my $wallt = "72:00:00";
my $job_demultiplex = PBS::Client::Job -> new(
wd => $wd,
queue => $queue,
name => $name,
wallt => $wallt,
cmd => "perl ".$script_directory."demultiplex.pl ".$dir_in." 2>"."demultiplex_error.log 1>"."demultiplex_output.log"
);
This Perlscript creates the following job:
#!/bin/sh
#PBS -N demultiplex
#PBS -d /store/www/labresults_QC/small_rna_sequence_analyser/data/data_temp/BGI_pilot
#PBS -q default
#PBS -l nodes=1
#PBS -l walltime=72:00:00
#PBS -W umask=002 <---
perl /store/www/labresults_QC/small_rna_sequence_analyser/scripts/demultiplex.pl /store/www/labresults_QC/small_rna_sequence_analyser/data/data_input/BGI_pilot 2>demultiplex_error.log 1>demultiplex_output.log
Is there a possibility to pass the indicated line (<---) to the job from the Perlscript?
Given the current codebase, no. You'd have to open a bug report to the PBS::Client module and request the feature. Accompany it with a patch - that might help.
This is a shell script , How do I accomplish the same thing in Perl?
prfile=~/sqllib/db2profile
profile()
{
if [ -f $prfile ] && [ "$prfile" != "" ];
then
. $prfile
else
read -p "Enter a valid Profile : " prfile
profile
fi
}
profile
Here it checks for the profile file , if found it executes it with . $prfile else it again asks user for the proper profile file
Update
#!/usr/bin/perl
use strict;
use warnings;
my $profile = "$ENV{'HOME'}/sqllib/db2proile";
# default profile
while (not -e $profile) { # until we find an existing file
print "Enter a valid profile: ";
chomp($profile = <>); # read a new profile
}
qx(. $profile);
This worked. I want the home directory to be dynamic rather than hardcoded as they differ for different machines. I'm just trying to accomplish with Perl what I have achieved with shell.
If I understand your objectives, I don't think you can use perl to accomplish this because perl will be running as a child process and it can not change the environment of your shell (it's parent process). Maybe this would work for you (untested, off the cuff)?
prfile=~/sqllib/db2profile
if [ -s "$prfile" ] ; then
. "$prfile"
else
while true ; do
read -p "Enter a valid Profile : " prfile
if [ -s "$prfile" ] ; then
. "$prfile"
break;
fi
done
fi
I'm using the Perl module Sudo.pm from CPAN.
Here is the code I'm using:
# In this two variable I'll store the object that runs sudo commands and
# the exit status of the commands
my ($su, $run);
# This functions accept an object returned from sudo->run and will check
# if there were errors running the code.
sub check_status {
# Retrieving the object
my $run = shift;
if (exists($run->{error})) {
print "Failed.\n";
}
else {
print "Done.\n";
}
}
# This first call erase all RSA related files
$su = Sudo->new(
{
sudo => '/usr/bin/sudo',
username => 'root',
pogram => '/usr/bin/rm',
program_args => '-f /tmp/cvmfs_test.key /tmp/cvmfs_test.csr /tmp/cvmfs_test.crt /tmp/whitelist.test.* /tmp/cvmfs_master.key /tmp/cvmfs_master.pub'
}
);
print 'Erasing RSA keys... ';
$run = $su->sudo_run();
check_status($run);
# This instance will erase configuration files created in /etc/cvmfs/config.d
$su = Sudo->new(
{
sudo => '/usr/bin/sudo',
username => 'root',
program => '/usr/bin/rm',
program_args => '-f /etc/cvmfs/config.d/127.0.0.1.conf'
}
);
print 'Erasing configuration files in /etc/cvmfs/config.d... ';
$run = $su->sudo_run();
check_status($run);
# This instance will erase /tmp/cvmfs.faulty
$su = Sudo->new(
{
sudo => '/usr/bin/sudo',
username => 'root',
program => '/usr/bin/rm',
program_args => '-f /tmp/cvmfs.faulty'
}
);
print 'Erasing /tmp/cvmfs.faulty... ';
$run = $su->sudo_run();
print $run->{stdout};
check_status($run);
# This instance will erase all previous extracted repository
$su = Sudo->new(
{
sudo => '/usr/bin/sudo',
username => 'root',
program => '/usr/bin/rm',
program_args => '-fr /tmp/server'
}
);
print 'Erasing /tmp/server directory... ';
$run = $su->sudo_run();
print $run->{stdout};
check_status($run);
# This instance will run 'restarting_services.sh'
$su = Sudo->new(
{
sudo => '/usr/bin/sudo',
username => 'root',
program => 'sh',
program_args => "$Bin/restarting_services.sh"
}
);
print 'Restarting services... ';
$run = $su->sudo_run();
check_status($run);
Is there someone who can explain me why only some of this instance works? To be precise, the first, the second and the fifth instance doesn't work, while the third and the fourth does.
I'm not able to get any output on STDOUT or STDERR and the check_status() function always answer 'Done', for all of them. But this is only because when the command doesn't work, the object is not set at all.
It seems to me I'm using the same syntax for all of them.
Of course, I'm using it with an user that is able to run sudo without password, that's why I didn't added that parameter.
Thank you very much.
There is a typo in your code.
pogram => '/usr/bin/rm',
should be:
program => '/usr/bin/rm',
David W's suggestions for debugging are absolutely spot-on...
Is there a way to have one app in dancer but with multiple appdirs.
Or could I do something like this:
My project is in dir 'foo'. And let's say that I have a dir 'bar' (not inside 'foo') which has a directory called 'public'. I what my app 'foo' to use this public as its own public and if it searches for let's say '/css/style.css' and it is not in '/bar/public/' it should search the '/foo/public/'. How can I do that?
OK, here is the good way to do it. It can of course be a plugin.
You should never do this kind of things by hacking inside Dancer's core, you should rather always consider implementing a route handler to do the job:
#!/usr/bin/env perl
use Dancer;
use File::Spec;
use Dancer::FileUtils 'read_file_content';
use Dancer::MIME;
use HTTP::Date;
# your routes here
# then the catchall route for
# serving static files
# better in config
my #public_dirs = qw(/tmp/test/foo /tmp/test/bar /tmp/test/baz);
get '/**' => sub {
my $path = request->path;
my $mime = Dancer::MIME->instance;
# security checks
return send_error("unauthrorized request", 403) if $path =~ /\0/;
return send_error("unauthrorized request", 403) if $path =~ /\.\./;
# decompose the path_info into a file path
my #path = split '/', $path;
for my $location (#public_dirs) {
my $file_path = File::Spec->catfile($location, #path);
next if ! -f $file_path;
my $content = read_file_content($file_path);
my $content_type = $mime->for_file($file_path);
my #stat = stat $file_path;
header 'Content-Type', $content_type;
header 'Content-Length', $stat[7];
header 'Last-Modified', HTTP::Date::time2str($stat[9]);
return $content;
}
pass;
};
start;
An example of this app running:
$ mkdir -p /tmp/test/foo /tmp/test/bar /tmp/test/baz
$ echo 1 > /tmp/test/foo/foo.txt
$ echo 2 > /tmp/test/bar/bar.txt
$ echo 3 > /tmp/test/baz/baz.txt
$ ./bin/app.pl
$ curl -I http://0:3000/baz.txt
HTTP/1.0 200 OK
Content-Length: 2
Content-Type: text/plain
Last-Modified: Fri, 14 Oct 2011 11:28:03 GMT
X-Powered-By: Perl Dancer 1.3051
One of the ways if to write a plugin that renders static (and replaces some functionality). You can use Dancer::Plugin::Thumbnail as an example.
Other way I see is to monkey-patch get_file_response() at Dancer::Renderer which is not really such a good idea.
Following code looks for static files in each dir from #dirs array. It's dirty, ugly and unsafe.
This can be broken in future version and may cause problems with other parts of Dancer framework I'm not familiar with. You're warned.
#!/usr/bin/env perl
use Dancer;
use Dancer::Renderer;
use MyWeb::App;
my $get_file_response_original = \&Dancer::Renderer::get_file_response;
my #dirs = ('foo');
*Dancer::Renderer::get_file_response = sub {
my $app = Dancer::App->current;
my $result;
# Try to find static in default dir
if ($result = $get_file_response_original->(#_)) {
return $result;
}
# Save current settings
my $path_backup = $app->setting('public');
# Go through additional dirs
foreach my $dir (#dirs) {
$app->setting(public => $dir);
if ($result = $get_file_response_original->(#_)) {
last;
}
}
# Restore public
$app->setting('public' => $path_backup);
return $result
};
dance;
Third ways is to let nginx just do this work for you by writing proper nginx config for your application.
May be this module will help to you?
https://github.com/Perlover/Dancer-Plugin-Hosts
You can setup virtual sites in Dancer with own appdir & other directory settings
I uploaded this module today to github
Soon will be in CPAN