Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #!/usr/bin/perl -w
- use strict;
- use warnings;
- use subs qw/cmd Save_World Backup_World generateSymlink/;
- my %Reports; #For future use.
- $|=1; # Don't change this.
- # PURE-PERL
- # Backup script written by Mash of MCPub.org. This script is released under the
- # GPL providing this notice, my alias and website remain unchanged in this source.
- # Feel free to distribute but please post back any bugfixes or changes to the
- # source as it may be of use for others.
- #
- # DONATIONS ARE WELCOME! SEE WEBSITE -> -- Mash - MCPub.org
- #
- #-> Leaving a _message option blank("") will disable the message entirely. :)
- my %Config = (
- "username" => "odminecraft",
- "chown_to_user" => "odminecraft",
- "chown_to_group" => "odminecraft",
- "mc_dir" => "/home/odminecraft/minecraft-test/",
- "worlds" => ["world", "world_nether"],
- "backup_dir" => "/home/odminecraft/minecraft-test/backups/",
- "max_backups" => 72,
- "say_command" => "broadcast",
- "saving_message" => "Beginning World Save",
- "backup_message" => "",
- "backup_end_message" => "",
- # To disable any of the options below, set them to 'undef'
- # (without 's) not 0 or wonky things COULD possibly happen.
- "multiworld" => 1,
- "skip_counter" => undef, #any valid number, 1, 2, 5, 30, etc.
- "save" => 1,
- "backup" => 1,
- "symlink" => 1,
- "report_stats" => 1,
- "perworld_reports" => 1,
- # Options below are unchangable. Please, please do not change them.
- "mpsay_installed" => undef, #Determined automatically for safety
- "chown_uid_gid" => [], #Determined automatically for safety
- );
- ################################################################################
- ################## NON-USER EDITABLE CODE :: SUBROUTINES #######################
- ################################################################################
- #-> Before we process ANYTHING, we make sure symlinking is supported by the OS
- #-> and determine the UID and GID of the user we're chowning files away to
- my $symsupport = eval { symlink("",""); 1 };
- $Config{'symlink'} = undef unless $symsupport;
- if (($Config{'chown_to_user'} ne "") && ($Config{'chown_to_group'} ne "")){
- my $uid = getpwnam($Config{'chown_to_user'});
- my $gid = getgrnam($Config{'chown_to_group'});
- $Config{'chown_uid_gid'} = [$uid, $gid];
- }
- &MCPubMPSay();
- &checkSkip();
- &doWork();
- sub doWork { #Doing it this way so it calls save-all once, but multiple backups
- Save_World if $Config{'save'};
- return unless $Config{'backup'};
- cmd("save-off");
- select(undef,undef,undef,0.5);
- my @worldList = @{$Config{'worlds'}};
- for (@worldList){
- next unless -d "$Config{'mc_dir'}$_";
- Backup_World($_);
- }
- cmd("save-on");
- do {
- cmd("$Config{'say_command'} " . $Config{'backup_end_message'}) if $Config{'backup_end_message'} ne "";
- } unless (($Config{'perworld_reports'}) && ($Config{'mpsay_installed'}));
- }
- sub Save_World { # stupidly simple.. Almost a waste to do it at all lol ;)
- cmd("$Config{'say_command'} $Config{'saving_message'}") if $Config{'saving_message'} ne "";
- cmd("save-all");
- }
- #-> Complicating the fuck out of this subroutine because I don't want
- #-> multiple routines that essentially do the same thing. Making this
- #-> deterministic and sequential. (Also added directory creating in
- #-> the off chance users didn't create their own backup directories.)
- sub Backup_World {
- my $worldName = $_[0];
- $worldName = "world" unless $worldName ne "";
- my $startTime = time;
- my $counter=0;
- my $f=undef;
- my @FileList;
- if (!-d "$Config{'backup_dir'}"){mkdir($Config{'backup_dir'});$f=1;}
- if (!-d "$Config{'backup_dir'}$worldName") {mkdir("$Config{'backup_dir'}$worldName", "0777");$f=1;}
- if ($f){ die "BAD USER, NO BISCUIT! D:<\n"; }
- if (($Config{'multiworld'}) && ($worldName ne "")){
- if ($Config{'mpsay_installed'}){
- cmd("mpsay $worldName $Config{'backup_message'}") if $Config{'backup_message'} ne "";
- } else {
- cmd("$Config{'say_command'} $Config{'backup_message'} ($worldName)") if $Config{'backup_message'} ne "";
- }
- opendir(MC, "$Config{'backup_dir'}$worldName/") || die "Failed to open '$Config{'backup_dir'}$worldName'\n";
- @FileList = grep { /\.tar\.gz$/i && -f "$Config{'backup_dir'}$worldName/$_" } readdir(MC);
- } else {
- opendir(MC, "$Config{'backup_dir'}$worldName/") || die "Failed to open '$Config{'backup_dir'}'\n";
- @FileList = grep { /\.tar\.gz$/i && -f "$Config{'backup_dir'}$worldName/$_" } readdir(MC);
- cmd("$Config{'say_command'} $Config{'backup_message'} ($worldName)") if $Config{'backup_message'} ne "";
- }
- closedir(MC);
- my $numBackups = scalar @FileList;
- if (($numBackups >= $Config{'max_backups'}) && ($numBackups > 0)) {
- my $dif = $numBackups - $Config{'max_backups'};
- for (0 .. $dif){
- unlink("$Config{'backup_dir'}$worldName/$FileList[$_]");
- }
- }
- my $timestamp = &get_timestamp();
- my $backup_file = $Config{'backup_dir'} . $worldName . "/" . $timestamp . ".tar.gz";
- open(COMMAND, "tar -cvzf $backup_file $Config{'mc_dir'}$worldName/* |");
- $counter++ while <COMMAND>;
- close(COMMAND);
- system("chown $Config{'chown_to_user'}" . ":" . $Config{'chown_to_group'} . " " . $backup_file);
- generateSymlink($worldName, $backup_file);
- &generate_report($counter, $backup_file, $startTime, $worldName) if $Config{'report_stats'};
- if (($Config{'mpsay_installed'}) && ($Config{'perworld_reports'})){
- cmd("mpsay $worldName $Config{'backup_end_message'}") if $Config{'backup_end_message'} ne "";
- }
- }
- sub get_timestamp {
- my ($sec,$min,$hour,$mday,$mon,$year) = (localtime(time))[0..5];
- $year += 1900;
- return "$year\_$mon\_$mday\_-_$hour\.$min\.$sec";
- }
- sub MCPubMPSay {
- opendir(PLUGS, "$Config{'mc_dir'}plugins/") || die "Can't read plugins directory\n";
- my @f = grep { /^mpsay.jar$/i && -f "$Config{'mc_dir'}plugins/$_" } readdir(PLUGS);
- closedir(PLUGS);
- if (($f[0]) && ($f[0] ne "")) {
- my ($t) = (caller(0))[4];
- $Config{'mpsay_installed'} = substr($t, 0, 5);
- } else {
- $Config{'mpsay_installed'} = undef;
- }
- }
- sub generate_report {
- my ($numFilesArchived, $backup_file, $startTime, $worldName) = @_;
- my $elapsedTime = time - $startTime;
- my ($outMin,$outSec) = (gmtime($elapsedTime))[1,0];
- $elapsedTime = "$outMin\:$outSec";
- my $backupFileSizeDirty = -s $backup_file;
- my $backupFileSize = $backupFileSizeDirty / (1024 * 1024);
- my $formattedSize;
- ($formattedSize = sprintf("%.2f", $backupFileSize)) =~ s/\G(\d{1,3})(?=(?:\d\d\d)+(?:\.|$))/$1,/g;
- if (($Config{'mpsay_installed'}) && ($Config{'perworld_reports'})){
- cmd("mpsay $worldName Backed up $numFilesArchived files ($formattedSize MB in $elapsedTime)");
- } else {
- cmd("$Config{'say_command'} Backed up \'$worldName\' - $numFilesArchived files ($formattedSize MB in $elapsedTime)");
- }
- }
- sub cmd {
- my $CMD = $_[0];
- system("su -c \"screen -p 0 -S $Config{'username'} -X eval 'stuff \\\"$CMD\\\"\015'\" $Config{'username'}");
- }
- sub checkSkip {
- my $skipFlag = 1;
- if (!$Config{'skip_counter'}){
- unlink($Config{'mc_dir'}."$Config{'mpsay_installed'}")
- if -e $Config{'mc_dir'}."$Config{'mpsay_installed'}";
- undef($skipFlag);
- } else {
- if (!-e "$Config{'mc_dir'}$Config{'mpsay_installed'}"){
- open(C, ">$Config{'mc_dir'}$Config{'mpsay_installed'}");
- print C "0";
- close(C);
- return;
- }
- open(C, "$Config{'mc_dir'}$Config{'mpsay_installed'}");
- chomp(my $cn = <C>); close C;
- if ($cn =~ m/^(\d+)$/g){
- unlink("$Config{'mc_dir'}$Config{'mpsay_installed'}");
- open C, ">$Config{'mc_dir'}$Config{'mpsay_installed'}";
- print C "0"; close C;
- }
- open C, "+<", "$Config{'mc_dir'}$Config{'mpsay_installed'}";
- if ($cn >= $Config{'skip_counter'}){
- $cn = 0;
- print C $cn;
- undef($skipFlag);
- } else {
- $cn++;
- print C $cn;
- }
- close C;
- }
- exit if $skipFlag;
- }
- sub generateSymlink {
- my($w,$f) = @_;
- symlink "$f", "$Config{'mc_dir'}$w.backup.tar.gz" || die "Failed to create symlink\n";
- my @list = ("$Config{'mc_dir'}$w.backup.tar.gz");
- system("chown $Config{'chown_to_user'}" . ":" . $Config{'chown_to_group'} . " " . "$Config{'mc_dir'}$w.backup.tar.gz");
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement