rewrite modul and add extra logDir backup
This commit is contained in:
parent
3ac7e48592
commit
b0a134e779
242
98_backup.pm
242
98_backup.pm
@ -1,8 +1,7 @@
|
|||||||
################################################################
|
################################################################
|
||||||
# $Id: 98_backup.pm 18643 2019-02-19 14:33:01Z CoolTux $
|
# Developed with Kate
|
||||||
# vim: ts=2:et
|
|
||||||
#
|
#
|
||||||
# (c) 2012 Copyright: Martin Fischer (m_fischer at gmx dot de)
|
# (c) 2012-2019 Copyright: Martin Fischer (m_fischer at gmx dot de)
|
||||||
# Maintained by Marko Oldenburg since 2019
|
# Maintained by Marko Oldenburg since 2019
|
||||||
# All rights reserved
|
# All rights reserved
|
||||||
#
|
#
|
||||||
@ -21,89 +20,123 @@
|
|||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
# GNU General Public License for more details.
|
# GNU General Public License for more details.
|
||||||
#
|
#
|
||||||
|
#
|
||||||
|
# $Id$
|
||||||
|
#
|
||||||
################################################################
|
################################################################
|
||||||
|
|
||||||
package main;
|
package main;
|
||||||
use strict;
|
use strict;
|
||||||
use warnings;
|
use warnings;
|
||||||
|
use FHEM::Meta;
|
||||||
|
|
||||||
sub CommandBackup($$);
|
#####################################
|
||||||
sub parseConfig($);
|
sub backup_Initialize($$) {
|
||||||
sub readModpath($$);
|
my %hash = ( Fn => 'FHEM::backup::CommandBackup',
|
||||||
sub createArchiv($$$);
|
Hlp => ',create a backup of fhem configuration, state and modpath' );
|
||||||
|
$cmds{backup} = \%hash;
|
||||||
|
|
||||||
|
return FHEM::Meta::InitMod( __FILE__, \%hash );
|
||||||
|
}
|
||||||
|
|
||||||
|
######################################
|
||||||
|
## unserer packagename
|
||||||
|
package FHEM::backup;
|
||||||
|
|
||||||
|
use strict;
|
||||||
|
use warnings;
|
||||||
|
use FHEM::Meta;
|
||||||
|
|
||||||
|
use GPUtils qw(GP_Import)
|
||||||
|
; # wird für den Import der FHEM Funktionen aus der fhem.pl benötigt
|
||||||
|
|
||||||
|
## Import der FHEM Funktionen
|
||||||
|
BEGIN {
|
||||||
|
GP_Import(
|
||||||
|
qw(AttrVal
|
||||||
|
gettimeofday
|
||||||
|
ResolveDateWildcards
|
||||||
|
attr
|
||||||
|
Log
|
||||||
|
fhemForked
|
||||||
|
defs
|
||||||
|
configDBUsed
|
||||||
|
TimeNow
|
||||||
|
BC_searchTelnet
|
||||||
|
BC_telnetDevice
|
||||||
|
DoTrigger)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
my @pathname;
|
my @pathname;
|
||||||
|
|
||||||
#####################################
|
sub CommandBackup($$) {
|
||||||
sub
|
|
||||||
backup_Initialize($$)
|
|
||||||
{
|
|
||||||
my %hash = ( Fn => "CommandBackup",
|
|
||||||
Hlp => ",create a backup of fhem configuration, state and modpath" );
|
|
||||||
$cmds{backup} = \%hash;
|
|
||||||
}
|
|
||||||
|
|
||||||
#####################################
|
|
||||||
sub
|
|
||||||
CommandBackup($$)
|
|
||||||
{
|
|
||||||
my ($cl, $param) = @_;
|
my ($cl, $param) = @_;
|
||||||
|
|
||||||
my $byUpdate = ($param && $param eq "startedByUpdate");
|
my $byUpdate = ($param && $param eq 'startedByUpdate');
|
||||||
my $modpath = AttrVal("global", "modpath","");
|
my $modpath = AttrVal('global', 'modpath', '');
|
||||||
my $configfile = AttrVal("global", "configfile", "");
|
my $configfile = AttrVal('global', 'configfile', '');
|
||||||
my $statefile = AttrVal("global", "statefile", "");
|
my $statefile = AttrVal('global', 'statefile', '');
|
||||||
|
my $logDir = AttrVal('global', 'logdir', 'none');
|
||||||
my $now = gettimeofday();
|
my $now = gettimeofday();
|
||||||
my @t = localtime($now);
|
my @t = localtime($now);
|
||||||
$statefile = ResolveDateWildcards($statefile, @t);
|
$statefile = ResolveDateWildcards($statefile, @t);
|
||||||
|
|
||||||
# prevent duplicate entries in backup list for default config, forum #54826
|
# prevent duplicate entries in backup list for default config, forum #54826
|
||||||
$configfile = '' if ($configfile eq 'fhem.cfg' || configDBUsed());
|
$configfile = '' if ($configfile eq 'fhem.cfg' || configDBUsed());
|
||||||
$statefile = '' if ($statefile eq "./log/fhem.save");
|
$statefile = '' if ($statefile eq './log/fhem.save');
|
||||||
my $msg;
|
my $msg;
|
||||||
my $ret;
|
my $ret;
|
||||||
|
|
||||||
Log 1, "NOTE: make sure you have a database backup!" if(configDBUsed());
|
Log(1, 'NOTE: make sure you have a database backup!') if(configDBUsed());
|
||||||
|
|
||||||
# set backupdir
|
# set backupdir
|
||||||
my $backupdir;
|
my $backupdir;
|
||||||
if (!defined($attr{global}{backupdir})) {
|
if (!defined($attr{global}{backupdir})) {
|
||||||
$backupdir = "$modpath/backup";
|
$backupdir = $modpath . '/backup';
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
if ($attr{global}{backupdir} =~ m/^\/.*/) {
|
if ($attr{global}{backupdir} =~ m/^\/.*/) {
|
||||||
$backupdir = $attr{global}{backupdir};
|
$backupdir = $attr{global}{backupdir};
|
||||||
} elsif ($attr{global}{backupdir} =~ m/^\.+\/.*/) {
|
}
|
||||||
$backupdir = "$modpath/$attr{global}{backupdir}";
|
elsif ($attr{global}{backupdir} =~ m/^\.+\/.*/) {
|
||||||
} else {
|
$backupdir = $modpath . '/' . $attr{global}{backupdir};
|
||||||
$backupdir = "$modpath/$attr{global}{backupdir}";
|
}
|
||||||
|
else {
|
||||||
|
$backupdir = $modpath . '/' . $attr{global}{backupdir};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
# create backupdir if not exists
|
# create backupdir if not exists
|
||||||
if (!-d $backupdir) {
|
if (!-d $backupdir) {
|
||||||
Log 4, "backup create backupdir: '$backupdir'";
|
Log(4, 'backup create backupdir: ' . $backupdir);
|
||||||
$ret = `(mkdir -p $backupdir) 2>&1`;
|
$ret = `(mkdir -p $backupdir) 2>&1`;
|
||||||
if ($ret) {
|
if ($ret) {
|
||||||
chomp $ret;
|
chomp($ret);
|
||||||
$msg = "backup: $ret";
|
$msg = 'backup: ' . $ret;
|
||||||
return $msg;
|
return $msg;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(configDBUsed()) {
|
if(configDBUsed()) {
|
||||||
# add configDB configuration file
|
# add configDB configuration file
|
||||||
push @pathname, 'configDB.conf';
|
push(@pathname, 'configDB.conf');
|
||||||
Log 4, "backup include: 'configDB.conf'";
|
Log(4, 'backup include: \'configDB.conf\'');
|
||||||
} else {
|
|
||||||
# get pathnames to archiv
|
|
||||||
push @pathname, $configfile if($configfile);
|
|
||||||
Log 4, "backup include: '$configfile'";
|
|
||||||
$ret = parseConfig($configfile);
|
|
||||||
push @pathname, $statefile if($statefile);
|
|
||||||
Log 4, "backup include: '$statefile'";
|
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
# get pathnames to archiv
|
||||||
|
push(@pathname, $configfile) if($configfile);
|
||||||
|
Log(4, 'backup include: ' . $configfile);
|
||||||
|
$ret = parseConfig($configfile);
|
||||||
|
push(@pathname, $statefile) if($statefile);
|
||||||
|
Log(4, 'backup include: ' . $statefile);
|
||||||
|
}
|
||||||
|
|
||||||
$ret = readModpath($modpath,$backupdir);
|
$ret = readModpath($modpath,$backupdir);
|
||||||
|
|
||||||
|
## add extra logdir path to backup
|
||||||
|
push(@pathname, $logDir) if($logDir ne 'none');
|
||||||
|
|
||||||
# create archiv
|
# create archiv
|
||||||
$ret = createArchiv($backupdir, $cl, $byUpdate);
|
$ret = createArchiv($backupdir, $cl, $byUpdate);
|
||||||
|
|
||||||
@ -113,9 +146,9 @@ CommandBackup($$)
|
|||||||
return $ret;
|
return $ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
sub
|
sub parseConfig($);
|
||||||
parseConfig($)
|
|
||||||
{
|
sub parseConfig($) {
|
||||||
my $configfile = shift;
|
my $configfile = shift;
|
||||||
# we need default value to read included files
|
# we need default value to read included files
|
||||||
$configfile = $configfile ? $configfile : 'fhem.cfg';
|
$configfile = $configfile ? $configfile : 'fhem.cfg';
|
||||||
@ -124,8 +157,8 @@ parseConfig($)
|
|||||||
my $ret;
|
my $ret;
|
||||||
|
|
||||||
if (!open($fh,$configfile)) {
|
if (!open($fh,$configfile)) {
|
||||||
$msg = "Can't open $configfile: $!";
|
$msg = 'Can\'t open ' . $configfile . ': ' . $!;
|
||||||
Log 1, "backup $msg";
|
Log(1, 'backup ' . $msg);
|
||||||
return $msg;
|
return $msg;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -134,47 +167,48 @@ parseConfig($)
|
|||||||
if ($l =~ m/^\s*include\s+(\S+)\s*.*$/) {
|
if ($l =~ m/^\s*include\s+(\S+)\s*.*$/) {
|
||||||
if (-e $1) {
|
if (-e $1) {
|
||||||
push @pathname, $1;
|
push @pathname, $1;
|
||||||
Log 4, "backup include: '$1'";
|
Log(4, 'backup include: ' . $1);
|
||||||
$ret = parseConfig($1);
|
$ret = parseConfig($1);
|
||||||
} else {
|
}
|
||||||
Log 1, "backup configfile: '$1' does not exists! File not included."
|
else {
|
||||||
|
Log(1, 'backup configfile: ' . $1 . ' does not exists! File not included.');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
close $fh;
|
close $fh;
|
||||||
return $ret;
|
return $ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
sub
|
sub readModpath($$) {
|
||||||
readModpath($$)
|
|
||||||
{
|
|
||||||
my ($modpath,$backupdir) = @_;
|
my ($modpath,$backupdir) = @_;
|
||||||
my $msg;
|
my $msg;
|
||||||
my $ret;
|
my $ret;
|
||||||
|
|
||||||
if (!opendir(DH, $modpath)) {
|
if (!opendir(DH, $modpath)) {
|
||||||
$msg = "Can't open $modpath: $!";
|
$msg = 'Can\'t open $modpath: ' . $!;
|
||||||
Log 1, "backup $msg";
|
Log(1, 'backup ' . $msg);
|
||||||
return $msg;
|
return $msg;
|
||||||
}
|
}
|
||||||
|
|
||||||
my @files = <$modpath/*>;
|
my @files = <$modpath/*>;
|
||||||
foreach my $file (@files) {
|
foreach my $file (@files) {
|
||||||
if ($file eq $backupdir && (-d $file || -l $file)) {
|
if ($file eq $backupdir && (-d $file || -l $file)) {
|
||||||
Log 4, "backup exclude: '$file'";
|
Log(4, 'backup exclude: ' . $file);
|
||||||
} else {
|
}
|
||||||
Log 4, "backup include: '$file'";
|
else {
|
||||||
|
Log(4, 'backup include: ' . $file);
|
||||||
push @pathname, $file;
|
push @pathname, $file;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return $ret;
|
return $ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
sub
|
sub createArchiv($$$) {
|
||||||
createArchiv($$$)
|
|
||||||
{
|
|
||||||
my ($backupdir,$cl,$byUpdate) = @_;
|
my ($backupdir,$cl,$byUpdate) = @_;
|
||||||
my $backupcmd = (!defined($attr{global}{backupcmd}) ? undef : $attr{global}{backupcmd});
|
my $backupcmd = (!defined($attr{global}{backupcmd}) ? undef : $attr{global}{backupcmd});
|
||||||
my $symlink = (!defined($attr{global}{backupsymlink}) ? "no" : $attr{global}{backupsymlink});
|
my $symlink = (!defined($attr{global}{backupsymlink}) ? 'no' : $attr{global}{backupsymlink});
|
||||||
my $tarOpts;
|
my $tarOpts;
|
||||||
my $msg;
|
my $msg;
|
||||||
my $ret;
|
my $ret;
|
||||||
@ -183,48 +217,53 @@ createArchiv($$$)
|
|||||||
$dateTime =~ s/ /_/g;
|
$dateTime =~ s/ /_/g;
|
||||||
$dateTime =~ s/(:|-)//g;
|
$dateTime =~ s/(:|-)//g;
|
||||||
|
|
||||||
my $pathlist = join( "\" \"", @pathname );
|
my $pathlist = join( '" "', @pathname );
|
||||||
|
|
||||||
my $cmd="";
|
my $cmd='';
|
||||||
if (!defined($backupcmd)) {
|
if (!defined($backupcmd)) {
|
||||||
if (lc($symlink) eq "no") {
|
if (lc($symlink) eq 'no') {
|
||||||
$tarOpts = "cf";
|
$tarOpts = 'cf';
|
||||||
} else {
|
}
|
||||||
$tarOpts = "chf";
|
else {
|
||||||
|
$tarOpts = 'chf';
|
||||||
}
|
}
|
||||||
|
|
||||||
# prevents tar's output of "Removing leading /" and return total bytes of
|
# prevents tar's output of "Removing leading /" and return total bytes of
|
||||||
# archive
|
# archive
|
||||||
$cmd = "tar -$tarOpts - \"$pathlist\" |gzip > $backupdir/FHEM-$dateTime.tar.gz";
|
# $cmd = "tar -$tarOpts - \"$pathlist\" |gzip > $backupdir/FHEM-$dateTime.tar.gz";
|
||||||
|
$cmd = "tar $tarOpts $backupdir/FHEM-$dateTime.tar.gz \"$pathlist\"";
|
||||||
} else {
|
|
||||||
$cmd = "$backupcmd \"$pathlist\"";
|
|
||||||
|
|
||||||
}
|
}
|
||||||
Log 2, "Backup with command: $cmd";
|
else {
|
||||||
|
$cmd = $backupcmd . ' \"' . $pathlist . '\"';
|
||||||
|
}
|
||||||
|
|
||||||
|
Log(2, 'Backup with command: ' . $cmd);
|
||||||
if(!$fhemForked && !$byUpdate) {
|
if(!$fhemForked && !$byUpdate) {
|
||||||
use Blocking;
|
use Blocking;
|
||||||
our $BC_telnetDevice;
|
our $BC_telnetDevice;
|
||||||
BC_searchTelnet("backup");
|
BC_searchTelnet('backup');
|
||||||
my $tp = $defs{$BC_telnetDevice}{PORT};
|
my $tp = $defs{$BC_telnetDevice}{PORT};
|
||||||
|
|
||||||
system("($cmd; echo Backup done;".
|
system("($cmd; echo Backup done;".
|
||||||
"$^X $0 localhost:$tp 'trigger global backup done')2>&1 &");
|
"$^X $0 localhost:$tp 'trigger global backup done')2>&1 &");
|
||||||
return "Started the backup in the background, watch the log for details";
|
return "Started the backup in the background, watch the log for details";
|
||||||
}
|
}
|
||||||
|
|
||||||
$ret = `($cmd) 2>&1`;
|
$ret = `($cmd) 2>&1`;
|
||||||
|
|
||||||
if($ret) {
|
if($ret) {
|
||||||
chomp $ret;
|
chomp $ret;
|
||||||
Log 1, "backup $ret";
|
Log(1, 'backup ' . $ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!defined($backupcmd) && -e "$backupdir/FHEM-$dateTime.tar.gz") {
|
if (!defined($backupcmd) && -e "$backupdir/FHEM-$dateTime.tar.gz") {
|
||||||
my $size = -s "$backupdir/FHEM-$dateTime.tar.gz";
|
my $size = -s "$backupdir/FHEM-$dateTime.tar.gz";
|
||||||
$msg = "backup done: FHEM-$dateTime.tar.gz ($size Bytes)";
|
$msg = "backup done: FHEM-$dateTime.tar.gz ($size Bytes)";
|
||||||
DoTrigger("global", $msg);
|
DoTrigger('global', $msg);
|
||||||
Log 1, $msg;
|
Log(1, $msg);
|
||||||
$ret .= "\n".$msg;
|
$ret .= "\n".$msg;
|
||||||
}
|
}
|
||||||
|
|
||||||
return $ret;
|
return $ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -260,6 +299,47 @@ createArchiv($$$)
|
|||||||
<br>
|
<br>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
|
|
||||||
=end html
|
=end html
|
||||||
|
|
||||||
|
=for :application/json;q=META.json 98_backup.pm
|
||||||
|
{
|
||||||
|
"abstract": "Modul to retrieves apt information about Debian update state",
|
||||||
|
"x_lang": {
|
||||||
|
"de": {
|
||||||
|
"abstract": "Modul um apt Updateinformationen von Debian Systemen zu bekommen"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"keywords": [
|
||||||
|
"fhem-mod-device",
|
||||||
|
"fhem-core",
|
||||||
|
"backup",
|
||||||
|
"tar"
|
||||||
|
],
|
||||||
|
"release_status": "stable",
|
||||||
|
"license": "GPL_2",
|
||||||
|
"author": [
|
||||||
|
"Marko Oldenburg <leongaultier@gmail.com>"
|
||||||
|
],
|
||||||
|
"x_fhem_maintainer": [
|
||||||
|
"CoolTux"
|
||||||
|
],
|
||||||
|
"x_fhem_maintainer_github": [
|
||||||
|
"LeonGaultier"
|
||||||
|
],
|
||||||
|
"prereqs": {
|
||||||
|
"runtime": {
|
||||||
|
"requires": {
|
||||||
|
"FHEM": 5.00918799,
|
||||||
|
"perl": 5.016,
|
||||||
|
"Meta": 0
|
||||||
|
},
|
||||||
|
"recommends": {
|
||||||
|
},
|
||||||
|
"suggests": {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
=end :application/json;q=META.json
|
||||||
|
|
||||||
=cut
|
=cut
|
||||||
|
Loading…
x
Reference in New Issue
Block a user