diff --git a/tasks/connection_check.php b/tasks/connection_check.php index 623b73d..2739052 100644 --- a/tasks/connection_check.php +++ b/tasks/connection_check.php @@ -62,7 +62,8 @@ $command = 'ssh -q '.$ssh_username.'@'.$ssh_hostname.' "bash -c \"test -f '.$remote_wp_cli.' && echo true || echo false\""'; $live_server_check = exec($command); -if ($live_server_check == 'false') { +// Anything but an explicit 'true' (e.g. no output from a dropped connection) is a failure +if ($live_server_check !== 'true') { // Exit Messages task_message('Connected but cannot find remote WP-CLI', 'Error', 31, false); diff --git a/tasks/database_sync.php b/tasks/database_sync.php index 54bf900..473085e 100644 --- a/tasks/database_sync.php +++ b/tasks/database_sync.php @@ -7,7 +7,7 @@ task_message($task_name); // pv check -if (`which pv`) { +if (shell_exec('which pv')) { $pipe = '| pv |'; } else { task_message('Install the \'pv\' command to monitor import progress', 'Notice', 33, false); @@ -16,12 +16,18 @@ $command = 'ssh '.$ssh_username.'@'.$ssh_hostname.' "bash -c \"cd '.$rem_proj_loc.' && '.$remote_wp_cli.' db export --single-transaction -\"" '.$pipe.' '.$local_wp_cli.' db import -'; debug_message($command); -system($command); +// pipefail catches a failed export, not just a failed import +system('bash -c '.escapeshellarg('set -o pipefail; '.$command), $db_status); + +if ($db_status !== 0) { + task_message('Database sync failed (exit code '.$db_status.')', 'Error', 31); + $fail_count++; +} /** - * TASK: Post sync queries + * TASK: Post sync queries (skipped if the import failed) */ -if ($queries = $_ENV['DEV_POST_SYNC_QUERIES']) { +if ($db_status === 0 && ($queries = $_ENV['DEV_POST_SYNC_QUERIES'])) { $command = $local_wp_cli . ' db query "' . preg_replace('/(`|")/i', '\\\\${1}', $queries) . '"'; debug_message($command); system($command); diff --git a/tasks/plugins_sync.php b/tasks/plugins_sync.php index 3833faa..71dd60d 100644 --- a/tasks/plugins_sync.php +++ b/tasks/plugins_sync.php @@ -13,11 +13,16 @@ return; } -if (`which rsync`) { +if (shell_exec('which rsync')) { task_message($task_name); - $command = 'rsync -avhP ' . $ssh_username . '@' . $ssh_hostname . ':' . $rem_proj_loc . '/' . $plugin_dir . '/ ./' . $plugin_dir . '/'; + $command = 'rsync -avhP ' . escapeshellarg($ssh_username . '@' . $ssh_hostname . ':' . $rem_proj_loc . '/' . $plugin_dir . '/') . ' ' . escapeshellarg('./' . $plugin_dir . '/'); debug_message($command); - system($command); + system($command, $rsync_status); + + if ($rsync_status !== 0 && $rsync_status !== 24) { + task_message($task_name.' failed (rsync exit code '.$rsync_status.')', 'Error', 31); + $fail_count++; + } } else { task_message($task_name.' task not ran, please install \'rsync\'', 'Error', 31); $fail_count++; diff --git a/tasks/uploads_sync.php b/tasks/uploads_sync.php index 965197b..b1936fc 100644 --- a/tasks/uploads_sync.php +++ b/tasks/uploads_sync.php @@ -9,15 +9,21 @@ if ($exclude_dirs = $_ENV['DEV_SYNC_DIR_EXCLUDES']) { $exclude_dirs = explode(',', $exclude_dirs); foreach ($exclude_dirs as $dir) { - $excludes .= ' --exclude=' . $dir; + $excludes .= ' --exclude=' . escapeshellarg($dir); } } -if (`which rsync`) { +if (shell_exec('which rsync')) { task_message($task_name); - $command = 'rsync -avhP ' . $ssh_username . '@' . $ssh_hostname . ':' . $rem_proj_loc . '/' . $upload_dir . '/ ./' . $upload_dir . '/' . $excludes; + $command = 'rsync -avhP ' . escapeshellarg($ssh_username . '@' . $ssh_hostname . ':' . $rem_proj_loc . '/' . $upload_dir . '/') . ' ' . escapeshellarg('./' . $upload_dir . '/') . $excludes; debug_message($command); - system($command); + system($command, $rsync_status); + + // 24 = files vanished mid-transfer, routine on a live uploads folder + if ($rsync_status !== 0 && $rsync_status !== 24) { + task_message($task_name.' failed (rsync exit code '.$rsync_status.')', 'Error', 31); + $fail_count++; + } } else { task_message($task_name.' task not ran, please install \'rsync\'', 'Error', 31); $fail_count++;