/** * Starts the batch process depending on where it was requested from. */ public function start() { switch ($this->batchInfo['from']) { case 'form': batch_set($this->batch); break; case 'drush': batch_set($this->batch); $this->batch =& batch_get(); $this->batch['progressive'] = FALSE; drush_log(t(self::BATCH_INIT_MESSAGE), 'status'); drush_backend_batch_process(); break; case 'backend': batch_set($this->batch); $this->batch =& batch_get(); $this->batch['progressive'] = FALSE; batch_process(); //todo: Does not take advantage of batch API and eventually runs out of memory on very large sites. break; case 'nobatch': $context = []; foreach ($this->batch['operations'] as $i => $operation) { $operation[1][] =& $context; call_user_func_array($operation[0], $operation[1]); } self::finishGeneration(TRUE, $context['results'], []); break; } }
public function createSettingsFile($database, $db_user, $db_cred) { $web_dir = $this->getDocumentRoot(); $project_domain = $this->getProjectDomain(); if (empty($web_dir)) { $document_root = $this->getProjectDir(); } else { $document_root = $this->getProjectDir() . '/' . $web_dir; } $project_site_folder = $document_root . '/sites/' . $project_domain; // Create the settings.php file $this->settings_generator->generate_file($database, $db_user, $db_cred, $project_domain); drush_log(dt('Created the settings.php file.'), 'success'); // Do we want a multisite setup or not? $multi = drush_confirm(dt('Do you want to configure Drupal as a multi site setup (settings.php in a separate sites folder)?')); if ($multi) { // Create an empty project folder. conf_path(FALSE) will pick it up and take care of the rest if (!$this->file_system->checkDir($project_site_folder)) { $this->file_system->createDir($project_site_folder); $source = $this->getProjectDir() . '/' . $this->getDocumentRoot() . '/sites/default/settings.php'; $target = $this->getProjectDir() . '/' . $this->getDocumentRoot() . '/sites/' . $this->getProjectDomain() . '/settings.php'; $this->file_system->moveFile($source, $target); } } }
function bootstrap_and_dispatch() { $phases = _drush_bootstrap_phases(FALSE, TRUE); $return = ''; $command_found = FALSE; _drush_bootstrap_output_prepare(); foreach ($phases as $phase) { if (drush_bootstrap_to_phase($phase)) { $command = drush_parse_command(); if (is_array($command)) { $bootstrap_result = drush_bootstrap_to_phase($command['bootstrap']); drush_enforce_requirement_bootstrap_phase($command); drush_enforce_requirement_core($command); drush_enforce_requirement_drupal_dependencies($command); drush_enforce_requirement_drush_dependencies($command); if ($bootstrap_result && empty($command['bootstrap_errors'])) { drush_log(dt("Found command: !command (commandfile=!commandfile)", array('!command' => $command['command'], '!commandfile' => $command['commandfile'])), 'bootstrap'); $command_found = TRUE; // Dispatch the command(s). $return = drush_dispatch($command); // Prevent a '1' at the end of the output. if ($return === TRUE) { $return = ''; } if (drush_get_context('DRUSH_DEBUG') && !drush_get_context('DRUSH_QUIET')) { // @todo Create version independant wrapper around Drupal timers. Use it. drush_print_timers(); } break; } } } else { break; } } if (!$command_found) { // If we reach this point, command doesn't fit requirements or we have not // found either a valid or matching command. // If no command was found check if it belongs to a disabled module. if (!$command) { $command = drush_command_belongs_to_disabled_module(); } // Set errors related to this command. $args = implode(' ', drush_get_arguments()); if (isset($command) && is_array($command)) { foreach ($command['bootstrap_errors'] as $key => $error) { drush_set_error($key, $error); } drush_set_error('DRUSH_COMMAND_NOT_EXECUTABLE', dt("The drush command '!args' could not be executed.", array('!args' => $args))); } elseif (!empty($args)) { drush_set_error('DRUSH_COMMAND_NOT_FOUND', dt("The drush command '!args' could not be found. Run `drush cache-clear drush` to clear the commandfile cache if you have installed new extensions.", array('!args' => $args))); } // Set errors that occurred in the bootstrap phases. $errors = drush_get_context('DRUSH_BOOTSTRAP_ERRORS', array()); foreach ($errors as $code => $message) { drush_set_error($code, $message); } } return $return; }
public function __construct($project_name, $project_dir) { drush_log(dt('Initializing Rum ...'), 'status'); // Set a few defaults in .drushrc.php. We can overrule these through the cli $this->settings_map = array('rum-workspace', 'rum-host', 'rum-os', 'rum-environment', 'rum-docroot', 'rum-project-db-dir'); foreach ($this->settings_map as $setting) { $this->checkSetting($setting); } // Set the current time once. date_default_timezone_set(drush_get_option('rum-timezone', 'Europe/Brussels')); $this->date = date("Y-m-d_H-i-s", $_SERVER['REQUEST_TIME']); // Set the workspace $this->workspace = drush_get_option('rum-workspace', ''); // Set the hostname of your machine (i.e. netsensei, stalski, swentel, atlas,...) $this->host_name = drush_get_option('rum-host', ''); // Set the type of OS you're using. Rum is not OS aware. $this->os = drush_get_option('rum-os', ''); // Set the environment $this->environment = drush_get_option('rum-environment', ''); // Set the project name $this->project_name = $project_name; // Set the project_dir for the action on this particular project $project_dir = FileSystem::sanitize($project_dir); $this->project_dir = $this->workspace . '/' . $project_dir; // Generate a domain name. Will be hostname.project_name (i.e. netsensei.foobar) $this->project_domain = $this->host_name . '.' . $project_name; // Set the default document root of your project i.e. 'www' $this->project_docroot = drush_get_option('rum-docroot', ''); // Set the default db dir where your project db dumps reside i.e. 'db' $this->project_db_dir = drush_get_option('rum-project-db-dir', ''); }
/** * {@inheritdoc} */ public function run($name, $time_limit = 0) { $worker = $this->workerManager->createInstance($name); $end = time() + $time_limit; $queue = $this->getQueue($name); $count = 0; while ((!$time_limit || time() < $end) && ($item = $queue->claimItem())) { try { drush_log(dt('Processing item @id from @name queue.', array('@name' => $name, 'id' => $item->item_id)), 'info'); $worker->processItem($item->data); $queue->deleteItem($item); $count++; } catch (SuspendQueueException $e) { // If the worker indicates there is a problem with the whole queue, // release the item and skip to the next queue. $queue->releaseItem($item); drush_set_error('DRUSH_SUSPEND_QUEUE_EXCEPTION', $e->getMessage()); } catch (\Exception $e) { // In case of any other kind of exception, log it and leave the item // in the queue to be processed again later. drush_set_error('DRUSH_QUEUE_EXCEPTION', $e->getMessage()); } } return $count; }
/** * {@inheritdoc} */ public function log($level, $message, array $context = array()) { // Translate the RFC logging levels into their Drush counterparts, more or // less. // @todo ALERT, CRITICAL and EMERGENCY are considered show-stopping errors, // and they should cause Drush to exit or panic. Not sure how to handle this, // though. switch ($level) { case LogLevel::ALERT: case LogLevel::CRITICAL: case LogLevel::EMERGENCY: case LogLevel::ERROR: $error_type = 'error'; break; case LogLevel::WARNING: $error_type = 'warning'; break; case LogLevel::DEBUG: case LogLevel::INFO: case LogLevel::NOTICE: $error_type = 'notice'; break; default: $error_type = $level; break; } drush_log($message, $error_type); }
/** * Magic __get, overriding Persistent. * * @param string $name * Name of the property. * * @return mixed * Value of set property. * @throws \Exception */ public function apiGetField($name) { $callers = debug_backtrace(); drush_log(dt('Site @site_name is missing value for @name from @calling_function.', array('@site_name' => $this->name, '@name' => $name, '@calling_function' => $callers[1]['function']))); $provider = Switchboard\Provider::getInstance($this->getProvider()); $provider->siteGetField($this->getName(), $name); }
/** * {@inheritdoc} */ public function log($level, $message, array $context = array()) { // Translate the RFC logging levels into their Drush counterparts, more or // less. // @todo ALERT, CRITICAL and EMERGENCY are considered show-stopping errors, // and they should cause Drush to exit or panic. Not sure how to handle this, // though. switch ($level) { case RfcLogLevel::ALERT: case RfcLogLevel::CRITICAL: case RfcLogLevel::EMERGENCY: case RfcLogLevel::ERROR: $error_type = 'error'; break; case RfcLogLevel::WARNING: $error_type = 'warning'; break; case RfcLogLevel::DEBUG: case RfcLogLevel::INFO: case RfcLogLevel::NOTICE: $error_type = 'notice'; break; default: $error_type = $level; break; } // Populate the message placeholders and then replace them in the message. $message_placeholders = $this->parser->parseMessagePlaceholders($message, $context); $message = empty($message_placeholders) ? $message : strtr($message, $message_placeholders); drush_log($message, $error_type); }
function configure_chosen() { drush_log('Configuring chosen', 'ok'); variable_set('chosen_minimum_multiple', '26'); variable_set('chosen_minimum_single', '99'); variable_set('chosen_disable_search_threshold', '32'); variable_set('chosen_minimum_width', '300'); }
/** * @inheritdoc */ protected function getContainerBuilder() { drush_log(dt("get container builder"), LogLevel::DEBUG); $container = parent::getContainerBuilder(); foreach ($this->serviceModifiers as $serviceModifier) { $serviceModifier->alter($container); } return $container; }
public function fetch($repository, $working_directory = NULL) { drush_log(dt('Fetching project data from remote source...'), 'status'); if (!$working_directory) { $working_directory = $this->getProjectDir(); } $this->state->fetch($repository, $working_directory); return TRUE; }
/** * @inheritdoc */ public function alter(ContainerBuilder $container) { drush_log(dt("service modifier alter"), LogLevel::DEBUG); // http://symfony.com/doc/2.7/components/dependency_injection/tags.html#register-the-pass-with-the-container $container->register('drush.service.consolecommands', 'Drush\\Command\\ServiceCommandlist'); $container->addCompilerPass(new FindCommandsCompilerPass('drush.service.consolecommands', 'console.command')); $container->register('drush.service.consolidationcommands', 'Drush\\Command\\ServiceCommandlist'); $container->addCompilerPass(new FindCommandsCompilerPass('drush.service.consolidationcommands', 'consolidation.commandhandler')); }
public function valid_credentials($db_spec) { // Drupal >=7 requires PDO and Drush requires php 5.6+ which ships with PDO // but it may be compiled with --disable-pdo. if (!class_exists('\\PDO')) { drush_log(dt('PDO support is required.'), LogLevel::BOOTSTRAP); return FALSE; } return TRUE; }
/** * Create a new database. * * @param boolean $quoted * Quote the database name. Mysql uses backticks to quote which can cause problems * in a Windows shell. Set TRUE if the CREATE is not running on the bash command line. */ public function createdb($quoted = FALSE) { // Make sure sqlite can create file $file = $this->db_spec['database']; $path = dirname($file); drush_log("SQLITE: creating '{$path}' for creating '{$file}'", 'debug'); drush_mkdir($path); if (!file_exists($path)) { drush_log("SQLITE: Cannot create {$path}", 'error'); } }
/** * Destroy the SQLite database. */ public static function destroy() { $location = Sqlite::getLocation(); drush_log(dt('Destroying SQLite database at @location', array('@location' => $location))); if (file_exists($location)) { unlink($location); drush_cache_clear_all('brain_path', 'switchboard', TRUE); drush_log(dt('SQLite database removed.')); } else { drush_log(dt('SQLite database does not exist, nothing to remove.')); } }
/** * The main Drush function. * * - Parses the command line arguments, configuration files and environment. * - Prepares and executes a Drupal bootstrap, if possible, * - Dispatches the given command. * * @return * Whatever the given command returns. */ function drush_main() { $phases = _drush_bootstrap_phases(); $completed_phases = array(); $return = ''; $command_found = FALSE; foreach ($phases as $phase) { if (drush_bootstrap($phase)) { $completed_phases[$phase] = TRUE; $command = drush_parse_command(); // Process a remote command if 'remote-host' option is set. if (drush_remote_command()) { $command_found = TRUE; break; } if (is_array($command)) { if (array_key_exists($command['bootstrap'], $completed_phases) && empty($command['bootstrap_errors'])) { drush_log(dt("Found command: !command (commandfile=!commandfile)", array('!command' => $command['command'], '!commandfile' => $command['commandfile'])), 'bootstrap'); $command_found = TRUE; // Dispatch the command(s). $return = drush_dispatch($command); if (drush_get_context('DRUSH_DEBUG')) { drush_print_timers(); } drush_log(dt('Peak memory usage was !peak', array('!peak' => drush_format_size(memory_get_peak_usage()))), 'memory'); break; } } } else { break; } } if (!$command_found) { // If we reach this point, we have not found either a valid or matching command. $args = implode(' ', drush_get_arguments()); if (isset($command) && is_array($command)) { foreach ($command['bootstrap_errors'] as $key => $error) { drush_set_error($key, $error); } drush_set_error('DRUSH_COMMAND_NOT_EXECUTABLE', dt("The drush command '!args' could not be executed.", array('!args' => $args))); } elseif (!empty($args)) { drush_set_error('DRUSH_COMMAND_NOT_FOUND', dt("The drush command '!args' could not be found.", array('!args' => $args))); } else { // This can occur if we get an error during _drush_bootstrap_drush_validate(); drush_set_error('DRUSH_COULD_NOT_EXECUTE', dt("Drush could not execute.")); } } // We set this context to let the shutdown function know we reached the end of drush_main(); drush_set_context("DRUSH_EXECUTION_COMPLETED", TRUE); // After this point the drush_shutdown function will run, // exiting with the correct exit code. return $return; }
public static function downloadPatch($url, $destination) { if ($downloaded = _drush_download_file($url, $destination, TRUE)) { if (!filesize($downloaded)) { throw new Exception("Remote patch {$url} downloaded as empty file {$destination}."); } else { drush_log(dt('Remote patch @url downloaded to @file.', array('@url' => $url, '@file' => $downloaded))); return $downloaded; } } else { throw new Exception("Unable to download or fetch remote patch from {$url} and save to {$destination}."); } }
private function drushRequest($params = array()) { global $base_url; if (preg_match('/default$/', $base_url) && !$this->servers) { drush_log(dt("In order to properly reset the OPcache cache, please use the -l/--uri flag to specify the correct URL of this Drupal installation, or specify paths to the PHP proxy servers in the OPcache module's settings form."), 'error'); return; } if (!$this->servers) { $server = url('<front>', array('absolute' => TRUE)); $this->httpRequest($server, $params); } else { $this->multiBackendRequest($params); } }
/** * Create a new database. * * @param boolean $quoted * Quote the database name. Mysql uses backticks to quote which can cause problems * in a Windows shell. Set TRUE if the CREATE is not running on the bash command line. */ public function createdb($quoted = FALSE) { $file = $this->db_spec['database']; if (file_exists($file)) { drush_log("SQLITE: Deleting existing database '{$file}'", LogLevel::DEBUG); drush_delete_dir($file, TRUE); } // Make sure sqlite can create file $path = dirname($file); drush_log("SQLITE: creating '{$path}' for creating '{$file}'", LogLevel::DEBUG); drush_mkdir($path); if (!file_exists($path)) { drush_log("SQLITE: Cannot create {$path}", LogLevel::ERROR); } }
/** * Output logs in format suitable for drush command and clear logs too. * * @throws \RuntimeException * When method is not executed in drush environment. */ public function outputDrush() { // Check for "drush_log" should be done by caller. if (!function_exists('drush_log')) { throw new \RuntimeException('Required global method "drush_log" is not available.'); } $currentLogs = $this->cleanLogs(); foreach ($currentLogs as $logEntry) { if (isset(static::$psrDrushLogLevels[$logEntry[0]])) { $drushLogLevel = static::$psrDrushLogLevels[$logEntry[0]]; } else { $drushLogLevel = $logEntry[0]; } drush_log($logEntry[1], $drushLogLevel); } }
public function install($profile) { $options['account-name'] = drush_prompt(dt('Enter the administrator (uid=1) account name')); $options['account-pass'] = drush_prompt(dt('Enter the administrator (uid=1) password')); $options['account-mail'] = drush_prompt(dt('Enter the administrator (uid=1) e-mail address')); $options['locale'] = drush_prompt(dt('Enter your desired locale')); $options['site-name'] = drush_prompt(dt('Enter the name of your site')); $options['site-mail'] = drush_prompt(dt('Enter the global mail address of your site')); // Setting the options as a drush command specific context so the site install // routine picks it up. drush_set_context('specific', $options); // Determin the major version and launch version specific installation. drush_include_engine('drupal', 'site_install', drush_drupal_major_version()); drush_core_site_install_version($profile, $options); drush_log(dt('Installation finished.'), 'success'); }
public function valid_credentials($db_spec) { $type = $db_spec['driver']; // Check for Drupal support of configured db type. if (file_exists('./includes/install.' . $type . '.inc')) { require_once './includes/install.' . $type . '.inc'; $function = $type . '_is_available'; if (!$function()) { drush_log(dt('!type extension for PHP is not installed. Check your php.ini to see how you can enable it.', array('!type' => $type)), LogLevel::BOOTSTRAP); return FALSE; } } else { drush_log(dt('!type database type is unsupported.', array('!type' => $type)), LogLevel::BOOTSTRAP); return FALSE; } return TRUE; }
public function process(ContainerBuilder $container) { drush_log(dt("process !storage !tag", ['!storage' => $this->storageClassId, '!tag' => $this->tagId]), LogLevel::DEBUG); // We expect that our called registered the storage // class under the storage class id before adding this // compiler pass, but we will test this presumption to be sure. if (!$container->has($this->storageClassId)) { drush_log(dt("storage class not registered"), LogLevel::DEBUG); return; } $definition = $container->findDefinition($this->storageClassId); $taggedServices = $container->findTaggedServiceIds($this->tagId); foreach ($taggedServices as $id => $tags) { drush_log(dt("found tagged service !id", ['!id' => $id]), LogLevel::DEBUG); $definition->addMethodCall('addCommandReference', array(new Reference($id))); } }
public function log($level, $message, array $context = array()) { $message = dt($message, $context); /** * The type of message to be logged. Common types are 'warning', 'error', 'success' and 'notice'. * A type of 'failed' can also be supplied to flag as an 'error'. * A type of 'ok' or 'completed' can also be supplied to flag as a 'success'. * If you want your log messages to print to screen without the user entering * a -v or --verbose flag, use type 'ok', this prints log messages out to * STDERR, which prints to screen (unless you have redirected it). All other * types of messages will be assumed to be notices. * */ if (strcmp($level, 'notice') == 0) { $level = 'ok'; } //Make the level notice equal drush OK so it is printed drush_log($message, $level); }
public function downloadCore() { $www_dir = $this->getProjectDir() . '/' . $this->getDocumentRoot(); if (!is_file($www_dir . '/misc/drupal.js')) { $core_version = $this->getCoreVersion(); $core = "drupal-" . $core_version . ".x"; drush_log(dt('Downloading Drupal core...'), 'status'); drush_set_option('backend', TRUE); drush_set_option('destination', $this->getProjectDir()); drush_set_option('drupal-project-rename', $this->getDocumentRoot()); if (drush_invoke('pm-download', array($core)) === FALSE) { return drush_set_error('', 'Drupal core download/extract failed.'); } drush_set_option('backend', FALSE); } else { drush_log(dt('Drupal already downloaded and unpacked for this project.')); } }
/** * The main Drush function. * * - Parses the command line arguments, configuration files and environment. * - Prepares and executes a Drupal bootstrap, if possible, * - Dispatches the given command. * * @return * Whatever the given command returns. */ function drush_main() { $phases = _drush_bootstrap_phases(); $return = ''; $command_found = FALSE; foreach ($phases as $phase) { if (drush_bootstrap($phase)) { $command = drush_parse_command(); if (is_array($command)) { if ($command['bootstrap'] == $phase && empty($command['bootstrap_errors'])) { drush_log(dt("Found command: !command", array('!command' => $command['command'])), 'bootstrap'); $command_found = TRUE; // Dispatch the command(s). $return = drush_dispatch($command); drush_log_timers(); break; } } } else { break; } } if (!$command_found) { // If we reach this point, we have not found either a valid or matching command. $args = implode(' ', drush_get_arguments()); $drush_command = array_pop(explode('/', DRUSH_COMMAND)); if (isset($command) && is_array($command)) { foreach ($command['bootstrap_errors'] as $key => $error) { drush_set_error($key, $error); } drush_set_error('DRUSH_COMMAND_NOT_EXECUTABLE', dt("The command '!drush_command !args' could not be executed.", array('!drush_command' => $drush_command, '!args' => $args))); } elseif (!empty($args)) { drush_set_error('DRUSH_COMMAND_NOT_FOUND', dt("The command '!drush_command !args' could not be found.", array('!drush_command' => $drush_command, '!args' => $args))); } else { // This can occur if we get an error during _drush_bootstrap_drush_validate(); drush_set_error('DRUSH_COULD_NOT_EXECUTE', dt("Drush could not execute.")); } } // We set this context to let the shutdown function know we reached the end of drush_main(); drush_set_context("DRUSH_EXECUTION_COMPLETED", TRUE); // After this point the drush_shutdown function will run, // exiting with the correct exit code. return $return; }
/** * Log a message, * but output it only if prod_log_level is greater than provided level. * * @param string $message The message * * @param array $variables variables to replace in message * * @param string $level The message level, we use the WATCHDOG_* severity constants * WATCHDOG_EMERGENCY 0 * WATCHDOG_ALERT 1 * WATCHDOG_CRITICAL 2 * WATCHDOG_ERROR 3 * WATCHDOG_WARNING 4 * WATCHDOG_NOTICE 5 * WATCHDOG_INFO 6 * WATCHDOG_DEBUG 7 * * @return TableInterface */ public function log($message, $args = NULL, $level) { if (variable_get('prod_log_level', WATCHDOG_NOTICE) >= $level) { watchdog('Prod', $message, $args, $level); // Using this 'if' because watchdog generates a drush_log call for // other levels if (WATCHDOG_DEBUG === $level) { if (!is_null($args)) { $argstr = ''; foreach ($args as $k => $v) { $argstr .= ', ' . $k . '=' . $v; } drush_log('[P] ' . $message . $argstr, 'ok'); } else { drush_log('[P] ' . $message, 'ok'); } } } }
function bootstrap_and_dispatch() { $phases = $this->bootstrap_init_phases(); $return = ''; $command_found = FALSE; _drush_bootstrap_output_prepare(); foreach ($phases as $phase) { if (drush_bootstrap_to_phase($phase)) { $command = drush_parse_command(); if (is_array($command)) { $command += $this->command_defaults(); // Insure that we have bootstrapped to a high enough // phase for the command prior to enforcing requirements. $bootstrap_result = drush_bootstrap_to_phase($command['bootstrap']); $this->enforce_requirement($command); if ($bootstrap_result && empty($command['bootstrap_errors'])) { drush_log(dt("Found command: !command (commandfile=!commandfile)", array('!command' => $command['command'], '!commandfile' => $command['commandfile'])), 'bootstrap'); $command_found = TRUE; // Dispatch the command(s). $return = drush_dispatch($command); // Prevent a '1' at the end of the output. if ($return === TRUE) { $return = ''; } if (drush_get_context('DRUSH_DEBUG') && !drush_get_context('DRUSH_QUIET')) { // @todo Create version independant wrapper around Drupal timers. Use it. drush_print_timers(); } break; } } } else { break; } } if (!$command_found) { // If we reach this point, command doesn't fit requirements or we have not // found either a valid or matching command. $this->report_command_error($command); } return $return; }
/** * {@inheritdoc} */ public function run($name, $time_limit = 0) { $info = $this->getInfo($name); $function = $info['worker callback']; $end = time() + $time_limit; $queue = $this->getQueue($name); $count = 0; while ((!$time_limit || time() < $end) && ($item = $queue->claimItem())) { try { drush_log(dt('Processing item @id from @name queue.', array('@name' => $name, 'id' => $item->item_id)), LogLevel::INFO); $function($item->data); $queue->deleteItem($item); $count++; } catch (\Exception $e) { // In case of exception log it and leave the item in the queue // to be processed again later. drush_set_error('DRUSH_QUEUE_EXCEPTION', $e->getMessage()); } } return $count; }
public function removeHostsEntry($project_domain) { $hosts_file = drush_get_option('rum-hosts-file', ''); drush_log(dt('Removing host entry from !file', array('!file' => $hosts_file)), 'status'); $hosts_lines = explode("\n", file_get_contents($hosts_file)); $host_available = FALSE; foreach ($hosts_lines as $delta => $host) { if (preg_match("/" . $project_domain . "/", $host)) { unset($hosts_lines[$delta]); $host_available = TRUE; } } // Remove stray empty lines $hosts_lines = array_filter($hosts_lines); if ($host_available) { exec("sudo sh -c 'echo \"" . implode("\n", $hosts_lines) . "\" > /etc/hosts'"); drush_log(dt('Entry %project_domain removed from hosts file', array('%project_domain' => $project_domain)), 'success'); } else { drush_log(dt('Entry %project_domain was not found in hosts file', array('%project_domain' => $project_domain)), 'warning'); } }