This is a very rough proof of concept patch, but the basic idea is to provide a simple command that gets users a working Drupal site, with nothing but php and Drush installed and with as close to zero configuration as possible.

To use it, run something like "drush -y qd mysite", and the command will:
- Download the latest stable Drupal into ./mysite/drupal.
- Install it, using SQLite at ./mysite/mysite.sqlite for the database.
- Generate a login link for user 1
- Initiate runserver to serve the site
- Open the default browser with the login link

While you can easily do each of these things separately, this just seems really convenient - both for new developers who just want to get started with minimum hassle, and for other developers who maintain different sandboxes for different core/contrib patches/projects (and have sample config/content appropriate to each patch).

I had trouble coming up with a descriptive enough name for this - in the end I went with with "quick-drupal", but I guess "auto", "start" or some other phrasing may make more sense. Also no idea if this should be with core, or part of runserver.

The command should accept almost any available option for each of the subcommands, so is pretty flexible. It is also pretty quick (especially with --cache - 13 seconds on my laptop), and it manages to do all the steps in a single incremental bootstrap. I am not 100% sure about the browser opening, skipping this may be better - it does work for me though (didn't test on OS X, although in theory "open" should do it). An interesting addition could be if arguments (after the site name) could accept contrib modules to download (and enable if drush can figure out the name).

Feedback welcome!

Members fund testing for the Drupal project. Drupal Association Learn more


znerol’s picture

I usually bootstrap my sandboxes with an sqlite databases in /dev/shm on Linux. Would be nice to have that as an option.

greg.1.anderson’s picture

This works with Firefox, but hangs up after launching Chrome (does not return until browser closes; need to background the launch somehow. & did not work).

The site-install portion of this patch works on Windows now (with other fixes, committed in other issues), but I still need to load the PDO libraries for sqlite and php-cgi to test run-server.

I could not find a good way to launch the preferred browser on Windows, and the installed browsers tend to not be on your path. The best suggestion I have here is perhaps just launch IE by default; it should always be found at C:\Program Files\Internet Explorer\iexplore.exe, and will open the URL specified by its first parameter. Perhaps we could also provide an option that allows the user to specify which browser to launch. (Also, there might be a better way to find the preferred browser in Windows.)

moshe weitzman’s picture

we could have the command return an URL and also add a couple example shell aliases that people can customize like

!C:\Program Files\Internet Explorer\iexplore.exe `drush qd`
!open `drush qd`
greg.1.anderson’s picture

In its current incarnation, the last thing that 'qd' does is call run-server; run-server in turn blocks until the user hits control-c, and then stops. This behavior would have to change in order for #3 to work.

moshe weitzman’s picture

Status: Needs review » Needs work

Looks good. We need to add more docs about available options. See site-install and pm-download and list the relevant ones like db-url, --package-handler, etc ... Document the argument ... Also, add a couple Examples in command array.

command array should state that it requires drupal 7. lets also declare drush dependencies on pm-downloadn and site-install even though those should always be present. this is a tipoff to command authors.

We have a user command for getting a one time login link. Might want to use drush_invoke() for that.

Some Field commands return an URL so whatever we do here we need to do there too.

moshe weitzman’s picture

Assigned: Unassigned » Owen Barton

Seems pretty close to me. Assigning to Owen though anyone could add the remaining bits.

moshe weitzman’s picture

Assigned: Owen Barton » Unassigned
4.22 KB

I expanded the help a lot. See attached.

Unfortunately, the race condition loses for me. I get an error in my browser because the http server is not up yet. A subsequent browser refresh works, of course. Any thoughts on how to fix?

Also, command specific options for internal invokes are not honored here. For example, in my drushrc I have $command_specific['site-install']['account-pass'] = 'admin';. I would have to make that global or copy it to core-quick-drupal to have it be effective. Should we do anything about this?

greg.1.anderson’s picture

I think it would be hard to support command-specific options for subcommands launched via drush_invoke. Well, it would not be hard, but if we supported it, the command-specific options for the subcommand would pollute the environment of the calling command. Maybe that is not so bad.

If we changed the call to site-install to be drush_invoke_process instead of drush_invoke, then we could support command-specific options cleanly. Either way, I could pick that task up in a separate issue.

moshe weitzman’s picture

i think drush_invoke_process('site-install') makes sense here. It should not be slow, as we are not dealing with an installed drupal site yet. perhaps we do same for the pm-download as well.

in irc, we talked about opening the browser in a subprocess whose code is like proc_open('while ( ping == 0 ) done; start browser"). this fixes the race condition and browsers that block.

Owen Barton’s picture

Status: Needs work » Needs review
2.25 KB

Here is a rough sketch of the proc_open check to fix the race condition. I included a built in timer, so after a certain number of runs it will just start the browser anyway (rather than hang out running curl forever). It seems to work pretty well for me. Not sure if the bash & curl dependency is a concern - an alternative is perhaps to make a little standalone php wrapper. Thoughts?

Just realized this missed the docs in the previous patch. Todos are to include those (I wonder if there is a way we can merge them from the origin commands, rather than duplicating the text?), to write some basic validation for the things we can't magically fix or gracefully fail on, and add some magic/grace as needed ;)

greg.1.anderson’s picture

Maybe to be forward-thinking, the proc open script could be factored into a separate function that used drush_is_windows to return a different script for windows than linux. For the initial implementation, the windows version could just run the browser ("let them press refresh").

As I type this, I realise that under mingw, the bash script would probably work, and the windows-specific script would probably fail. Maybe what we really need is some way to tell if drush was called by the drush wrapper or by drush.bat (add a commandline option in drush.bat?), and decide on the script to use from that setting.

I don't know how much work we want to do on Windows prior to the first commit, though.

Owen Barton’s picture

Status: Needs work » Needs review


Owen Barton’s picture

83.93 KB

Been working offline last week, and attached patch includes a fair amount of work on both this issue and some related work on runserver (in retrospect I probably should have split this into two patches). Description of changes since the previous patch below:

* Can now start browser (without any race or the nasty shell loop) when runserver comes up by overriding the httpserver listening() event/method.
* Have a general purpose utility function to start browser, as well as a new --browser option that allows you to set a specific browser, or turn it off completely (this could be global, or we could just include in commands that use the browser...thoughts?).
* Reworked the runserver addr:host parsing code so that you can include a path, ensure all the elements are optional and allow a default addr:host/path that is merged in. If a path is present a browser will be started on that path. Interested in thoughts if runserver should open a browser by default (and if so what path), or only if a path is specified (as we do now).
* I also added a --dns option - if this is set you can use hostnames in the addr:port/path spec and it will ask DNS for the IP to bind to, or you can use IPs and it will ask rDNS to get a friendly hostname for the browser. Not sure if this should be set by default or not...needs some more testing I think.
* Also added functionality so that if you include the --user option with runserver (and we use --user=1 from quick-drupal) it will initially log in that user via the prepend file. Currently off by default - though potentially this could be on by default if we think this is better - thoughts?
* There is also a --watchdog option that will collect watchdog messages in drupal, and output them as part of the runserver log (also off by default, but open to ideas). This is somewhat of a proof of concept - I would love to make this pluggable somehow - so for example devel could allow allow the user to print queries, xhprof stats, or allow devs to send arbitrary print_r($var) to the runserver log.
* If --debug is set for runserver, it will display the entire request/response object for each request, which is pretty handy when you need it.
* Improved quick-drupal docs (reusing docs from other commands, rather than duplicating).
* Ability to specify quick-drupal arguments for contrib projects to install into the new site. Extensions with the same name as projects are enabled by default, with an --enable option if you want to specify this manually. Interested in other ways of managing this (will be easier when we get a pm-install command).
* Better error checking for commands/bootstrap for quick-drupal. I played with drush_invoke_process(), but in the end stuck with drush_invoke() since it seemed to work fine.
* Added a --server and --browser options that controls the runserver addr:host/path for quick-drupal and browser selection.

I am going to try and add some tests for both of these - I am thinking of making it possible to force runserver to exit after a single request, which would allow us to test both commands (and most of the options) pretty reasonably. If we use wget as the "browser" we can test that functionality too.

Owen Barton’s picture

23.67 KB

Previous patch was borked - use this one instead. I also forgot to mention one other change (and the only one that has potential to affect existing code) - drush_invoke() was not returning the command return value (as it says it does in the doxygen), but was instead just returning TRUE/FALSE on success/fail - it should now return the command return (which could be a string or whatever) or FALSE on fail.

moshe weitzman’s picture

Status: Needs review » Needs work

Code looks good to me. Only two things popped up

  • Drush also declares system_watchdog(). Can we not get duplicate function error?
  • In the rollback case, drush_invoke() used to return !$rollback but now it returns $rollback. Is OK?
greg.1.anderson’s picture

Yeah, this looks awesome; I just need it to support install profiles, and it will help me a lot. It's fine by me to do that in a separate issue; I'll help out as time permits.

Owen Barton’s picture

25.19 KB

Updated patch fixes the $rollback issue noted above (system_watchdog is inside the cgi process so shouldn't be duplicate). Also now works with install profiles. Added some more examples.

I think this is basically ready to go.

Owen Barton’s picture


greg.1.anderson’s picture

Status: Needs review » Fixed


Status: Fixed » Closed (fixed)

Automatically closed -- issue fixed for 2 weeks with no activity.

moshe weitzman’s picture

Issue tags: +Needs change record

Needs change notification for this and runserver

moshe weitzman’s picture

Issue tags: -Needs change record

Added change notice at