AppleScript C Perl Shell Xcode Other

Run Time Machine from cron

Post Reply
coding / perl     Views: 609Prev .. Next
Run Time Machine from cronPosted: Wednesday, March 4, 2020 [14:50:10] - 1
rootPosted by:rootMember Since:
June 16 2010
Posts: 357
There are a few reasons to run Time Machine backup from cron.
- There are too many macs for one NAS/Time Capsule
- No need to backup too often
- You want to be in-control of backups
- It's just cool and because you can

Run Time Machine from cron

View Code#!/usr/bin/perl
## Copyright 2020 CodeMacs.Com
## Program to run Time Machine from cron
# Time Machine has to be setup properly before running this program and
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the "Software"),
# to deal in the Software without restriction, including without limitation
# the rights to use, copy, modify, merge, publish, distribute,
# copies of the Software, and to permit persons to whom the Software
# is furnished to do so, subject to the following conditions:

# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.

# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
# OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

use strict;
use warnings;
use POSIX qw(mktime);

open(STDOUT,">/path_to_folder/time.machine.result.txt");

## Check if Time Machine drive is available
my $host = `ping -c 1 -r -t 5 freenas.local`;print "$host\n";
unless($host =~ m/1 packets received/) {print "No Time Machine host present\n";exit(0);}
my %weekDays = ('Sun','Sunday','Mon','Monday','Tue','Tuesday','Wed','Wednesday','Thu','Thursday','Fri','Friday','Sat','Saturday');
my %allMonths = ('Jan','January','Feb','February','Mar','March','Apr','April','May','May','Jun','June',
'Jul','July','Aug','August','Sep','September','Oct','October','Nov','November','Dec','December');

# Full path to a program is a good practice - check it first with "which tmutil"
# Turn Auto Backup off
`/usr/bin/tmutil disable`; ## Comment it out if your TM is turned off
my $lastbk = `/usr/bin/tmutil latestbackup`; ## Check last backup
my $chkpr = 'backupd';my $foundit=''; ## Make sure backup is not running
open (IN, "ps axw |");
while (<IN>) {
if (/$chkpr/) {print "Backup was runnig\t$chkpr\n";$foundit = 1;last;}
} ## WHILE END
close IN;
if($foundit) {`/usr/bin/tmutil stopbackup`;print "Backup was stopped\n";sleep(15);}
else {print "No backup was running, so we can start it\n";}

## Now read the date when last backup was performed
$lastbk =~ s/\n|\r//g;my @prts = split(/\//,$lastbk);my $ldate = pop(@prts);@prts=();
my($ye,$mo,$da,$ti) = split(/\-/,$ldate);
$ti =~ s#(\d{2})(\d{2})(\d{2})##;my $hr=$1;my $min=$2;my $sec=$3;
my $unxlst = makeunix($mo,$da,$ye,$hr,$min,$sec); ## Get epoch date of the last backup
unless($unxlst) {$unxlst=1;} ## If no epoch time - assign 1 to it
my $tnow = time; ## Time now
my $lapsed = $tnow - $unxlst; ## Lapsed since last backup
unless($lapsed < 86400) {sendemail($lapsed,$unxlst); ## Report big gap in backup
} ## END IF LAPSED MORE THAN A DAY - SOMETHING WENT WRONG
else {
my $finaltime = localtime($unxlst);$finaltime =~ tr/ //s;my($wd,$mo,$da,$ti,$ye) = split(/\s/,$finaltime);
$mo = $allMonths{$mo};$wd = $weekDays{$wd};
print "Good previous backup.\nLast backup done on: $wd, $mo $da, $ye at $ti\n";
} ## END LAST BACKUP WAS GOOD

## Now, all checks are done - run the actual backup
my $program = '/usr/bin/tmutil startbackup';
print "Running the program\n$program\n";
exec "$program"; ## Perl program will exit at this point

