drush

Drupal VM 4.8 and Drush 9.0.0 - Some major changes

tl;dr: Drupal VM 4.8.0 was just released, and it uses Drush 9 and Drush Launcher to usher in a new era of Drush integration!

Drush has been Drupal's stable sidekick for many years; even as Drupal core has seen major architectural changes from versions 4 to 5, 5 to 6, 6 to 7, and 7 to 8, Drush itself has continued to maintain an extremely stable core set of APIs and integrations for pretty much all the time I've been using it.

Drush.org homepage
New Drush version, new Drush website!

Speeding up Composer-based Drupal installation

Drupal VM is one of the most flexible and powerful local development environments for Drupal, but one the main goals of the project is to build a fully-functional Drupal 8 site quickly and easily without doing much setup work. The ideal would be to install Vagrant, clone or download the project, then run vagrant up. A few minutes later, you'd have a Drupal 8 site ready for hacking on!

In the past, you always had to do a couple extra steps in between, configuring a drupal.make.yml file and a config.yml file. Recently, thanks in huge part to Oskar Schöldström's herculean efforts, we achieved that ideal by switching from defaulting to a Drush make-based workflow to a Composer-based workflow (this will come in the 3.1.0 release, very soon!). But it wasn't without trial and tribulation!

Ensuring Drush commands run properly using Drush 8.x via Acquia Cloud Hooks

Any time there are major new versions of software, some of the tooling surrounding the software requires tweaks before everything works like it used to, or as it's documented. Since Drupal 8 and Drush 8 are both relatively young, I expect some growing pains here and there.

One problem I ran into lately was quite a head-scratcher: On Acquia Cloud, I had a cloud hook set up that was supposed to do the following after code deployments:

# Build a Drush alias (e.g. [subscription].[environment]).
drush_alias=${site}'.'${target_env}

# Run database updates.
drush @${drush_alias} updb -y

# Import configuration from code.
drush @${drush_alias} cim vcs

This code (well, with fra -y instead of cim) works fine for some Drupal 7 sites I work on in Acquia Cloud, but it seems that database updates were detected but never run, and configuration changes were detected but never made... it took a little time to see what was happening, but I eventually figured it out.

The tl;dr fix?

Adding a role to a user programmatically in Drupal 8

Since a quick Google search didn't bring up how to do this in Drupal 8 (there are dozens of posts on how to do it in Drupal 7), I thought I'd post a quick blog post on how you can modify a user's roles in Drupal 8. Hint: It's a lot easier than you'd think!

In Drupal 7, $user was an object... but it was more like an object that acted like a dumb storage container. You couldn't really do anything with it directly—instead, you had to stick it in functions (like user_multiple_role_edit()) to do things like add or remove roles or modify account information.

In Drupal 8, $user is a real, useful object. Want to modify the account name and save the change?

Preventing yourself from accidentally breaking production with Drush

For all the sites I maintain, I have at least a local and production environment. Some projects warrant a dev, qa, etc. as well, but for the purposes of this post, let's just assume you often run drush commands on local or development environments during development, and eventually run a similar command on production during a deployment.

What happens if, at some point, you are churning through some Drush commands, using aliases (e.g. drush @site.local break-all-the-things to break things for testing), and you accidentally enter @site.prod instead of @site.local? Or what if you were doing something potentially disastrous, like deleting a database table locally so you can test a module install file, using drush sqlq to run a query?

$ drush @site.prod break-all-the-things -y
Everything is broken!                                    [sadpanda]

How to set complex string variables with Drush vset

I recently ran into an issue where drush vset was not setting a string variable (in this case, a time period that would be used in strtotime()) correctly:

# Didn't work:
$ drush vset custom_past_time '-1 day'
Unknown options: --0, --w, --e, --k.  See `drush help variable-set`      [error]
for available options. To suppress this error, add the option
--strict=0.

Using the --strict=0 option resulted in the variable being set to a value of "1".

After scratching my head a bit, trying different ways of escaping the string value, using single and double quotes, etc., I finally realized I could just use variable_set() with drush's php-eval command (shortcut ev):

# Success!
$ drush ev "variable_set('custom_past_time', '-1 day');"
$ drush vget custom_past_time
custom_past_time: '-1 day'

This worked perfectly and allowed me to go make sure my time was successfully set to one day in the past.

Quickly resetting a local MySQL database from the command line [Updated]

[Update: And, as quickly as I finished writing this post, I thought to myself, "surely, this would be a good thing to have drush do out-of-the-box. And... it already does, making my work on this shell script null and void. I present to you: drush sql-drop! Oh, well.]

When I'm creating or updating an installation profile/distribution for Drupal, I need to reinstall Drupal over and over again. Doing this requires a few simple steps: drop/recreate the database (or drop all db tables), then drush site-install (shortcut: si) with the proper arguments to install the site again.

In the past, I've often had Sequel Pro running in the background on my Mac, and I'd select all the database tables, right-click, choose 'Delete Tables', then have to click again on a button to confirm the deletion. This took maybe 10-20 seconds, depending on whether I already had Sequel Pro running, and how good my mouse muscles were working.

Setting a max_execution_time limit for PHP CLI

PHP's command line interface doesn't respect the max_execution_time limit within your php.ini settings. This can be both a blessing and a curse (but more often the latter). There are some drush scripts that I run concurrently for batch operations that I want to make sure don't run away from me, because they perform database operations and network calls, and can sometimes slow down and block other operations.

Memory usage - PHP and MySQL locked from runaway threads
Can you tell when the batch got backlogged? CPU usage spiked to 20, and threads went from 100 to 400.

I found that some large batch operations (where there are hundreds of thousands of items to work on) would hold the server hostage and cause a major slowdown, and when I went to the command line and ran:

$ drush @site-alias ev "print ini_get('max_execution_time');"

My Simple, but Nerve-Calming, drush Update Workflow

Just posted for my own reference - here's my workflow for updating a D6 (probably also D7) website using drush. Comprehensive information about all drush commands can be found on the http://drush.ws/ website. If you're not yet drinking the drush kool-aid, you need to—if you use a Linux server, of course.

  1. Visit admin/reports/updates page on your site, read through any relevant release notes for required updates (to check if there are special requirements for said update).
  2. $ drush @site pm-updatecode <module1_shortname> <module2_shortname> (add all modules to be updated)
  3. $ drush @site updatedb (updates the site database - update.php)
  4. $ drush @site cc all (clears all caches on the site)

The reason I do this manually, instead of running something like pm-update or pm-updatecode is that I like the granularity and security of doing all the updates discretely—especially when I'm updating a larger site, where I like to know exactly what's happening when I update.