++ to those who recommended cpanm - it's one of the first things I install on a Pi. SD cards have a limited life - about 1K writes before things start to fail (they can usually handle small failing areas). All my production Pis therefore have a second SD card on a USB adapter. The following code is on them all & run whenever I make a material change. This means that I can swap the card immediately whenever one dies.
#!/usr/bin/perl
use strict;
use warnings;
use feature 'say';
use constant DEBUG => 0;
my %tree;
my @tree = split(/\n/, `lsblk -bnlo NAME,SIZE,MOUNTPOINT`);
for (@tree) {
my ($key, $size, $mount) = (split(/\s+/, $_));
$key =~ s/\d.*//;
if ($key =~ m/^sd*/ or $key eq 'mmcblk') {
$tree{$key}{'mount'} = $mount;
$tree{$key}{'size'} = $size unless defined $tree{$key}{'size'
+};
}
}
my $target;
use Data::Dumper; print Dumper %tree if DEBUG;
for (keys %tree) {
if ('' eq $tree{$_}{'mount'}) {
$target = $_;
last;
}
}
die 'No target found!' unless $target;
my $cmd = "sudo dd if=/dev/mmcblk0 of=/dev/$target bs=1M";
say $cmd if DEBUG;
if ($tree{$target}{'size'} >= $tree{'mmcblk'}{'size'}) {
say 'Backing up - target large enough.';
} else {
die "Can't back up with source larger than target.";
}
exec $cmd unless DEBUG;
=pod
=head1 NAME AND SYNOPSIS
sdbackup.pl
=head1 DESCRIPTION
This is a standalone programme to be invoked manually. It is
written for a Raspberry Pi with a second SD card attached via
a USB adaptor. On the original target, dns, there is a thumb
drive mounted for logging. The code is therefore designed to
look for an unmounted device on one of the "sd" interfaces. If
such a device is found, the main SD card will be copied to it
unless the target is smaller than the source. The backup will
take roughly 1.2 minutes per meg. It will back up to the
first unmounted attached block device that appears in the
hash created from the 'lsblk' command. If there are two or
more unmounted devices, the target may not be predictable.
=head2 Constants
The only constant is DEBUG. If this is set to a value Perl
treats as true, no backup will be performed and a hash will
dumped before the command candidate is printed. Otherwise the
backup will be started unless the target is smaller than the
source.
=head2 Constraints
The code relies on the behaviour of 'lsblk' and in particular
its property of listing the block device before the partitions.
It also relies on the name of the mounted SD card starting
with 'mmcblk' followed by a digit. If there is more than one
such device, behaviour may be unpredictable.
=head2 lsblk parameters
=over
* b - Show device sizes in bytes.
* n - No headings
* l - Use list format
* o - Output the columns in the list that follows.
=back
=cut
Regards,
John Davies