sub makeunix { ##########
my($m,$mday,$y,$hour,$min,$sec)=@_;
unless($mday) {$mday = 1;}
my $mon = $m - 1;my $yr = $y - 1900;my $wday='';
my $timestamp = mktime($sec,$min,$hour,$mday,$mon,$yr,$wday,0,-1);
if($timestamp) {return $timestamp;} else {return;}
} ## END SUB FIND MONTH ##

sub sendemail { ##########
my $lapsed = shift;my $lastbk=shift;
my $ago = cnvrtsecs($lapsed);
my $sendmail = '/usr/sbin/sendmail -t -oi';
my $finaltime = localtime($lastbk);$finaltime =~ tr/ //s;my($wd,$mo,$da,$ti,$ye) = split(/\s/,$finaltime);
$mo = $allMonths{$mo};$wd = $weekDays{$wd};
open(MAIL,"|$sendmail");
print MAIL <<EOM;
From: time_machine\@your_mac.home\nTo: your_email\@your_domain.com\nSubject: TM Backup did not happen for more than a day on your Mac in a Living Room\n
Mac in a Living Room backup delay report
Last backup was finished: $ago ago on $wd, $mo $da, $ye at $ti
\nReported by /program_location/time.machine.cgi
EOM
close(MAIL);
print "Last backup was finished: $ago ago on $wd, $mo $da, $ye\n";
} ## END SUB SEND EMAIL ##

sub cnvrtsecs {
my $s=shift;
return sprintf "%02d seconds", $s if $s < 60;
my $m = $s / 60; $s = $s % 60;
return sprintf "%02d hours %02d seconds", $m, $s if $m < 60;
my $h = $m / 60; $m %= 60;
return sprintf "%02d hours %02d minutes %02d seconds", $h, $m, $s if $h < 24;
my $d = $h / 24; $h %= 24;
return sprintf "%d days %02d hours %02d minutes %02d seconds", $d, $h, $m, $s;
} ## END BACK TO MINUTES



Time Machine has to be set and initial backup finished prior to running this program.
This program has to be run as rootThere's no place like ~
Run Time Machine tmutil and cronPosted: Wednesday, March 4, 2020 [21:24:32] - 2
rootPosted by:rootMember Since:
June 16 2010
Posts: 357
On old Mac OS X (up to 10.8.5 verified) cron job can be set by editing a crontab file and adding the following line:
View Code20 1 * * * root /opt/local/bin/perl /your_program_folder/time.machine.cgi


where:
20 - minutes
1 - hour
so, program will run daily at 1:20AM
root - run under root user
/opt/local/bin/perl /your_program_folder/time.machine.cgi - command to run

------------

Newer Mac OS uses launchd replacing cron jobs.
You'd need to create a plist file and place it in /Library/LaunchDaemons folder.
plist file should be something like this:
View Code<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>com.time.machine.run</string>
<key>ProgramArguments</key>
<array>
<string>/opt/local/bin/perl</string>
<string>/your_program_folder/time.machine.cgi</string>
<string>sleep</string>
<string>10</string>
</array>
<key>StartCalendarInterval</key>
<dict>
<key>Minute</key>
<integer>00</integer>
<key>Hour</key>
<integer>21</integer>
</dict>
</dict>
</plist>


according to settings in plist file above, your Time Machine program will run daily at 9:00PM (21:00 hours).

plist file should be chown -ed to root:wheel
View Codesudo chown root:wheel /Library/LaunchDaemons/com.time.machine.run.plist


and then activated:
View Codesudo launchctl load /Library/LaunchDaemons/com.time.machine.run.plist


to unload it, just run:
View Codesudo launchctl unload /Library/LaunchDaemons/com.time.machine.run.plist


------

Tailor starting time to your needs when computer is not doing heavy jobs.
Another great feature of this program - if you set it on MacBook [Pro] laptop - it will not run when NAS or Time Capsule is not present.There's no place like ~
coding / perlPrev .. Next
 
Post Reply
Home - Coding: AppleScript C Perl Shell Xcode Other
Our Telegram Group