--- a/lib/SI/system.pm Wed Jan 20 21:52:01 2010 +0100
+++ b/lib/SI/system.pm Wed Jan 20 22:29:06 2010 +0100
@@ -10,10 +10,14 @@
sub id() {
- # hope it's eth* or wlan*
- local $_ = (sort grep { /^(eth|wlan)/ } `ifconfig -a`)[0];
- /^(?<dev>\S+)\s.*HWaddr\s+(?<mac>[\da-f:]+)\s*$/i
+ $_ = `ip link`;
+ s/\n\s+/ /g;
+ s/^\d+:\s*//mg;
+
+ (sort grep /^(eth|wlan)/, split /\n/, $_)[0]
+ =~ /link\/ether\s+(?<mac>\S+)/
and return $+{mac};
+
die "ERR: Can't get system identification (MAC address)\n";
}
--- a/si Wed Jan 20 21:52:01 2010 +0100
+++ b/si Wed Jan 20 22:29:06 2010 +0100
@@ -13,6 +13,7 @@
use Getopt::Long;
use File::Path;
use File::Basename;
+use Pod::Usage;
use lib "lib";
use SI::ptable;
@@ -23,33 +24,31 @@
use SI::tools;
use SI::system;
+my $opt_base = "..";
my $opt_exit = "";
-my $opt_dir = "";
MAIN: {
- my %id = (
- mac => SI::system::id,
- name => undef,
- );
-
GetOptions(
- "exit=s" => \$opt_exit,
- "dir=s" => \$opt_dir
- ) or die "Bad usage\n";
+ "exit=s" => \$opt_exit,
+ "b|base=s" => \$opt_base,
+ "h|help" => sub { pod2usage(-verbose => 1, -exit => 0) },
+ "m|man" => sub { pod2usage(-verbose => 2, -exit => 0) },
+ ) or pod2usage;
my %devices; # the overall data collector
- my $dir;
+ my $dir;
+
+ my $sys_id = SI::system::id; # mostly the MAC
+ my $sys_name;
- if ($opt_dir ne "") {
- $dir = $opt_dir;
- }
- else {
- $dir = dirname($0) . "/../image-$id{mac}";
- rmtree($dir);
- -d $dir or mkdir($dir, 0700) or die "Can't mkdir $dir: $!\n";
- }
+ $dir = "$opt_base/image-$sys_id";
+ $dir =~ s/\/+/\//g;
- mkpath(map { "$dir/$_" } qw(info ptable lvm blkid mbr dump));
+ rmtree($dir);
+ mkpath(map { "$dir/$_" } qw(info ptable lvm blkid mbr dump),
+ { verbose => 1 });
+
+ warn grep { -l && readlink =~ /\/.*-$sys_id$/ } glob("$opt_base");
SI::ptable::volumes("$dir/ptable/%s", %devices);
die Dumper \%devices if $opt_exit =~ /ptable/;
@@ -69,19 +68,17 @@
SI::system::fsck(%devices);
die Dumper \%devices if $opt_exit =~ /fsck/;
- $id{name} = SI::system::hostname(%devices);
- unlink("../image-$id{name}") if -l "../image-$id{name}";
- symlink(basename($dir), "../image-$id{name}");
+ # now we can retrieve the system name, first we had to
+ # check the devices
+ $sys_name = SI::system::hostname(%devices);
- print { new IO::File ">$dir/info/mac" } "$id{mac}\n";
- print { new IO::File ">$dir/info/name" } "$id{name}\n";
+ print { new IO::File ">$dir/info/mac" } "$sys_id\n";
+ print { new IO::File ">$dir/info/name" } "$sys_name\n";
print { new IO::File ">$dir/info/devices" } Dumper \%devices
or die "ERR: Can't open $dir/info/devices: $!\n";
SI::dumper::dump("$dir/dump/%s", %devices);
-
- # HACK ... fixme
- system("rmdir ../* 2>/dev/null");
+ symlink(basename($dir), "../image-$sys_name");
print { new IO::File ">$dir/done" } localtime() . "\n";
run("sync");
@@ -89,4 +86,43 @@
}
+=head1 NAME
+
+si - system imager
+
+=head1 SYNOPSIS
+
+ si [-b|--base-dir DIR]
+
+=head1 DESCRIPTION
+
+The B<si> tool tries its best to create a restorable system backup - but
+it is B<limited> to Linux filesystems and a simple LVM structure.
+
+(The restore tool currently does not exist.)
+
+=head1 OPTIONS
+
+=over
+
+=item B<-b>|B<--base-dir> I<DIR>
+
+Where to create the directories for saving the system. (default: ..)
+
+=back
+
+=head1 Operational Details
+
+B<si> saves the master boot record and the partition table (via C<sfdisk
+-d>) of any non-removeable hard disk. It analyzes an LVM setup and
+saves the volume manger configuration. And last but not least it dumps
+all ext* file systems.
+
+
+=head1 AUTHOR
+
+Heiko Schlittermann <hs@schlittermann.de>
+
+=cut
+
# vim:sts=4 sw=4 aw ai si: