Projekt

Allgemein

Profil

Herunterladen (7,9 KB) Statistiken
| Zweig: | Markierung: | Revision:
149d2f33 Moritz Bunkus
#!/usr/bin/perl

use strict;

22e5a8bb Moritz Bunkus
my $exe_dir;

149d2f33 Moritz Bunkus
BEGIN {
ecb3c2e6 Moritz Bunkus
use FindBin;

cff913a1 Moritz Bunkus
unshift(@INC, $FindBin::Bin . '/../modules/override'); # Use our own versions of various modules (e.g. YAML).
push (@INC, $FindBin::Bin . '/..'); # '.' will be removed from @INC soon.
push (@INC, $FindBin::Bin . '/../modules/fallback'); # Only use our own versions of modules if there's no system version.
149d2f33 Moritz Bunkus
}

use CGI qw( -no_xhtml);
use Cwd;
use Daemon::Generic;
use Data::Dumper;
use DateTime;
use English qw(-no_match_vars);
db7dbf26 Moritz Bunkus
use File::Spec;
cff913a1 Moritz Bunkus
use List::MoreUtils qw(any);
a63be3ad Moritz Bunkus
use List::Util qw(first);
7056eb31 Moritz Bunkus
use POSIX qw(setuid setgid);
149d2f33 Moritz Bunkus
use SL::Auth;
07672867 Moritz Bunkus
use SL::DBUpgrade2;
c6dd542b Moritz Bunkus
use SL::DB::AuthClient;
149d2f33 Moritz Bunkus
use SL::DB::BackgroundJob;
use SL::BackgroundJob::ALL;
use SL::Form;
use SL::Helper::DateTime;
c3f94f18 Sven Schöling
use SL::InstanceConfiguration;
149d2f33 Moritz Bunkus
use SL::LXDebug;
67b21d42 Moritz Bunkus
use SL::LxOfficeConf;
149d2f33 Moritz Bunkus
use SL::Locale;
29458987 Moritz Bunkus
use SL::Mailer;
cff913a1 Moritz Bunkus
use SL::System::Process;
db7dbf26 Moritz Bunkus
use SL::System::TaskServer;
29458987 Moritz Bunkus
use Template;
149d2f33 Moritz Bunkus
e08abae0 Moritz Bunkus
our %lx_office_conf;
149d2f33 Moritz Bunkus
e36a3c06 Moritz Bunkus
sub debug {
return if !$lx_office_conf{task_server}->{debug};
c6dd542b Moritz Bunkus
$::lxdebug->message(LXDebug::DEBUG1(), join(' ', "task server:", @_));
}

sub enabled_clients {
return SL::DB::Manager::AuthClient->get_all(where => [ '!task_server_user_id' => undef ]);
e36a3c06 Moritz Bunkus
}

58c87e38 Moritz Bunkus
sub initialize_kivitendo {
c6dd542b Moritz Bunkus
my ($client) = @_;
58c87e38 Moritz Bunkus
c6dd542b Moritz Bunkus
chdir $exe_dir;
149d2f33 Moritz Bunkus
package main;

c3f94f18 Sven Schöling
$::lxdebug = LXDebug->new;
$::locale = Locale->new($::lx_office_conf{system}->{language});
$::form = Form->new;
$::auth = SL::Auth->new;
c6dd542b Moritz Bunkus
return if !$client;

$::auth->set_client($client->id);

$::form->{__ERROR_HANDLER} = sub { die @_ };

c3f94f18 Sven Schöling
$::instance_conf = SL::InstanceConfiguration->new;
d7fddb8d Moritz Bunkus
$::request = SL::Request->new(
cgi => CGI->new({}),
layout => SL::Layout::None->new,
);

58c87e38 Moritz Bunkus
die 'cannot reach auth db' unless $::auth->session_tables_present;

d7fddb8d Moritz Bunkus
$::auth->restore_session;
58c87e38 Moritz Bunkus
$::auth->create_or_refresh_session;
d7fddb8d Moritz Bunkus
c6dd542b Moritz Bunkus
my $login = $client->task_server_user->login;

58c87e38 Moritz Bunkus
die "cannot find user $login" unless %::myconfig = $::auth->read_user(login => $login);
die "cannot find locale for user $login" unless $::locale = Locale->new($::myconfig{countrycode} || $::lx_office_conf{system}->{language});
d7fddb8d Moritz Bunkus
}

