diff --git a/includes/backend.inc b/includes/backend.inc
index 21ab8c0..b6e4813 100644
--- a/includes/backend.inc
+++ b/includes/backend.inc
@@ -292,8 +292,8 @@ function _drush_backend_integrate($data, $backend_options, $outputted) {
 /**
  * Call an external command using proc_open.
  *
- * @param cmd
- *    The command to execute. This command already needs to be properly escaped.
+ * @param cmds
+ *    An array of commands to execute. These commands already need to be properly escaped.
  * @param data
  *    An associative array that will be JSON encoded and passed to the script being called.
  *    Objects are not allowed, as they do not json_decode gracefully.
@@ -303,68 +303,102 @@ function _drush_backend_integrate($data, $backend_options, $outputted) {
  *   If it executed successfully, it returns an associative array containing the command
  *   called, the output of the command, and the error code of the command.
  */
-function _drush_proc_open($cmd, $post_options = NULL, $context = NULL, $backend_options = array()) {
-
+function _drush_proc_open($cmds, $post_options = NULL, $context = NULL, $backend_options = array()) {
+  if (isset($backend_options['concurrency']) && count($cmds) == 1) {
+    $backend_options_arr = array();
+    for ($i = 0; $i <= $backend_options['concurrency']; $i++) {
+      $backend_options_arr[$i] = $backend_options;
+      $backend_options_arr[$i]['output-label'] = ' * [@self.' . $i . '] ';
+    }
+    $cmds = array_fill(0, $backend_options['concurrency'], $cmds[0]);
+    $backend_options = $backend_options_arr;
+  }
   $descriptorspec = array(
-     0 => array("pipe", "r"),  // stdin is a pipe that the child will read from
-     1 => array("pipe", "w"),  // stdout is a pipe that the child will write to
-     2 => array("pipe", "w")   // stderr is a pipe the child will write to
+    0 => array("pipe", "r"),  // stdin is a pipe that the child will read from
+    1 => array("pipe", "w"),  // stdout is a pipe that the child will write to
+    2 => array("pipe", "w")   // stderr is a pipe the child will write to
   );
-  $process = proc_open($cmd, $descriptorspec, $pipes, null, null, array('context' => $context));
-  if (is_resource($process)) {
-    if ($post_options) {
-      fwrite($pipes[0], json_encode($post_options)); // pass the data array in a JSON encoded string
+  $open_processes = array();
+  $bucket = array();
+  // Initiate processes for each command.
+  foreach ($cmds as $site => $c) {
+    $process = array();
+    drush_log($backend_options[$site]['output-label'] . $c);
+    $process['process'] = proc_open($c, $descriptorspec, $process['pipes'], null, null, array('context' => $context));
+    if (is_resource($process['process'])) {
+      if ($post_options) {
+        fwrite($process['pipes'][0], json_encode($post_options)); // pass the data array in a JSON encoded string
+      }
+      // If we do not close stdin here, then we cause a deadlock;
+      // see: http://drupal.org/node/766080#comment-4309936
+      // If we reimplement interactive commands to also use
+      // _drush_proc_open, then clearly we would need to keep
+      // this open longer.
+      fclose($process['pipes'][0]);
+
+      foreach (array(1, 2) as $pipe) {
+        $process['info'] = stream_get_meta_data($process['pipes'][$pipe]);
+        stream_set_blocking($process['pipes'][$pipe], FALSE);
+        stream_set_timeout($process['pipes'][$pipe], 1);
+      }
+      $bucket[$site]['cmd'] = $c;
+      $bucket[$site]['output'] = '';
+      $bucket[$site]['backend_opts'] = $backend_options[$site];
+      $bucket[$site]['end_of_output'] = FALSE;
+      $bucket[$site]['outputted'] = FALSE;
+      $open_processes[$site] = $process;
     }
-    // If we do not close stdin here, then we cause a deadlock;
-    // see: http://drupal.org/node/766080#comment-4309936
-    // If we reimplement interactive commands to also use
-    // _drush_proc_open, then clearly we would need to keep
-    // this open longer.
-    fclose($pipes[0]);
-
-    $info = stream_get_meta_data($pipes[1]);
-    stream_set_blocking($pipes[1], TRUE);
-    stream_set_timeout($pipes[1], 1);
-    $output = '';
-    $end_of_output = FALSE;
-    $outputted = FALSE;
-    while (!feof($pipes[1]) && !$info['timed_out']) {
-      $string = fread($pipes[1], 4096);
-      $output_end_pos = strpos($string, 'DRUSH_BACKEND_OUTPUT_START>>>');
-      if ($output_end_pos !== FALSE) {
-        $trailing_string = substr($string, 0, $output_end_pos);
-        drush_backend_parse_packets($trailing_string, $backend_options);
-        _drush_backend_print_output($trailing_string, $backend_options);
-        $end_of_output = TRUE;
+  }
+
+  // Loop through processes until they all close.
+  while (sizeof($open_processes)) {
+    foreach ($open_processes as $site => &$current_process) {
+      if (isset($current_process['pipes'][1]) || isset($current_process['pipes'][2])) {
+        // Collect output from stdout and stderr
+        foreach (array(1, 2) as $pipe) {
+          if (isset($current_process['pipes'][$pipe])) {
+            $bucket[$site][$pipe] = '';
+            $info = stream_get_meta_data($current_process['pipes'][$pipe]);
+
+            if (!feof($current_process['pipes'][$pipe]) && !$info['timed_out']) {
+              $string = fread($current_process['pipes'][$pipe], 4096);
+              $output_end_pos = strpos($string, 'DRUSH_BACKEND_OUTPUT_START>>>');
+              if ($output_end_pos !== FALSE) {
+                $trailing_string = substr($string, 0, $output_end_pos);
+                drush_backend_parse_packets($trailing_string, $bucket[$site]['backend_opts']);
+                _drush_backend_print_output($trailing_string, $bucket[$site]['backend_opts']);
+                $bucket[$site]['end_of_output'] = TRUE;
+              }
+              if (!$bucket[$site]['end_of_output']) {
+                drush_backend_parse_packets($string, $bucket[$site]['backend_opts']);
+                // Pass output through.
+                _drush_backend_print_output($string, $bucket[$site]['backend_opts']);
+                $bucket[$site]['outputted'] = TRUE;
+              }
+              $bucket[$site][$pipe] .= $string;
+              $bucket[$site]['output'] .= $string;
+              $info = stream_get_meta_data($current_process['pipes'][$pipe]);
+              flush();
+            }
+            else {
+              fclose($current_process['pipes'][$pipe]);
+              unset($current_process['pipes'][$pipe]);
+              // close the pipe , set a marker
+            }
+          }
+        }
       }
-      if (!$end_of_output) {
-        drush_backend_parse_packets($string, $backend_options);
-        // Pass output through.
-        _drush_backend_print_output($string, $backend_options);
-        $outputted = TRUE;
+      else {
+        // if both pipes are closed for the process, remove it from active loop and add a new process to open.
+        $bucket[$site]['code'] = proc_close($current_process['process']);
+        unset($open_processes[$site]);
       }
-      $output .= $string;
-      $info = stream_get_meta_data($pipes[1]);
-      flush();
-    };
-
-    $info = stream_get_meta_data($pipes[2]);
-    stream_set_blocking($pipes[2], TRUE);
-    stream_set_timeout($pipes[2], 1);
-    while (!feof($pipes[2]) && !$info['timed_out']) {
-      $string = fgets($pipes[2], 4096);
-      $output .= $string;
-      fwrite(STDERR, $string);
-      $info = stream_get_meta_data($pipes[2]);
-      flush();
-    };
-
-    fclose($pipes[1]);
-    fclose($pipes[2]);
-    $code = proc_close($process);
-    return array('cmd' => $cmd, 'output' => $output, 'code' => $code, 'outputted' => $outputted);
+    }
   }
-  return FALSE;
+  return $bucket;
+  // TODO: Handle bad proc handles
+  //}
+  //return FALSE;
 }
 
 /**
@@ -524,29 +558,32 @@ function _drush_backend_adjust_options($site_record, $command, $command_options,
  *   If the command could not be completed successfully, FALSE.
  *   If the command was completed, this will return an associative array containing the data from drush_backend_output().
  */
-function drush_backend_invoke_sitealias_command($site_record, $command, $args, $command_options = array(), $backend_options = array()) {
-  $backend_options = _drush_backend_adjust_options($site_record, $command, $command_options, $backend_options);
-  $os = drush_os($site_record);
-
-  $site_record += array( 'path-aliases' => array() );
-  $site_record['path-aliases'] += array(
-     '%drush-script' => NULL,
-  );
-  $drush_path = $site_record['path-aliases']['%drush-script'];
-
-  // If the caller did not pass in a specific path to drush, then we will
-  // use a default value.  For commands that are being executed on the same
-  // machine, we will use DRUSH_COMMAND, which is the path to the drush.php
-  // that is running right now.  For remote commands, we will run a wrapper
-  // script instead of drush.php -- drush.bat on Windows, or drush on Linux.
-  $drush_command_path = drush_build_drush_command($drush_path, array_key_exists('php', $command_options) ? $command_options['php'] : NULL, drush_os($site_record), array_key_exists('remote-host', $site_record));
-
-  // Insure that contexts such as DRUSH_SIMULATE and NO_COLOR are included.
-  $command_options += _drush_backend_get_global_contexts($site_record);
+function drush_backend_invoke_sitealias_command($site_records, $command, $args, $command_options = array(), $backend_options = array()) {
+  $backend_options = _drush_backend_adjust_options($site_records, $command, $command_options, $backend_options);
 
   list($post_options, $commandline_options, $drush_global_options) = _drush_backend_classify_options($command_options, $backend_options);
-  $cmd = _drush_backend_generate_command($site_record, $drush_command_path . " " . _drush_backend_argument_string($drush_global_options, $os) . " " . $command, $args, $commandline_options, $backend_options) . ' 2>&1';
-  return _drush_backend_invoke($cmd, $post_options, $backend_options);
+  $cmds = array();
+  foreach ($site_records as $site_record)  {
+    $os = drush_os($site_record);
+    $site_record += array( 'path-aliases' => array() );
+    $site_record['path-aliases'] += array(
+      '%drush-script' => NULL,
+    );
+    $drush_path = $site_record['path-aliases']['%drush-script'];
+
+    // If the caller did not pass in a specific path to drush, then we will
+    // use a default value.  For commands that are being executed on the same
+    // machine, we will use DRUSH_COMMAND, which is the path to the drush.php
+    // that is running right now.  For remote commands, we will run a wrapper
+    // script instead of drush.php -- drush.bat on Windows, or drush on Linux.
+    $drush_command_path = drush_build_drush_command($drush_path, array_key_exists('php', $command_options) ? $command_options['php'] : NULL, $os, array_key_exists('remote-host', $site_record));
+
+    // Insure that contexts such as DRUSH_SIMULATE and NO_COLOR are included.
+    $command_options += _drush_backend_get_global_contexts($site_record);
+
+    $cmds[] = _drush_backend_generate_command($site_record, $drush_command_path . " " . _drush_backend_argument_string($drush_global_options, $os) . " " .  $command, $args, $commandline_options, $backend_options) . ' 2>&1';
+  }
+  return _drush_backend_invoke($cmds, $post_options, $backend_options);
 }
 
 /**
@@ -638,34 +675,45 @@ function _drush_backend_classify_options($command_options, $backend_options) {
  *   If the command could not be completed successfully, FALSE.
  *   If the command was completed, this will return an associative array containing the data from drush_backend_output().
  */
-function _drush_backend_invoke($cmd, $post_options = NULL, $backend_options = array()) {
+function _drush_backend_invoke($cmds, $post_options = NULL, $backend_options = array()) {
   if (drush_get_context('DRUSH_SIMULATE') && !array_key_exists('override-simulated', $backend_options)) {
-    drush_print(dt('Simulating backend invoke: !cmd', array('!cmd' => $cmd)));
+    foreach ($cmds as $cmd) {
+      drush_print(dt('Simulating backend invoke: !cmd', array('!cmd' => $cmd)));
+    }
     return FALSE;
   }
-  drush_log(dt('Backend invoke: !cmd', array('!cmd' => $cmd)), 'command');
+  foreach ($cmds as $cmd) {
+    drush_log(dt('Backend invoke: !cmd', array('!cmd' => $cmd)), 'command');
+  }
   if (array_key_exists('interactive', $backend_options)) {
-    drush_log(dt("executing !cmd", array('!cmd' => $cmd)));
-    return drush_op_system($cmd);
+    foreach ($cmds as $cmd) {
+      drush_log(dt("executing !cmd", array('!cmd' => $cmd)));
+      $ret = drush_op_system($cmd);
+    }
+    return $ret;
   }
   else {
-    $proc = _drush_proc_open($cmd, $post_options, NULL, $backend_options);
-
-    if (($proc['code'] == DRUSH_APPLICATION_ERROR) && $backend_options['integrate']) {
-      drush_set_error('DRUSH_APPLICATION_ERROR', dt("The external command could not be executed due to an application error."));
-    }
+    $procs = _drush_proc_open($cmds, $post_options, NULL, $backend_options);
+    $procs = is_array($procs) ? $procs : array($procs);
 
-    if ($proc['output']) {
-      $values = drush_backend_parse_output($proc['output'], $backend_options, $proc['outputted']);
-      if (is_array($values)) {
-        return $values;
+    foreach ($procs as $proc) {
+      $ret = array();
+      if (($proc['code'] == DRUSH_APPLICATION_ERROR) && $backend_options['integrate']) {
+        drush_set_error('DRUSH_APPLICATION_ERROR', dt("The external command could not be executed due to an application error."));
       }
-      else {
-        return drush_set_error('DRUSH_FRAMEWORK_ERROR', dt("The command could not be executed successfully (returned: !return, code: %code)", array("!return" => $proc['output'], "%code" =>  $proc['code'])));
+
+      if ($proc['output']) {
+        $values = drush_backend_parse_output($proc['output'], $backend_options, $proc['outputted']);
+        if (is_array($values)) {
+          $ret = $ret + $values;
+        }
+        else {
+          $ret = drush_set_error('DRUSH_FRAMEWORK_ERROR', dt("The command could not be executed successfully (returned: !return, code: %code)", array("!return" => $proc['output'], "%code" =>  $proc['code'])));
+        }
       }
     }
   }
-  return FALSE;
+  return empty($ret) ? FALSE : $ret;
 }
 
 /**
diff --git a/includes/command.inc b/includes/command.inc
index c50eec8..823ae9a 100644
--- a/includes/command.inc
+++ b/includes/command.inc
@@ -370,18 +370,23 @@ function _drush_flatten_options($options) {
  *   array containing the results of the API call.
  *   @see drush_backend_get_result()
  */
-function drush_invoke_process($site_alias_record, $command_name, $commandline_args = array(), $commandline_options = array(), $backend_options = FALSE) {
+function drush_invoke_process($site_alias_records, $command_name, $commandline_args = array(), $commandline_options = array(), $backend_options = FALSE) {
   // NULL is a synonym to '@self', although the later is preferred.
-  if (!isset($site_alias_record)) {
-    $site_alias_record = '@self';
+  if (empty($site_alias_records)) {
+    $site_alias_records = array('@self');
+  }
+  elseif (is_string($site_alias_records)) {
+    $site_alias_records = array($site_alias_records);
   }
   // If the first parameter is not a site alias record,
   // then presume it is an alias name, and try to look up
   // the alias record.
-  if (!is_array($site_alias_record)) {
-    $site_alias_record = drush_sitealias_get_record($site_alias_record);
+  foreach ($site_alias_records as &$site_alias_record) {
+    if (!is_array($site_alias_record)) {
+      $site_alias_record = drush_sitealias_get_record($site_alias_record);
+    }
   }
-  return drush_do_site_command($site_alias_record, $command_name, $commandline_args, $commandline_options, $backend_options);
+  return drush_do_site_command($site_alias_records, $command_name, $commandline_args, $commandline_options, $backend_options);
 }
 
 /**
diff --git a/includes/drush.inc b/includes/drush.inc
index d70df32..87b3ec8 100644
--- a/includes/drush.inc
+++ b/includes/drush.inc
@@ -965,8 +965,8 @@ function drush_remote_command() {
       $multi_options['reserve-margin'] = $max_name_length + strlen($label_separator);
       foreach ($site_list as $alias_name => $alias_record) {
         $backend_options['output-label'] = str_pad($alias_name, $max_name_length, " ") . $label_separator;
-        $values = drush_do_site_command($alias_record, $command, $args, $multi_options, $backend_options);
       }
+      $values = drush_do_site_command($site_list, $command, $args, $multi_options, $backend_options);
     }
     else {
       if ($interactive) {
@@ -974,9 +974,9 @@ function drush_remote_command() {
       }
       foreach ($site_list as $alias_name => $alias_record) {
         drush_print(dt("!site >> !command", array('!command' => $command . ' ' . implode(" ", $args), '!site' => $alias_name)));
-        $values = drush_do_site_command($alias_record, $command, $args, $multi_options, $backend_options);
-        drush_print($values['output']);
       }
+      $values = drush_do_site_command($site_list, $command, $args, $multi_options, $backend_options);
+      drush_print($values['output']);
     }
     return TRUE;
   }
@@ -1056,20 +1056,22 @@ function drush_do_multiple_command($command, $source_record, $destination_record
  *   FALSE - do not integrate errors
  *   array - @see drush_backend_invoke_sitealias_command
  */
-function drush_do_site_command($site_record, $command, $args = array(), $data = array(), $backend_options = FALSE) {
+function drush_do_site_command($site_records, $command, $args = array(), $data = array(), $backend_options = FALSE) {
   $values = NULL;
-  if (!empty($site_record)) {
+  if (!empty($site_records)) {
     if (is_bool($backend_options)) {
       $integrate = $backend_options;
       $backend_options = array('integrate' => $integrate);
     }
-    foreach ($site_record as $key => $value) {
-      if (!isset($data[$key]) && !in_array($key, drush_sitealias_site_selection_keys())) {
-        $data[$key] = $site_record[$key];
+    foreach ($site_records as $site_record) {
+      foreach ($site_record as $key => $value) {
+        if (!isset($data[$key]) && !in_array($key, drush_sitealias_site_selection_keys())) {
+          $data[$key] = $site_record[$key];
+        }
       }
     }
-    $values = drush_backend_invoke_sitealias_command($site_record, $command, $args, $data, $backend_options);
   }
+  $values = drush_backend_invoke_sitealias_command($site_records, $command, $args, $data, $backend_options);
   return $values;
 }
 
@@ -1097,7 +1099,7 @@ function drush_do_command_redispatch($command, $args = array(), $remote_host = N
 
   // Run the command in a new process.
   drush_log(dt('Begin redispatch via invoke process'));
-  $values = drush_invoke_process('@self', $command, $args, $command_options, $backend_options);
+  $values = drush_invoke_process(array('@self'), $command, $args, $command_options, $backend_options);
   drush_log(dt('Invoke process is complete'));
 
   return $values;
