400
403
return strftime("%y%m%d %H:%M:%S", localtime());
405
# Die subroutine kills all child processes and exits this process.
406
# This subroutine takes the same argument as the built-in die function.
408
# message string which is printed to stdout
413
# kill all child processes of this process
414
kill_child_processes();
416
die "$prefix Error: $message";
407
# Global initialization:
408
# 1. Override the 'die' builtin to customize the format of error messages
410
# 2. Setup signal handlers to terminate gracefully on fatal signals
413
*CORE::GLOBAL::die = sub {
415
print STDERR "$prefix Error: @_";
417
# Mimic the default 'die' behavior: append information about the caller
418
# and the new line, if the argument does not already end with a newline
419
if ($_[-1] !~ m(\n$)) {
420
my ($pkg, $file, $line) = caller 0;
422
print STDERR " at $file line $line.\n";
428
foreach ('HUP', 'INT', 'QUIT', 'ABRT', 'PIPE', 'TERM', 'XFSZ') {
429
$SIG{$_} = \&catch_fatal_signal;
434
# Make sure all child processes are killed on exit. This doesn't cover cases
435
# when innobackupex is terminated with a signal.
438
# We only want to execute this in the parent script process, and ignore
439
# for all child processes it may spawn
440
if ($$ == $innobackupex_pid) {
441
kill_child_processes();
446
# kill child processes spawned by the script
448
sub kill_child_processes {
450
kill($kill_signal, $ibbackup_pid);
451
wait_for_ibbackup_finish();
456
sub catch_fatal_signal {
457
# Don't print anything if a child process is terminated with a signal
458
if ($$ == $innobackupex_pid) {
459
die "Terminated with SIG$_[0]"
420
464
# Finds all files that match the given pattern recursively beneath
421
465
# the given directory. Returns a list of files with their paths relative
464
508
} elsif ($mode == 2) {
465
509
$file_cmd = "qpress -do " . $file . " > " . $dest_file;
467
Die("Unknown decrypt_decompress mode : $mode\n");
511
die "Unknown decrypt_decompress mode : $mode";
469
513
print STDERR "$prefix $file_cmd\n";
470
system("$file_cmd") && Die "$file_cmd failed with $!\n";
514
system("$file_cmd") && die "$file_cmd failed with $!";
471
515
system("rm -f $file");
547
591
if ($status == $pids[$freepidindex]) {
548
592
my $childretcode = $? >> 8;
549
593
if ($childretcode != 0) {
550
Die("Child failed on $workingfiles[$freepidindex] : $childretcode");
594
die "Child failed on $workingfiles[$freepidindex] : $childretcode";
553
597
} elsif ($status == -1) {
554
Die("waitpid failed on $workingfiles[$freepidindex] : $status");
598
die "waitpid failed on $workingfiles[$freepidindex] : $status";
557
601
# couldn't find a free slot yet so sleep for 1/10 th of a second or so.
581
625
my $childretcode = $? >> 8;
582
626
if ($status == $pids[$freepidindex]) {
583
627
if ($childretcode != 0) {
584
Die("Child failed on $workingfiles[$freepidindex] : $childretcode");
628
die "Child failed on $workingfiles[$freepidindex] : $childretcode";
587
Die("waitpid failed on $workingfiles[$freepidindex] : $status");
631
die "waitpid failed on $workingfiles[$freepidindex] : $status";
851
895
# Create the directory in the destination if necessary
852
896
if (! -e "$dst_path") {
853
897
print STDERR "$prefix Creating directory '$dst_path'\n";
854
mkdir "$dst_path" or Die "mkdir failed: $!";
898
mkdir "$dst_path" or die "mkdir failed: $!";
855
899
} elsif (! -d "$dst_path") {
856
Die "$dst_path exists, but is not a directory";
900
die "$dst_path exists, but is not a directory";
859
903
# Don't overwrite files unless $copy_dir_overwrite is 1
860
904
if (!$copy_dir_overwrite && -e "$copy_dir_dst/$_") {
861
Die "Failed to process file $File::Find::name: " .
905
die "Failed to process file $File::Find::name: " .
862
906
"not overwriting file $copy_dir_dst/$_";
1043
1087
"Original undo directory");
1046
# check that the original options file and the backup options file have
1047
# the same value for "innodb_data_file_path" option
1048
#$backup_innodb_data_file_path =
1049
# get_option(\%backup_config, 'mysqld', 'innodb_data_file_path');
1050
#if (!are_equal_innodb_data_file_paths($orig_innodb_data_file_path,
1051
# $backup_innodb_data_file_path)
1053
# Die "The value of 'innodb_data_file_path' option in the original "
1054
# . "my.cnf file '$config_file' is different from the value "
1055
# . "in the backup my.cnf file '$backup_config_file'.\n(original: "
1056
# . "'$orig_innodb_data_file_path')\n"
1057
# . "(backup: '$backup_innodb_data_file_path')";
1060
1090
# make a list of all ibdata files in the backup directory and all
1061
1091
# directories in the backup directory under which there are ibdata files
1062
1092
foreach my $c (parse_innodb_data_file_path($orig_innodb_data_file_path)) {
1064
1094
# check that the backup data file exists
1065
1095
if (! -e "$backup_dir/$c->{filename}") {
1066
1096
if (-e "$backup_dir/$c->{filename}.ibz") {
1067
Die "Backup data file '$backup_dir/$c->{filename}' "
1097
die "Backup data file '$backup_dir/$c->{filename}' "
1068
1098
. "does not exist, but "
1069
1099
. "its compressed copy '$c->{path}.ibz' exists. Check "
1070
1100
. "that you have decompressed "
1072
1102
. "'$innobackup_script --copy-back ...' "
1073
1103
. "or '$innobackup_script --move-back ...' !";
1074
1104
} elsif (-e "$backup_dir/$c->{filename}.qp") {
1075
Die "Backup data file '$backup_dir/$c->{filename}' "
1105
die "Backup data file '$backup_dir/$c->{filename}' "
1076
1106
. "does not exist, but "
1077
1107
. "its compressed copy '$c->{path}.qp' exists. Check "
1078
1108
. "that you have run "
1081
1111
. "'$innobackup_script --copy-back ...' "
1082
1112
. "or '$innobackup_script --move-back ...' !";
1083
1113
} elsif (-e "$backup_dir/$c->{filename}.xbcrypt") {
1084
Die "Backup data file '$backup_dir/$c->{filename}' "
1114
die "Backup data file '$backup_dir/$c->{filename}' "
1085
1115
. "does not exist, but "
1086
1116
. "its compressed copy '$c->{path}.xbcrypt' exists. Check "
1087
1117
. "that you have run "
1123
1153
print STDERR "$prefix in '$backup_dir'\n";
1124
1154
print STDERR "$prefix back to '$orig_undo_dir'\n";
1125
1155
opendir(DIR, $backup_dir)
1126
|| Die "Can't open directory '$backup_dir': $!\n";
1156
|| die "Can't open directory '$backup_dir': $!";
1127
1157
while (defined($file = readdir(DIR))) {
1128
1158
if ($file =~ /^$ibundo_files$/ && -f "$backup_dir/$file") {
1129
1159
$src_name = escape_path("$backup_dir/$file");
1136
1166
# copy InnoDB log files to original InnoDB log directory
1137
1167
opendir(DIR, $backup_dir)
1138
|| Die "Can't open directory '$backup_dir': $!\n";
1168
|| die "Can't open directory '$backup_dir': $!";
1139
1169
print STDERR "\n$prefix Starting to $operation InnoDB log files\n";
1140
1170
print STDERR "$prefix in '$backup_dir'\n";
1141
1171
print STDERR "$prefix back to original InnoDB log directory '$orig_iblog_dir'\n";
1276
1306
if ($ibbackup_pid == $pid) {
1277
1307
# The file doesn't exist, but the process has terminated
1278
Die "ibbackup child process has died";
1309
die "The xtrabackup child process has died";
1460
1491
$ibbackup_pid = $pid;
1462
1493
# child process
1463
exec($cmdline) || Die "Failed to exec ibbackup: $!";
1494
exec($cmdline) || die "Failed to exec ibbackup: $!";
1466
Die "failed to fork ibbackup child process: $!";
1497
die "failed to fork ibbackup child process: $!";
1513
1544
my $con = shift;
1515
1546
if (defined($con->{keep_alive_pid})) {
1516
Die "Keep-alive process has already been started for this connection."
1547
die "Keep-alive process has already been started for this connection."
1519
1550
my $keep_alive_pid = fork();
1557
1588
my $con = shift;
1559
1590
if (!defined($con->{keep_alive_pid})) {
1560
Die "Keep-alive process has never been started for this connection."
1591
die "Keep-alive process has never been started for this connection."
1563
1594
kill 'INT', $con->{keep_alive_pid};
1612
1643
if ($args{abort_on_error}) {
1613
1644
if (!$dbd_mysql_installed) {
1614
die "ERROR: Failed to connect to MySQL server as " .
1645
die "Failed to connect to MySQL server as " .
1615
1646
"DBD::mysql module is not installed";
1617
1648
if (!$con{dbh}) {
1618
die "ERROR: Failed to connect to MySQL server: " .
1649
die "Failed to connect to MySQL server: " .
1619
1650
$con{connect_error};
1964
1995
if (defined($query_killer_pid)) {
1965
1996
kill 'HUP' => $query_killer_pid;
1966
1997
waitpid($query_killer_pid, 0);
1998
undef $query_killer_pid;
1967
1999
print STDERR "Query killing process is finished\n";
2032
# kill_child_processes subroutine kills all child processes of this process.
2034
sub kill_child_processes {
2035
if ($ibbackup_pid) {
2036
kill($kill_signal, $ibbackup_pid);
2039
stop_query_killer();
2044
2064
# require_external subroutine checks that an external program is runnable
2045
2065
# via the shell. This is tested by calling the program with the
2046
2066
# given arguments. It is checked that the program returns 0 and does
2186
2206
&& $ibbackup_version le "2.0") {
2187
2207
# --include option was given, but ibbackup is too
2188
2208
# old to support it
2189
Die "--include option was given, but ibbackup is too old"
2209
die "--include option was given, but ibbackup is too old"
2190
2210
. " to support it. You must upgrade to InnoDB Hot Backup"
2191
2211
. " v2.0 in order to use --include option.\n";
2238
2258
"file '$option_tmpdir/$xtrabackup_pid_file' " .
2239
2259
"was found.\n";
2240
2260
unlink $option_tmpdir . "/" . $xtrabackup_pid_file ||
2241
Die "Failed to delete " .
2261
die "Failed to delete " .
2242
2262
"'$option_tmpdir/$xtrabackup_pid_file': $!";
2317
# no command line arguments
2318
print STDERR "$prefix You must specify the backup directory.\n";
2322
2336
# read command line options
2323
2337
$rcode = GetOptions('compress' => \$option_compress,
2324
2338
'decompress' => \$option_decompress,
2383
2397
'lock-wait-query-type=s' =>
2384
2398
\$option_lock_wait_query_type
2402
die "You must specify the backup directory.\n";
2403
} elsif (@ARGV > 1) {
2404
die "Too many command line arguments\n";
2388
2408
# failed to read options
2389
print STDERR "$prefix Bad command line arguments\n";
2409
die "Bad command line arguments\n";
2392
2411
if ($option_help) {
2393
2412
# print help text and exit
2403
2422
if ($option_defaults_file && $option_defaults_extra_file) {
2404
print STDERR "$prefix --defaults-file and --defaults-extra-file " .
2423
die "--defaults-file and --defaults-extra-file " .
2405
2424
"options are mutually exclusive";
2409
2427
if ($option_copy_back && $option_move_back) {
2424
2442
# validate lock-wait-query-type and kill-long-query-type values
2425
2443
if (!(grep {$_ eq $option_lock_wait_query_type} qw/all update/)) {
2426
Die "Wrong value of lock-wait-query-type. ".
2444
die "Wrong value of lock-wait-query-type. ".
2427
2445
"Possible values are all|update, but $option_lock_wait_query_type ".
2428
2446
"is specified.";
2430
2448
if (!(grep {$_ eq $option_kill_long_query_type} qw/all select/)) {
2431
Die "Wrong value of kill-long-query-type. ".
2449
die "Wrong value of kill-long-query-type. ".
2432
2450
"Possible values are all|select, but $option_kill_long_query_type ".
2433
2451
"is specified.";
2436
2454
if ($option_parallel && $option_parallel < 1) {
2437
Die "$prefix --parallel must be a positive numerical value" .
2455
die "--parallel must be a positive value.\n";
2441
2458
if ($option_stream eq 'tar') {
2461
print STDERR "$prefix Missing command line argument\n";
2463
} elsif (@ARGV > 1) {
2464
print STDERR "$prefix Too many command line arguments\n";
2468
2477
if (!$option_apply_log && !$option_copy_back && !$option_move_back
2469
2478
&& !$option_decrypt && !$option_decompress) {
2470
2479
# we are making a backup, get backup root directory
2488
2497
if ($option_slave_info) {
2489
2498
if ($option_no_lock and !$option_safe_slave_backup) {
2490
print STDERR "--slave-info is used with --no-lock but without --safe-slave-backup. The binlog position cannot be consistent with the backup data.\n";
2499
die "--slave-info is used with --no-lock but without --safe-slave-backup. The binlog position cannot be consistent with the backup data.\n";
2495
2503
if ($option_rsync && $option_stream) {
2496
print STDERR "--rsync doesn't work with --stream\n";
2504
die "--rsync doesn't work with --stream\n";
2500
2507
if ($option_decompress) {
2501
2508
if (system("which qpress &>/dev/null") >> 8 != 0) {
2502
print STDERR "--decompress requires qpress\n";
2509
die "--decompress requires qpress\n";
2529
2535
$dir .= '/' . strftime("%Y-%m-%d_%H-%M-%S", localtime())
2530
2536
unless $option_no_timestamp;
2531
mkdir($dir, 0777) || Die "Failed to create backup directory $dir: $!";
2537
mkdir($dir, 0777) || die "Failed to create backup directory $dir: $!";
2533
2539
# create subdirectories for ibdata files if needed
2534
2540
# foreach my $a (split(/;/, $innodb_data_file_path)) {
2566
2572
$path = $path . "/" . $a;
2567
2573
if (! -d $path) {
2568
2574
# this directory does not exist, create it !
2569
mkdir($path, 0777) || Die "Failed to create backup directory: $!";
2575
mkdir($path, 0777) || die "Failed to create backup directory: $!";
2626
2632
$rsync_file_list = $rsync_tmpfile_pass2;
2628
2634
open(RSYNC, ">$rsync_file_list")
2629
|| Die "Can't open $rsync_file_list for writing: $!\n";
2635
|| die "Can't open $rsync_file_list for writing: $!";
2632
2638
opendir(DIR, $source_dir)
2633
|| Die "Can't open directory '$source_dir': $!\n";
2639
|| die "Can't open directory '$source_dir': $!";
2634
2640
$now = current_time();
2635
2641
if ($prep_mode) {
2636
2642
$operation = "a prep copy of";
2653
2659
if (! -e "$backup_dir/$database") {
2654
2660
# create database directory for the backup
2655
2661
mkdir("$backup_dir/$database", 0777)
2656
|| Die "Couldn't create directory '$backup_dir/$database': $!";
2662
|| die "Couldn't create directory '$backup_dir/$database': $!";
2720
2726
# ignore errors in the prep mode, since we are running without lock,
2721
2727
# so some files may have disappeared.
2722
2728
if (system("$rsync_cmd") && !$prep_mode) {
2723
Die "rsync failed: $!\n";
2729
die "rsync failed: $!";
2726
2732
$now = current_time();
2731
2737
# with --files-from.
2732
2738
if (!$prep_mode && !$option_no_lock) {
2733
2739
open(RSYNC, "<$rsync_tmpfile_pass1")
2734
|| Die "Can't open $rsync_tmpfile_pass1 for reading: $!\n";
2740
|| die "Can't open $rsync_tmpfile_pass1 for reading: $!";
2736
2742
while (<RSYNC>) {
2745
2751
unlink "$rsync_tmpfile_pass1" || \
2746
Die "Failed to delete $rsync_tmpfile_pass1: $!";
2752
die "Failed to delete $rsync_tmpfile_pass1: $!";
2747
2753
unlink "$rsync_tmpfile_pass2" || \
2748
Die "Failed to delete $rsync_tmpfile_pass2: $!";
2754
die "Failed to delete $rsync_tmpfile_pass2: $!";
2771
2777
my $filename = shift;
2772
2778
my $lines_ref = shift;
2774
open(FILE, $filename) || Die "can't open file '$filename': $!";
2780
open(FILE, $filename) || die "can't open file '$filename': $!";
2775
2781
@{$lines_ref} = <FILE>;
2776
close(FILE) || Die "can't close file '$filename': $!";
2782
close(FILE) || die "can't close file '$filename': $!";
2778
2784
foreach my $a (@{$lines_ref}) {
2971
2976
if (!exists $config{$group}) {
2973
print STDERR "$prefix fatal error: no '$group' group in MySQL options\n";
2978
die "no '$group' group in MySQL options";
2977
2981
$group_hash_ref = ${$config_ref}{$group};
2978
2982
if (!exists ${$group_hash_ref}{$option_name}) {
2980
print STDERR "$prefix fatal error: no '$option_name' option in group '$group' in MySQL options\n";
2984
die "no '$option_name' option in group '$group' in MySQL options";
2984
2987
return ${$group_hash_ref}{$option_name};
3089
3092
# the option value is pathname of the file containing
3090
3093
# list of databases
3091
3094
if (! -f $option_databases) {
3092
Die "can't find file '$option_databases'";
3095
die "can't find file '$option_databases'";
3095
3098
# read from file the value of --databases option
3201
3204
if($var_version =~ m/5\.0\.\d/) {
3202
Die "MySQL 5.0 support was removed in Percona XtraBackup 2.1. The last version to support MySQL 5.0 was Percona XtraBackup 2.0.";
3205
die "MySQL 5.0 support was removed in Percona XtraBackup 2.1. The last version to support MySQL 5.0 was Percona XtraBackup 2.0.\n";
3205
3208
if($var_version =~ m/5\.1\.\d/ && !defined($var_innodb_version)) {
3206
Die "Support for MySQL 5.1 with builtin InnoDB (not the plugin) was removed in Percona XtraBackup 2.1. The last version to support MySQL 5.1 with builtin InnoDB was Percona XtraBackup 2.0.";
3209
die "Support for MySQL 5.1 with builtin InnoDB (not the plugin) was removed in Percona XtraBackup 2.1. The last version to support MySQL 5.1 with builtin InnoDB was Percona XtraBackup 2.0.\n";
3209
3212
if($var_version =~ m/5\.1\.\d/) {
3229
3232
if (!$ibbackup_binary) {
3230
Die "Unsupported server version: '$var_version' " .
3233
die "Unsupported server version: '$var_version' " .
3231
3234
"(InnoDB version: '$var_innodb_version'). " .
3232
3235
"Please report a bug at ".
3233
3236
"https://bugs.launchpad.net/percona-xtrabackup\n";
3295
3298
mysql_query($con, 'START SLAVE SQL_THREAD');
3298
Die "Slave_open_temp_tables did not become zero after waiting $option_safe_slave_backup_timeout seconds";
3301
die "Slave_open_temp_tables did not become zero after $option_safe_slave_backup_timeout seconds";
3301
3304
sub get_slave_open_temp_tables {
3304
3307
get_mysql_status($con);
3306
3309
if (!defined($con->{status}->{Slave_open_temp_tables})) {
3307
Die "Failed to get Slave_open_temp_tables from SHOW STATUS"
3310
die "Failed to get Slave_open_temp_tables from SHOW STATUS"
3309
3312
if (!defined($con->{status}->{Slave_open_temp_tables}->{Value})) {
3310
Die "SHOW STATUS LIKE 'slave_open_temp_tables' did not return anything"
3313
die "SHOW STATUS LIKE 'slave_open_temp_tables' did not return anything"
3313
3316
return $con->{status}->{Slave_open_temp_tables}->{Value};
3353
3356
# Only treat as fatal cases where the file exists
3354
3357
if ( -e "$src_path/$src_file" ) {
3355
Die "Failed to stream '$src_path/$src_file': $ret";
3358
die "Failed to stream '$src_path/$src_file': $ret";
3357
3360
print STDERR "$prefix Ignoring nonexistent file '$src_path/$src_file'.\n";
3377
3380
$dst_file_esc = $dst_file_esc . ".xbcrypt";
3378
3381
$ret = system("$encrypt_cmd -i \"$src_file_esc\" -o \"$dst_file_esc\"");
3379
3382
if ($ret != 0) {
3380
Die "Failed to copy and encrypt file '$src_file': $ret";
3383
die "Failed to copy and encrypt file '$src_file': $ret";
3382
3385
} elsif ( -e "$src_file_esc" ) {
3383
3386
$ret = system("$CP_CMD \"$src_file_esc\" \"$dst_file_esc\"");
3384
3387
if ($ret != 0) {
3385
Die "Failed to copy file '$src_file': $ret";
3388
die "Failed to copy file '$src_file': $ret";