428bfc18 Moritz Bunkus
sub cleanup_kivitendo {
50119c7a Sven Schöling
eval { SL::DB->client->dbh->rollback; };
428bfc18 Moritz Bunkus
$::auth->save_session;
$::auth->expire_sessions;
$::auth->reset;

$::form = undef;
$::myconfig = ();
$::request = undef;
c6dd542b Moritz Bunkus
$::auth = undef;
}

sub clean_before_sleeping {
SL::DBConnect::Cache->disconnect_all_and_clear;
SL::DB->db_cache->clear;
c1c40424 Moritz Bunkus
File::Temp::cleanup();
428bfc18 Moritz Bunkus
}

7056eb31 Moritz Bunkus
sub drop_privileges {
e08abae0 Moritz Bunkus
my $user = $lx_office_conf{task_server}->{run_as};
7056eb31 Moritz Bunkus
return unless $user;

my ($uid, $gid);
while (my @details = getpwent()) {
next unless $details[0] eq $user;
($uid, $gid) = @details[2, 3];
last;
}
endpwent();

if (!$uid) {
print "Error: Cannot drop privileges to ${user}: user does not exist\n";
exit 1;
}

if (!setgid($gid)) {
print "Error: Cannot drop group privileges to ${user} (group ID $gid): $!\n";
exit 1;
}

if (!setuid($uid)) {
print "Error: Cannot drop user privileges to ${user} (user ID $uid): $!\n";
exit 1;
}
}

29458987 Moritz Bunkus
sub notify_on_failure {
my (%params) = @_;

my $cfg = $lx_office_conf{'task_server/notify_on_failure'} || {};

return if any { !$cfg->{$_} } qw(send_email_to email_from email_subject email_template);

chdir $exe_dir;

return debug("Template " . $cfg->{email_template} . " missing!") unless -f $cfg->{email_template};

my $email_to = $cfg->{send_email_to};
if ($email_to !~ m{\@}) {
my %user = $::auth->read_user(login => $email_to);
return debug("cannot find user for notification $email_to") unless %user;

$email_to = $user{email};
return debug("user for notification " . $user{login} . " doesn't have a valid email address") unless $email_to =~ m{\@};
}

my $template = Template->new({
INTERPOLATE => 0,
EVAL_PERL => 0,
ABSOLUTE => 1,
CACHE_SIZE => 0,
e3159b22 Moritz Bunkus
ENCODING => 'utf8',
29458987 Moritz Bunkus
});

return debug("Could not create Template instance") unless $template;

$params{client} = $::auth->client;

c6dd542b Moritz Bunkus
eval {
my $body;
$template->process($cfg->{email_template}, \%params, \$body);

Mailer->new(
from => $cfg->{email_from},
to => $email_to,
subject => $cfg->{email_subject},
content_type => 'text/plain',
charset => 'utf-8',
e3159b22 Moritz Bunkus
message => $body,
c6dd542b Moritz Bunkus
)->send;

1;
} or do {
debug("Sending a failure notification failed with an exception: $@");
};
29458987 Moritz Bunkus
}

149d2f33 Moritz Bunkus
sub gd_preconfig {
my $self = shift;

31eb98ad Moritz Bunkus
SL::LxOfficeConf->read($self->{configfile});
149d2f33 Moritz Bunkus
c6dd542b Moritz Bunkus
die "Missing section [task_server] in config file" unless $lx_office_conf{task_server};

if ($lx_office_conf{task_server}->{login} || $lx_office_conf{task_server}->{client}) {
print STDERR <<EOT;
ERROR: The keys 'login' and/or 'client' are still present in the
section [task_server] in the configuration file. These keys are
deprecated. You have to configure the clients for which to run the
task server in the web admin interface.

The task server will refuse to start until the keys have been removed from
the configuration file.
EOT
exit 2;
}
149d2f33 Moritz Bunkus
07672867 Moritz Bunkus
initialize_kivitendo();

my $dbupdater_auth = SL::DBUpgrade2->new(form => $::form, auth => 1)->parse_dbupdate_controls;
if ($dbupdater_auth->unapplied_upgrade_scripts($::auth->dbconnect)) {
print STDERR <<EOT;
The authentication database requires an upgrade. Please login to
kivitendo's administration interface in order to apply it. The task
server cannot start until the upgrade has been applied.
EOT
exit 2;
}

7056eb31 Moritz Bunkus
drop_privileges();
149d2f33 Moritz Bunkus
return ();
}

