Files
scripts/sshcron.pl
2025-06-03 23:03:08 +02:00

234 lines
7.8 KiB
Perl

# Automatically enables "strict", "warnings", "utf8" and Perl 5.10 features
use Mojolicious::Lite;
use Net::SSH::Perl;
use Data::Printer;
use Try::Tiny;
use File::Slurp qw(:std);
use JSON;
my $config = plugin 'Config';
# Datei einlesen
my $fi = read_file( 'sshcron.json', err_mode => "quiet");
my $daten = [];
if ( $fi ) {
$daten = decode_json($fi);
}
# Route with placeholder
get '/' => sub {
my $c = shift;
$c->render(template => 'index', da => $daten );
};
# Route with placeholder
any '/jobs/:new/:server' => {new => '', server => ''} => sub {
my $c = shift;
my $j = $c->req->json;
my $new = $c->stash('new');
my $server = $c->stash('server');
if ( $j->{new} && $j->{server} ) {
$server = $j->{server};
$new = $j->{new};
}
my @servers;
my @neline;
my %se;
my @allserver;
# bei angabe der richtigen Parameter ...
if ( $new =~ /upd|del/ && $server ne "" ) {
for my $old ( @{$daten} ) {
if ( $server eq 'alle' ) {
if ( !$se{$old->{server}} ) {
$se{$old->{server}} = 1;
push @servers, $old->{server};
}
} elsif ( defined $old->{server} && $old->{server} ne $server ) {
push @neline, $old;
}
}
if ( $new eq "upd" ) {
if ( $server ne "alle" ) {
push @servers, $server;
}
for my $ser ( @servers ) {
try {
my $ssh = Net::SSH::Perl->new($ser, options => [ "MACs +hmac-sha1" ]);
$ssh->login('root', '8-Tung');
my($stdout, $stderr, $exit) = $ssh->cmd("grep -rHv '##' '/etc/cron.d'");
next if ( defined $stderr );
for my $text ( split '\n', $stdout ) {
my @s = split ':', $text;
if ( scalar(@s) == 1 || $s[1] =~ /$config->{ignore}/ ) {
} else {
my $status = "Ja";
if ( $s[1] =~ /^#/ ) {
$status = "Nein";
}
my @file = split( '/', $s[0]);
my @j = split( ' ', $s[1]);
my $pro = "";
if (scalar(@j) > 6) {
for my $p ( 6 .. scalar(@j)-1 ) {
if ($p == scalar(@j)-1 ) {
$pro .= "$j[$p]";
} else {
$pro .= "$j[$p] ";
}
}
if (scalar(@s) > 2 ) {
for my $p ( 2 .. scalar(@s)-1 ) {
$pro .= ":$s[$p]";
}
}
push @neline, { datei => $file[scalar(@file)-1], user => $j[5], min => $j[0] =~ s/#//r , std => $j[1], day => $j[2], month => $j[3], monthday => $j[4], programm => $pro, server => $ser, status => $status };
}
}
}
} catch {
push @neline, { datei => '', user =>'', min => '', std => '', day => '', month => '', monthday => '', programm => 'error', server => $ser, status => '' };
};
}
}
# schreiben der neuen Daten in JSON Datei
write_file('sshcron.json', encode_json(\@neline) );
$daten = \@neline;
}
my %s;
for my $old ( @{$daten} ) {
if ( !$s{$old->{server}} ) {
$s{$old->{server}} = 1;
push @allserver, $old->{server};
}
}
# p $daten;
if ( $j->{new} && $j->{server} ) {
$c->render(json => { rc => 0, msg => 'OK' });
} else {
$c->render(template => 'jobs', da => $daten , server => \@allserver);
}
};
# Start the Mojolicious command system
app->start;
__DATA__
@@ index.html.ep
% layout 'index';
<div class="container-fluid">
<h3>zeigt, holt Cronjobs aus cron.d</h3>
<h5>/jobs/:upd|del/:server</h5>
</div>
@@ jobs.html.ep
% layout 'index';
<div class="container-fluid">
<div class="menu col-6 px-3">
<select class="form-control-sm server">
% for my $d ( @$server ) {
<option value="<%= $d %>"><%= $d %></option>
% }
</select>
<button id="refresh" class="btn btn-secondary fas fa-sync" type="button"></button>
<button id="del" class="btn bt-sm btn-secondary fas fa-trash" type="button"></button>
</div>
<table id="tbl" class="table table-striped table-bordered table-sm nowrap" style="width:100%">
<thead>
<tr>
<th>activ</th>
<th>server</th>
<th>min</th>
<th>hour</th>
<th>day</th>
<th>month</th>
<th>monthday</th>
<th>user</th>
<th>file</th>
<th>program</th>
</tr>
</thead>
<tbody>
% for my $d ( @{$da} ) {
<tr>
<td><%= $d->{status} %></td>
<td><%= $d->{server} %></td>
<td><%= $d->{min} %></td>
<td><%= $d->{std} %></td>
<td><%= $d->{day} %></td>
<td><%= $d->{month} %></td>
<td><%= $d->{monthday} %></td>
<td><%= $d->{user} %></td>
<td><%= $d->{datei} %></td>
<td><%= $d->{programm} %></td>
</tr>
%}
</tbody>
</table>
</div>
@@ layouts/index.html.ep
<!DOCTYPE html>
<html>
<head>
<title>MyApp</title>
% my $htlib = 'omv';
%= stylesheet "http://$htlib/htlib/bootstrap/4.3.1/css/bootstrap.min.css"
%= stylesheet "http://$htlib/htlib/fontawesome/5.7.2/css/all.css"
%= stylesheet "http://$htlib/htlib/jquery-datatables/1.10.19/css/dataTables.bootstrap4.min.css"
%= stylesheet "http://$htlib/htlib/jquery-datatables/extensions/Scroller/1.5.0/css/scroller.bootstrap4.min.css"
<style>
div.dataTables_wrapper div.dataTables_filter {
text-align: unset;
}
</style>
<!-- Jquery / Datatables -->
%= javascript "http://$htlib/htlib/jquery/jquery-3.3.1.js"
%= javascript "http://$htlib/htlib/bootstrap/4.3.1/js/bootstrap.bundle.min.js"
%= javascript "http://$htlib/htlib/jquery-datatables/1.10.19/js/jquery.dataTables.min.js"
%= javascript "http://$htlib/htlib/jquery-datatables/extensions/Scroller/1.5.0/js/dataTables.scroller.min.js"
</head>
<body>
<%= content %>
<script>
$(document).ready(function() {
$('#tbl').DataTable({
scrollY: '85vh',
deferRender: true,
scroller: true,
});
$('#tbl_filter > label').addClass('ml-auto pr-3');
$('#tbl_filter').addClass('row pt-3');
$('.menu').prependTo('#tbl_filter')
$('#del').on('click', function() {
var c = confirm('Einträge für Server löschen (JOBs werden NICHT auf dem Server gelöscht)');
if (c) {
$.post('/jobs/', JSON.stringify({ new: 'del', server: $('.server option:selected').val() }), function(){
location.reload();
} )
}
})
$('#refresh').on('click', function() {
$.post('/jobs/', JSON.stringify({ new: 'upd', server: $('.server option:selected').val() }), function(){
location.reload();
} )
})
});
</script>
</body>
</html>