c6dd542b Moritz Bunkus
sub run_once_for_all_clients {
initialize_kivitendo();

my $clients = enabled_clients();

foreach my $client (@{ $clients }) {
debug("Running for client ID " . $client->id . " (" . $client->name . ")");
58c87e38 Moritz Bunkus
c6dd542b Moritz Bunkus
my $ok = eval {
initialize_kivitendo($client);
149d2f33 Moritz Bunkus
my $jobs = SL::DB::Manager::BackgroundJob->get_all_need_to_run;

c6dd542b Moritz Bunkus
if (@{ $jobs }) {
debug(" Executing the following jobs: " . join(' ', map { $_->package_name } @{ $jobs }));
} else {
debug(" No jobs to execute found");
}
149d2f33 Moritz Bunkus
f6669610 Moritz Bunkus
foreach my $job (@{ $jobs }) {
# Provide fresh global variables in case legacy code modifies
# them somehow.
c6dd542b Moritz Bunkus
initialize_kivitendo($client);
22e5a8bb Moritz Bunkus
29458987 Moritz Bunkus
my $history = $job->run;

ce89fe5c Moritz Bunkus
debug(" Executed job " . $job->package_name .
"; result: " . (!$history ? "no return value" : $history->has_failed ? "failed" : "succeeded") .
($history && $history->has_failed ? "; error: " . $history->error_col : ""));

29458987 Moritz Bunkus
notify_on_failure(history => $history) if $history && $history->has_failed;
f6669610 Moritz Bunkus
}
149d2f33 Moritz Bunkus
1;
};

29458987 Moritz Bunkus
if (!$ok) {
my $error = $EVAL_ERROR;
debug("Exception during execution: ${error}");
notify_on_failure(exception => $error);
}

428bfc18 Moritz Bunkus
cleanup_kivitendo();
c6dd542b Moritz Bunkus
}
}

sub gd_run {
while (1) {
cc7356a7 Moritz Bunkus
$SIG{'ALRM'} = 'IGNORE';

c6dd542b Moritz Bunkus
run_once_for_all_clients();
428bfc18 Moritz Bunkus
e36a3c06 Moritz Bunkus
debug("Sleeping");
149d2f33 Moritz Bunkus
c6dd542b Moritz Bunkus
clean_before_sleeping();

149d2f33 Moritz Bunkus
my $seconds = 60 - (localtime)[0];
2dffed32 Moritz Bunkus
if (!eval {
cc7356a7 Moritz Bunkus
$SIG{'ALRM'} = sub {
$SIG{'ALRM'} = 'IGNORE';
e36a3c06 Moritz Bunkus
debug("Got woken up by SIGALRM");
2dffed32 Moritz Bunkus
die "Alarm!\n"
};
sleep($seconds < 30 ? $seconds + 60 : $seconds);
1;
}) {
die $@ unless $@ eq "Alarm!\n";
}
149d2f33 Moritz Bunkus
}
}

cff913a1 Moritz Bunkus
$exe_dir = SL::System::Process->exe_dir;
chdir($exe_dir) || die "Cannot change directory to ${exe_dir}\n";
149d2f33 Moritz Bunkus
db7dbf26 Moritz Bunkus
mkdir SL::System::TaskServer::PID_BASE() if !-d SL::System::TaskServer::PID_BASE();

my $file = first { -f } ("${exe_dir}/config/kivitendo.conf", "${exe_dir}/config/lx_office.conf", "${exe_dir}/config/kivitendo.conf.default");

die "No configuration file found." unless $file;

$file = File::Spec->abs2rel(Cwd::abs_path($file), Cwd::abs_path($exe_dir));
149d2f33 Moritz Bunkus
67b21d42 Moritz Bunkus
newdaemon(configfile => $file,
b7348417 Moritz Bunkus
progname => 'kivitendo-background-jobs',
db7dbf26 Moritz Bunkus
pidbase => SL::System::TaskServer::PID_BASE() . '/',
149d2f33 Moritz Bunkus
);

1;