diff --git a/12.x/dependency-injection/index.html b/12.x/dependency-injection/index.html index a723cd9e75..9fc6e4325a 100644 --- a/12.x/dependency-injection/index.html +++ b/12.x/dependency-injection/index.html @@ -5259,7 +5259,8 @@
12.5+
-Command files may inject Drush and Drupal services by adding the AutowireTrait to the class (example: PmCommands). This enables your Constructor parameter type hints determine the the injected service. When a type hint is insufficient, an #[Autowire] Attribute on the constructor property (with service: named argument) directs AutoWireTrait to the right service (example: LoginCommands).
+Command files may inject Drush and Drupal services by adding the AutowireTrait to the class (example: MaintCommands). This enables your Constructor parameter type hints determine the the injected service. When a type hint is insufficient, an #[Autowire] Attribute on the constructor property (with +service: named argument) directs AutoWireTrait to the right service.
If your command is not found by Drush, add the -vvv
option for debug info about any service instantiation errors. If Autowire is still insufficient, a commandfile may implement its own create()
method (see below).
11.6+
@@ -5313,7 +5314,7 @@Drush is a command line shell and Unix scripting interface for Drupal. Drush core ships with lots of useful commands and generators. Similarly, it runs update.php, executes SQL queries, runs content migrations, and misc utilities like cron or cache rebuild. Drush can be extended by 3rd party commandfiles.
"},{"location":"#resources","title":"Resources","text":"
A: The Drupal Shell.
"},{"location":"#how-do-i-pronounce-drush","title":"How do I pronounce Drush?","text":"Some people pronounce the dru with a long 'u' like Drupal. Fidelity points go to them, but they are in the minority. Most pronounce Drush so that it rhymes with hush, rush, flush, etc. This is the preferred pronunciation.
"},{"location":"#credits","title":"Credits","text":"When preparing to run a command, Drush works by bootstrapping the Drupal environment in very much the same way that is done during a normal page request from the web server, so most Drush commands run in the context of a fully-initialized website.
For efficiency and convenience, some Drush commands can work without first bootstrapping a Drupal site, or by only partially bootstrapping a site. This is faster than a full bootstrap. It is also a matter of convenience, because some commands are useful even when you don't have a working Drupal site.
Commands may specify their bootstrap level with via an attribute or an annotation. Commands supplied by Drupal modules are always full
.
use Drush\\Attributes as CLI;\n\n#[CLI\\Bootstrap(level: DrupalBootLevels::NONE)]\npublic function fetch($search = null, $options = ['image-viewer' => 'open', 'google-custom-search-api-key' => 'AIza']) {\n $this->doFetch($search, $options);\n}\n
/**\n * @bootstrap none\n*/\npublic function fetch($search = null, $options = ['image-viewer' => 'open', 'google-custom-search-api-key' => 'AIza']) {\n $this->doFetch($search, $options);\n}\n
Prior to bootstrapping, Drush goes through the preflight process, where the following things occur:
Preflight
bootstrap @full
. Bootstrapping is done from a Symfony Console command hook. The different bootstrap levels are described below.
"},{"location":"bootstrap/#none","title":"none","text":"Only run Drush preflight, without considering Drupal at all. Any code that operates on the Drush installation, and not specifically any Drupal directory, should bootstrap to this phase. This Attribute and value may also be used on a command class when it wants to load before Drupal bootstrap is started. Commands that ship inside Drupal modules always bootstrap to full, regardless of none value.
"},{"location":"bootstrap/#root","title":"root","text":"Set up and test for a valid Drupal root, either through the --root options, or evaluated based on the current working directory. Any code that interacts with an entire Drupal installation, and not a specific site on the Drupal installation should use this bootstrap phase.
"},{"location":"bootstrap/#site","title":"site","text":"Set up a Drupal site directory and the correct environment variables to allow Drupal to find the configuration file. If no site is specified with the --uri options, Drush will assume the site is 'default', which mimics Drupal's behaviour. Note that it is necessary to specify a full URI, e.g. --uri=http://example.com, in order for certain Drush commands and Drupal modules to behave correctly. See the Drush configuration for more information. Any code that needs to modify or interact with a specific Drupal site's settings.php file should bootstrap to this phase.
"},{"location":"bootstrap/#configuration","title":"configuration","text":"Load the settings from the Drupal sites directory. This phase is analogous to the DRUPAL_BOOTSTRAP_CONFIGURATION bootstrap phase in Drupal itself, and this is also the first step where Drupal specific code is included. This phase is commonly used for code that interacts with the Drupal install API, as both install.php and update.php start at this phase.
"},{"location":"bootstrap/#database","title":"database","text":"Connect to the Drupal database using the database credentials loaded during the previous bootstrap phase. This phase is analogous to the DRUPAL_BOOTSTRAP_DATABASE bootstrap phase in Drupal. Any code that needs to interact with the Drupal database API needs to be bootstrapped to at least this phase.
"},{"location":"bootstrap/#full","title":"full","text":"Fully initialize Drupal. This is analogous to the DRUPAL_BOOTSTRAP_FULL bootstrap phase in Drupal. Any code that interacts with the general Drupal API should be bootstrapped to this phase.
"},{"location":"bootstrap/#max","title":"max","text":"This is not an actual bootstrap phase. Commands that use the \"max\" bootstrap level will cause Drush to bootstrap as far as possible, and then run the command regardless of the bootstrap phase that was reached. This is useful for Drush commands that work without a bootstrapped site, but that provide additional information or capabilities in the presence of a bootstrapped site. For example, drush status
will show progressively more information the farther the site bootstraps.
Tip
<module-name>/src/Drush/<Commands|Generators>
directory. The Drush
subdirectory is a new requirement.Creating a new Drush command is easy. Follow the steps below.
drush generate drush:command-file
.drush generate module
to create a new module.The following are both valid ways to declare a command:
PHP8 AttributesAnnotationsuse Drush\\Attributes as CLI;\n\n/**\n * Retrieve and display xkcd cartoons (attribute variant).\n */\n#[CLI\\Command(name: 'xkcd:fetch-attributes', aliases: ['xkcd-attributes'])]\n#[CLI\\Argument(name: 'search', description: 'Optional argument to retrieve the cartoons matching an index, keyword, or \"random\".')]\n#[CLI\\Option(name: 'image-viewer', description: 'Command to use to view images (e.g. xv, firefox).', suggestedValues: ['open', 'xv', 'firefox'])]\n#[CLI\\Option(name: 'google-custom-search-api-key', description: 'Google Custom Search API Key')]\n#[CLI\\Usage(name: 'drush xkcd', description: 'Retrieve and display the latest cartoon')]\n#[CLI\\Usage(name: 'drush xkcd sandwich', description: 'Retrieve and display cartoons about sandwiches.')]\npublic function fetch($search = null, $options = ['image-viewer' => 'open', 'google-custom-search-api-key' => 'AIza']) {\n $this->doFetch($search, $options);\n}\n
/**\n * @command xkcd:fetch\n * @param $search Optional argument to retrieve the cartoons matching an index number, keyword, or \"random\".\n * @option image-viewer Command to use to view images (e.g. xv, firefox).\n * @option google-custom-search-api-key Google Custom Search API Key.\n * @usage drush xkcd\n * Retrieve and display the latest cartoon.\n * @usage drush xkcd sandwich\n * Retrieve and display cartoons about sandwiches.\n * @aliases xkcd\n*/\npublic function fetch($search = null, $options = ['image-viewer' => 'open', 'google-custom-search-api-key' => 'AIza']) {\n $this->doFetch($search, $options);\n}\n
Drush command info (annotations/attributes) can be altered from other modules. This is done by creating and registering command info alterers. Alterers are classes that are able to intercept and manipulate an existing command annotation.
In the module that wants to alter a command info, add a class that:
Drupal\\<module-name>\\Drush\\CommandInfoAlterers
and the class file should be located under the src/Drush/CommandInfoAlterers
directory.Foo
can be whatever string you want. The file must end in CommandInfoAlterer.php
.\\Consolidation\\AnnotatedCommand\\CommandInfoAltererInterface
.alterCommandInfo()
method.For an example, see WootCommandInfoAlterer provided by the testing 'woot' module.
"},{"location":"commands/#symfony-console-commands","title":"Symfony Console Commands","text":"Drush lists and runs Symfony Console commands, in addition to more typical annotated commands. See this test and this commandfile.
"},{"location":"commands/#auto-discovered-commands-psr4","title":"Auto-discovered commands (PSR4)","text":"Such commands are auto-discovered by their class PSR4 namespace and class/file name suffix. Drush will auto-discover commands if:
Drush\\Commands
. For instance, if a Drush command provider third party library maps this PSR4 autoload entry: \"autoload\": {\n\"psr-4\": {\n\"My\\\\Custom\\\\Library\\\\\": \"src\"\n}\n}\n
then the Drush global commands class namespace should be My\\Custom\\Library\\Drush\\Commands
and the class file should be located under the src/Drush/Commands
directory.*DrushCommands
, e.g. FooDrushCommands
.Auto-discovered commandfiles should declare their Drush version compatibility via a conflict
directive. For example, a Composer-managed site-wide command that works with both Drush 11 and Drush 12 might contain something similar to the following in its composer.json file:
\"conflict\": {\n\"drush/drush\": \"<11.0\",\n}\n
Using require
in place of conflict
is not recommended. Symlinked packages
While it is good practice to make your custom commands into a Composer package, please beware that symlinked packages (by using the composer repository type Path) will not be discovered by Drush. When in development, it is recommended to specify your package's path in your drush.yml
to have quick access to your commands.
Commandfiles that are installed in a Drupal site and are not bundled inside a Drupal module are called site-wide commandfiles. Site-wide commands may either be added directly to the Drupal site's repository (e.g. for site-specific policy files), or via composer require
. See the examples/Commands folder for examples. In general, it's preferable to use modules to carry your Drush commands.
Here are some examples of valid commandfile names and namespaces:
Note: Make sure you do not include src
in the path to your command. Your command may not be discovered and have additional problems.
If a commandfile is added via a Composer package, then it may declare any dependencies that it may need in its composer.json file. Site-wide commandfiles that are committed directly to a site's repository only have access to the dependencies already available in the site.
A site-wide commandfile should have tests that run with each (major) version of Drush that is supported. You may model your test suite after the example drush extension project.
"},{"location":"commands/#global-commands-discovered-by-configuration","title":"Global commands discovered by configuration","text":"Deprecation
Configuration discovery has been deprecated and will be removed in a future version of Drush. It is recommended that you avoid global Drush commands, and favor site-wide or PSR4 discovered commandfiles instead. If you really need commands that are not part of any Drupal site, consider making a stand-alone script or custom .phar instead. See ahoy, Robo and g1a/starter as potential starting points.
Global commandfiles discoverable by configuration are not supported by default; in order to enable them, you must configure your drush.yml
configuration file to add an include
search location.
For example:
drush:\npaths:\ninclude:\n- '${env.home}/.drush/commands'\n
With this configuration in place, global commands may be placed as described in the Site-Wide Drush Commands section above. Global commandfiles may not declare any dependencies of their own; they may only use those dependencies already available via the autoloader. Tip
Example
can be whatever string you want.Commands.php
Commands
must be one of:Drush provides commands to export, pull, and import Drupal configuration files.
"},{"location":"config-exporting/#simple-value-changes","title":"Simple - value changes","text":"It is not necessary to alter configuration values to make simple value changes to configuration variables, as this may be done by the configuration override system.
The configuration override system allows you to change configuration values for a given instance of a site (e.g. the development server) by setting configuration variables in the site's settings.php file. For example, to change the name of a local development site:
$config['system.site']['name'] = 'Local Install of Awesome Widgets, Inc.';\n
Note that the configuration override system is a Drupal feature, not a Drush feature. It should be the preferred method for changing configuration values on a per-environment basis; however, it does not work for some things, such as enabling and disabling modules."},{"location":"config-exporting/#advanced-variation-by-environment","title":"Advanced - variation by environment","text":"Drupal cron tasks are often set up to be run via a wget/curl call to cron.php; this same task can also be accomplished via the cron command, which circumvents the need to provide a web server interface to cron.
"},{"location":"cron/#quick-start","title":"Quick start","text":"If you just want to get started quickly, here is a crontab entry that will run cron once every hour at ten minutes after the hour:
10 * * * * cd [DOCROOT] && /usr/bin/env PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin COLUMNS=72 ../vendor/bin/drush --uri=your.drupalsite.org --quiet maint:status && /vendor/bin/drush --uri=your.drupalsite.org --quiet cron\n
You should set up crontab to run your cron tasks as the same user that runs the web server; for example, if you run your web server as the user www-data:
sudo crontab -u www-data -e\n
You might need to edit the crontab entry shown above slightly for your particular setup; for example, if you have installed Drush to some directory other than /usr/local/drush, then you will need to adjust the path to drush appropriately. We'll break down the meaning of each section of the crontab entry in the documentation that continues below.
"},{"location":"cron/#setting-the-schedule","title":"Setting the schedule","text":"See man 5 crontab
for information on how to format the information in a crontab entry. In the example above, the schedule for the crontab is set by the string 10 * * * *
. These fields are the minute, hour, day of month, month and day of week; *
means essentially 'all values', so 10 * * * *
will run any time the minute == 10 (once every hour).
We use /usr/bin/env to run Drush so that we can set up some necessary environment variables that Drush needs to execute. By default, cron will run each command with an empty PATH, which would not work well with Drush. To find out what your PATH needs to be, just type:
echo $PATH\n
Take the value that is output and place it into your crontab entry in the place of the one shown above. You can remove any entry that is known to not be of interest to Drush (e.g. /usr/games), or is only useful in a graphic environment (e.g. /usr/X11/bin).
"},{"location":"cron/#setting-columns","title":"Setting COLUMNS","text":"When running Drush in a terminal, the number of columns will be automatically determined by Drush by way of the tput command, which queries the active terminal to determine what the width of the screen is. When running Drush from cron, there will not be any terminal set, and the call to tput will produce an error message. Spurious error messages are undesirable, as cron is often configured to send email whenever any output is produced, so it is important to make an effort to insure that successful runs of cron complete with no output.
In some cases, Drush is smart enough to recognize that there is no terminal -- if the terminal value is empty or \"dumb\", for example. However, there are some \"non-terminal\" values that Drush does not recognize, such as \"unknown.\" If you manually set COLUMNS
, then Drush will respect your setting and will not attempt to call tput.
By default, Drush will print a success message when the run of cron is completed. The --quiet flag will suppress these and other progress messages, again avoiding an unnecessary email message.
"},{"location":"cron/#specifying-the-drupal-site-to-run","title":"Specifying the Drupal site to run","text":"There are many ways to tell Drush which Drupal site to select for the active command, and any may be used here. The example uses cd [DOCROOT]
, but you could also use the --root and --uri flags.
The call to maint:status checks to see if the site is in maintenance mode. If yes, cron will not run and the command returns a failure. It is not safe to run cron while the site is in maintenance. See https://drupal.slack.com/archives/C45SW3FLM/p1675287662331809.
"},{"location":"dependency-injection/","title":"Dependency Injection","text":"Drush command files obtain references to the resources they need through a technique called dependency injection. When using this programing paradigm, a class by convention will never use the new
operator to instantiate dependencies. Instead, it will store the other objects it needs in class variables, and provide a way for other code to assign an object to that variable.
Tip
Drush 11 and prior required dependency injection via a drush.services.yml file. This approach is deprecated in Drush 12+.
"},{"location":"dependency-injection/#autowire","title":"Autowire","text":"12.5+
Command files may inject Drush and Drupal services by adding the AutowireTrait to the class (example: PmCommands). This enables your Constructor parameter type hints determine the the injected service. When a type hint is insufficient, an #[Autowire] Attribute on the constructor property (with service: named argument) directs AutoWireTrait to the right service (example: LoginCommands).
If your command is not found by Drush, add the -vvv
option for debug info about any service instantiation errors. If Autowire is still insufficient, a commandfile may implement its own create()
method (see below).
11.6+
Command files not using Autowire may inject services by adding a create() method to the commandfile. The passed in Container is a League container with a delegate to the Drupal container. Note that the type hint should be to Psr\\Container\\ContanierInterface
not Symfony\\Component\\DependencyInjection\\ContainerInterface
. A create() method and constructor will look something like this:
class WootStaticFactoryCommands extends DrushCommands\n{\n protected $configFactory;\n\n protected function __construct($configFactory)\n {\n $this->configFactory = $configFactory;\n }\n\n public static function create(Psr\\Container\\ContainerInterface $container): self\n {\n return new static($container->get('config.factory'));\n }\n
See the Drupal Documentation for details on how to inject Drupal services into your command file. This approach mimics Drupal's blocks, forms, and controllers."},{"location":"dependency-injection/#createearly-method","title":"createEarly() method","text":"12.0+
The createEarly()
method was deprecated in Drush 12.5. Instead put a #[CLI\\Bootstrap(DrupalBootLevels::NONE)]
Attribute on the command class and inject dependencies via the usual __construct
with AutowireTrait.
Note also that Drush commands packaged with Drupal modules are not discovered until after Drupal bootstraps, and therefore cannot use createEarly()
. This mechanism is only usable by PSR-4 discovered commands packaged with Composer projects that are not Drupal modules.
A command class may implement the following interfaces. When doing so, implement the corresponding trait to satisfy the interface.
10.3+
The deploy command standardizes how Drupal deployments work. The intent is your deployment script updates the codebase for the target site and then this command performs the following:
drush updatedb --no-cache-clear\ndrush cache:rebuild\ndrush config:import\ndrush cache:rebuild\ndrush deploy:hook\n
"},{"location":"deploycommand/#authoring-update-functions","title":"Authoring update functions","text":"Below are the 3 types of update functions run by this command, in order. Choose the most appropriate for your need.
Function Drupal API Purpose HOOK_update_n() Not allowed Low level changes. HOOK_post_update_NAME() Allowed Runs before config is imported. HOOK_deploy_NAME() Allowed Runs after config is imported."},{"location":"deploycommand/#configuration","title":"Configuration","text":"If you need to customize this command, you should use Drush configuration for the subcommands listed above (e.g. updatedb, config:import, etc.).
"},{"location":"generators/","title":"Overview","text":"Tip
Drush 11 and prior required generators to define a drush.services.yml file. This is no longer used with Drush 12+ generators. See docs for injecting dependencies..
Generators jump start your coding by building all the boring boilerplate code for you. After running the generate command, you have a guide for where to insert your custom logic.
Drush's generators reuse classes provided by the excellent Drupal Code Generator project. See its Commands directory for inspiration.
"},{"location":"generators/#writing-custom-generators","title":"Writing Custom Generators","text":"Drupal modules may supply their own Generators, just like they can supply Commands.
See Woot module, which Drush uses for testing. Specifically,
Generators that don't ship inside Drupal modules are called global generators. For example see CustomDrushGenerator. In general, it is better to use modules to carry your generators. If you still prefer using a global generator, please note:
Drush\\Generators
. For instance, if a Drush generator provider third party library maps this PSR4 autoload entry: \"autoload\": {\n\"psr-4\": {\n\"My\\\\Custom\\\\Library\\\\\": \"src\"\n}\n}\n
then the Drush global generator class namespace should be My\\Custom\\Library\\Drush\\Generators
and the class file should be located under the src/Drush/Generators
directory.Foo
can be whatever string you want. The file must end in Generator.php
.Sitewide generators (as opposed to auto-discovered PSR4) have a namespace that starts with \\Drush\\Generators
, the directory above Generators must be one of: 1. A Folder listed in the --include option. include may be provided via config or via CLI. 1. ../drush
, /drush
or /sites/all/drush
. These paths are relative to Drupal root.
All commandfiles may implement methods that are called by Drush at various times in the request cycle. To implement one, add a #[CLI\\Hook(type: HookManager::ARGUMENT_VALIDATOR, target: 'pm:install')]
(for example) to the top of your method. The class constants for hooks are located in HookManager.
Drush commands can define custom events that other command files can hook. You can find examples in CacheCommands and SanitizeCommands
First, the command must implement CustomEventAwareInterface and use CustomEventAwareTrait, as described in the dependency injection documentation.
Then, the command may ask the provided hook manager to return a list of handlers with a certain attribute. In the example below, the my-event
label is used:
/**\n * This command uses a custom event 'my-event' to collect data. Note that\n * the event handlers will not be found unless the hook manager is\n * injected into this command handler object via `setHookManager()`\n * (defined in CustomEventAwareTrait).\n */\n #[CLI\\Command(name: 'example:command')] \n public function exampleCommand()\n {\n $myEventHandlers = $this->getCustomEventHandlers('my-event');\n $result = [];\n foreach ($myEventHandlers as $handler) {\n $result[] = $handler();\n }\n sort($result);\n return implode(',', $result);\n }\n
Other commandfiles may provide implementations via a PHP8 Attribute or an Annotation.
PHP8 AttributesAnnotations/**\n * #[CLI\\Hook(type: HookManager::ON_EVENT, target: 'my-event')]\n */\npublic function hookOne()\n{\n return 'one';\n}\n
/**\n * @hook on-event my-event\n */\npublic function hookOne()\n{\n return 'one';\n}\n
"},{"location":"install/","title":"Install","text":"Tip
Drush only supports one install method. It requires that your Drupal site be built with Composer and Drush be listed as a dependency.
See the Drush 8 or Drush 9 docs for installing prior versions of Drush.
composer require drush/drush
to add it.vendor/bin/drush
. To simplify things, add ./vendor/bin
to your $PATH
, allowing you to call Drush via drush
from the project root. If you have only one Drupal codebase on your system, you may put /path/to/vendor/bin
in your $PATH
; now you can call Drush from everywhere, without having to change to project root.drush completion --help
for more details. Note
PATH=/path/to/php:$PATH
drush status ...`$this->io()
.$this->io()->choice()
and $this->io()->confirm()
.10.4+
The Migrate API delivers services for migrating data from a source system to Drupal. This API is provided by the core migrate
module. In order to migrate data to Drupal, you'll need to create migrations for each type of destination data.
These commands are an alternative to https://www.drupal.org/project/migrate_tools. Don't use that module if you use these commands.
"},{"location":"migrate/#defining-migrations","title":"Defining migrations","text":"Learn how to create migrations from the Drupal official documentation:
Drush provides a set of commands that allows to run migration operations such as importing, checking the current status of migrations, rolling-back migrations, stopping an ongoing migration, etc. Such commands are available only when the migrate
module is enabled. In order the get a full list of migrate commands, type:
drush --filter=migrate\n
To get help on each command run drush with the command name as parameter and the --help
option. For example next command will show details about the migrate:import Drush command:
drush migrate:import --help\n
"},{"location":"output-formats-filters/","title":"Output Formats, Fields and Filters","text":"Drush utilizes a powerful formatting and filtering system that provides the user with a lot of control over how output from various commands is rendered.
The --format
option may be used to select the data format used to print the output of a command. Most commands that produce informative output about some object or system can transform their data into different formats. For example, the version command may be printed in a human-readable table (the default), or in a json array:
$ drush version\n Drush version : 10.3.1\n$ drush version --format=json\n{\n\"drush-version\": \"10.3.1\"\n}\n
The available output formats are shown in the help
for each command: $ drush help version\nShow drush version.\n\nOptions:\n --format=<json> Select output format. Available: json, string, var_export, yaml. Default is key-value.\n
"},{"location":"output-formats-filters/#output-fields","title":"Output Fields","text":"If you wish to limit the number of columns produced by a command, use the --fields
option. List the field names in the order they should be displayed:
$ drush views:list --fields=machine-name,status\n+-------------------+----------+\n| Machine name | Status |\n+-------------------+----------+\n| block_content | Enabled |\n| comment | Enabled |\n| comments_recent | Enabled |\n| content | Enabled |\n| content_recent | Enabled |\n| files | Enabled |\n| frontpage | Enabled |\n| taxonomy_term | Enabled |\n| user_admin_people | Enabled |\n| watchdog | Enabled |\n| who_s_new | Enabled |\n| who_s_online | Enabled |\n| archive | Disabled |\n| glossary | Disabled |\n+-------------------+----------+\n
The available field names are shown in the help
text: $ drush help views:list\nGet a list of all views in the system.\n\nOptions:\n --fields=FIELDS Available fields: Machine name (machine-name), Name (label), Description (description), Status (status), Tag (tag) [default: \"machine-name,label,description,status\"]
Fields may be named either using their human-readable name, or via their machine name. Note also that some commands do not display all of their available data columns by default. To show all available fields, use --fields=*
There is also a singular form --field
available. If this form is used, it will also force the output format to string
.
$ drush views:list --field=machine-name \nblock_content\ncomment\ncomments_recent\ncontent\ncontent_recent\nfiles\nfrontpage\ntaxonomy_term\nuser_admin_people\nwatchdog\nwho_s_new\nwho_s_online\narchive\nglossary\n
"},{"location":"output-formats-filters/#output-filters","title":"Output Filters","text":"A number of Drush commands that output tabular data support a --filter
option that allows rows from the output to be selected with simple logic expressions.
In its simplest form, the --filter
option takes a string that indicates the value to filter by in the command's default filter field. For example, the role:list command specifies perms
as its default filter; the output of the role:list
command may be limited to only those roles that have a specified permission:
$ drush role:list --filter='post comments'\nauthenticated:\n label: 'Authenticated user'\nperms:\n - 'access comments'\n- 'access content'\n- 'access shortcuts'\n- 'access site-wide contact form'\n- 'access user contact forms'\n- 'post comments'\n- 'search content'\n- 'skip comment approval'\n- 'use text format basic_html'\n
Note that not all commands have a default filter field. Other fields in the output may be searched by using a simple expression in the --filter
term. For example, to list only the enabled extensions with the pm:list
command, you could run:
$ drush pm:list --filter='status=enabled'\n
To search for fields that contain a string using the operator *=
, or match a regular expression with the ~=
operator. For example, to find all views whose machine name contains the word content: drush views:list --filter='machine-name*=content'\n
To use a regular expression to find any core requirement notice whose title contains either php or gd drush core:requirements --filter='title~=#(php|gd)#i'\n
Finally, filter expressions may also use logical-and (&&
) or logical-or (||
) operations to separate multiple terms. Parenthesis are not supported. For example, to search both the title
and severity
fields in the core:requirements
command: drush core:requirements --filter='title~=#(php|gd)#i&&severity=warning'\n
The =
and *=
operators always use case-insensitive comparisons. The ~=
operator is case-sensitive, unless the i
PCRE modifier is used, as shown in the previous example.
Using the --filter
feature is similar to using grep
. The main difference is that the filter feature does a semantic search, which is to say that it explicitly compares against the data in specific fields. In comparison, the grep
command does a line-based search.
Show only results where the severity is warning:
drush core:requirements --filter='severity=warning'
Show only lines that contain the string warning (either in the severity field, or somewhere else on the line):
drush core:requirements | grep -i warning
The table below compares and contrasts the two ways of searching.
Feature --filter grep Regular expressions Yes, with~=
Yes Word-wrapped field data Searched correctly Might cause false negative Search just one field Yes Might get false positives Search multiple fields Yes, with ||
/&&
Yes (line-based searching) Searching hides header No Yes (unless it matches)"},{"location":"repl/","title":"REPL (a custom shell for Drupal)","text":"The php:cli command is interactive PHP REPL with your bootstrapped site (remote or local). It\u2019s a Drupal code playground. You can do quick code experimentation, grab some data, or run Drush commands. This can also help with debugging certain issues. See this blog post for an introduction. Run help
for a list of commands.
Any global PsySH configuration is loaded by Drush. If you prefer a config file that is specific to the project (and can be checked in with other source code), set the environment variable PSYSH_CONFIG=</path/to/config-file>
. This file then takes precedence over any global file.
Entity classes are available without their namespace. For example, Node::load() works instead of Drupal\\Node\\entity\\Noad::load().
"},{"location":"site-alias-manager/","title":"Site Alias Manager","text":"The Site Alias Manager (SAM) service is used to retrieve information about one or all of the site aliases for the current installation.
$this->siteAliasManager->getself()
.In its most basic form, the Drush site alias feature provides a way for teams to share short names that refer to the live and staging sites (usually remote) for a given Drupal site.
Add an alias file called $PROJECT/drush/sites/self.site.yml
, where $PROJECT
is the project root (location of composer.json file). The site alias file should be named self.site.yml
because this name is special, and is used to define the different environments (usually remote) of the current Drupal site.
The contents of the alias file should look something like the example below:
# File: self.site.yml\nlive:\n host: server.domain.com\n user: www-admin\n root: /other/path/to/live/drupal\n uri: http://example.com\nstage:\n host: server.domain.com\n user: www-admin\n root: /other/path/to/stage/drupal\n uri: http://stage.example.com\n
The top-level element names (live
and stage
in the example above) are used to identify the different environments available for this site. These may be used on the command line to select a different target environment to operate on by prepending an @
character, e.g. @live
or @stage
.
Following these steps, a cache:rebuild on the live environment would be:
$ drush @live cache:rebuild\n
All of the available aliases for a site's environments may be listed via:
$ drush site:alias @self\n
The elements of a site alias are:
host
option must be omitted for local sites, as this option controls various operations, such as whether or not rsync parameters are for local or remote machines, and so on.user
item and specify a user in the ~/.ssh/config
file.Drush typically uses ssh to run commands on remote systems; all team members should install ssh keys on the target servers (e.g. via ssh-add
).
It is also possible to create site alias files that reference other sites on the same local system. Site alias files for other local sites are usually stored in the directory ~/.drush/sites
; however, Drush does not search this location for alias files by default. To use this location, you must add the path in your Drush configuration file. For example, to re-add both of the default user alias path from Drush 8, put the following in your ~/.drush/drush.yml
configuration file:
drush:\n paths:\n alias-path:\n - '${env.HOME}/.drush/sites'\n - /etc/drush/sites\n
A canonical alias named example that points to a local Drupal site named at http://example.com like this:
# File: example.site.yml\ndev:\n root: /path/to/drupal\n uri: http://example.com\n
Note that the first part of the filename (in this case example defines the name of the site alias, and the top-level key dev defines the name of the environment.
With these definitions in place, it is possible to run commands targeting the dev environment of the target site via:
$ drush @example.dev status\n
This command is equivalent to the longer form: $ drush --root=/path/to/drupal --uri=http://example.com status\n
See Additional Site Alias Options for more information."},{"location":"site-aliases/#altering-aliases","title":"Altering aliases:","text":"See examples/Commands/SiteAliasAlterCommands.php) for an example.
"},{"location":"site-aliases/#site-specifications","title":"Site specifications:","text":"When a site alias name is provided on the command line, a site specification may be used instead. A site specification is a site alias that is not saved on the filesystem but instead is provided directly e.g. drush user@server/path/to/drupal#uri core:status
. See example site specifications.
Site aliases may reference environment variables, just like any Drush config file. For example, ${env.PROJECT_SSH_USER}
will be replaced by the value of the PROJECT_SSH_USER
environment value.
SSH site aliases may set environment variables via the env-vars
key. See below.
Aliases are commonly used to define short names for local or remote Drupal installations; however, an alias is really nothing more than a collection of options.
docker-compose
exec rather than ssh
.kubectl
exec rather than ssh
.ssh
command itself, e.g. -p 100
ssh --t
option) based on whether the local Drush command is running interactively or not. To force Drush to always or never create a tty, set the ssh.tty
option to true or false, respectively.--no-dump
will be selected whenever the @stage
alias is used in any of the following ways:drush @stage sql-sync @self @live
drush sql-sync @stage @live
drush sql-sync @live @stage
Complex example:
# File: remote.site.yml\nlive:\n host: server.domain.com\n user: www-admin\n root: /other/path/to/drupal\n uri: http://example.com\n ssh:\n options: '-p 100'\n paths:\n drush-script: '/path/to/drush'\n env-vars:\n PATH: /bin:/usr/bin:/home/www-admin/.composer/vendor/bin\n DRUPAL_ENV: live\n command:\n site:\n install:\n options:\n admin-password: 'secret-secret'\n
"},{"location":"site-aliases/#site-alias-files-for-service-providers","title":"Site Alias Files for Service Providers","text":"There are a number of service providers that manage Drupal sites as a service. Drush allows service providers to create collections of site alias files to reference all of the sites available to a single user. In order to do this, a new location must be defined in your Drush configuration file:
drush:\n paths:\n alias-path:\n - '${env.HOME}/.drush/sites/provider-name'\n
Site aliases stored in this directory may then be referenced by its full alias name, including its location, e.g.:
$ drush @provider-name.example.dev\n
Such alias files may still be referenced by their shorter name, e.g. @example.dev
. Note that it is necessary to individually list every location where site alias files may be stored; Drush never does recursive (deep) directory searches for alias files. The site:alias
command may also be used to list all of the sites and environments in a given location, e.g.:
$ drush site:alias @provider-name\n
Add the option --format=list
to show only the names of each site and environment without also showing the values in each alias record."},{"location":"site-aliases/#wildcard-aliases-for-service-providers","title":"Wildcard Aliases for Service Providers","text":"Some service providers that manage Drupal sites allow customers to create multiple \"environments\" for a site. It is common for these providers to also have a feature to automatically create Drush aliases for all of a user's sites. Rather than write one record for every environment in that site, it is also possible to write a single wildcard alias that represents all possible environments. This is possible if the contents of each environment alias are identical save for the name of the environment in one or more values. The variable ${env-name}
will be substituted with the environment name wherever it appears.
Example wildcard record:
# File: remote-example.site.yml\n'*':\n host: ${env-name}.server.domain.com\n user: www-admin\n root: /path/to/${env-name}\n uri: http://${env-name}.remote-example.com\n
With a wildcard record, any environment name may be used, and will always match. This is not desirable in instances where the specified environment does not exist (e.g. if the user made a typo). An alias alter hook in a policy file may be used to catch these mistakes and report an error. See SiteAliasAlterCommands for an example on how to do this.
"},{"location":"site-aliases/#docker-compose","title":"Docker Compose","text":"The example below shows drush calling into a Docker hosted site. See the https://github.com/consolidation/site-alias and https://github.com/consolidation/site-process projects for more developer information about transports.
An example appears below. Edit to suit:
# File: mysite.site.yml\nlocal:\nThis environment is an example of the DockerCompose transport.\n docker:\n service: drupal\n exec:\n options: --user USER\nstage:\n uri: http://stage.example.com\n root: /path/to/remote/drupal/root\n host: mystagingserver.myisp.com\n user: publisher\n os: Linux\n paths:\n - files: sites/mydrupalsite.com/files\n - custom: /my/custom/path\n command:\n sql:\n sync:\n options:\n no-dump: true\ndev:\n root: /path/to/docroot\n uri: https://dev.example.com\n
"},{"location":"site-aliases/#kubernetes","title":"Kubernetes","text":"Drush provides transport for running drush commands on your Kubernetes cluster via kubectl. See an example and options below.
prod: \n kubectl:\n namespace: 'my-drupal-namespace'\n resource: 'pods/my-drupal-pod' \n container: 'drupal'\n
"},{"location":"site-aliases/#key-options","title":"Key options","text":"Note that most options typically passed to rsync via drush rsync
are \"passthrough options\", which is to say they appear after the --
separator on the command line. Passthrough options are actually arguments, and it is not possible to set default arguments in an alias record. The drush rsync
command does support two options, --mode
and --exclude-paths
, which are interpreted directly by Drush. Default values for these options may be specified in an alias record, as shown below.
dev:\n root: /path/to/docroot\n uri: https://dev.example.com\n command:\n core:\n rsync:\n options:\n mode: rlptz\n exclude-paths: 'css:imagecache:ctools:js:tmp:php:styles'\n
"},{"location":"usage/","title":"Usage","text":"Drush can be run in your shell by typing drush
from within your project root directory or anywhere within Drupal.
$ drush [options] <command> [argument1] [argument2]\n
Use the help command to get a list of available options and commands:
$ drush help pm:list\n
For even more documentation, use the topic command:
$ drush topic\n
"},{"location":"usage/#using-the-uri-option-and-root-options","title":"Using the --uri option and --root options.","text":"For multi-site installations, use a site alias or the --uri option to target a particular site.
$ drush --uri=http://example.com pm:install\n
If you are outside the Composer project and not using a site alias, you need to specify --root and --uri for Drush to locate and bootstrap the right Drupal site.
"},{"location":"usage/#site-aliases","title":"Site Aliases","text":"Drush lets you run commands on a remote server. Once defined, aliases can be referenced with the @ nomenclature, i.e.
# Run pending updates on staging site.\n$ drush @staging updatedb\n# Synchronize staging files to production\n$ drush rsync @staging:%files/ @live:%files\n# Synchronize database from production to local, excluding the cache table\n$ drush sql:sync --structure-tables-key=custom @live @self\n
See Site aliases for more information.
"},{"location":"using-drush-configuration/","title":"Drush Configuration","text":"Drush configuration is useful to cut down on typing out lengthy and repetitive command line options, and to avoid mistakes.
"},{"location":"using-drush-configuration/#directories-and-discovery","title":"Directories and Discovery","text":"drush.yml files are discovered as below, in order of precedence:
sites/{example.com}/drush.yml
).sites/all/drush
, WEBROOT/drush
, or PROJECTROOT/drush
.--config
option.~/.drush/drush.yml
)./etc/drush/drush.yml
or C:\\ProgramData\\Drush\\drush.yml
).If a configuration file is found in any of the above locations, it will be loaded and merged with other configuration files in the search list. Run drush status --fields=drush-conf
to see all discovered config files.
Your Drush config file may reference environment variables using a syntax like ${env.HOME}
. For example see the drush.paths
examples below.
An alternative way to populate Drush configuration is to define environment variables that correspond to config keys. For example, to populate the options.uri
config item, create an environment variable DRUSH_OPTIONS_URI=http://example.com
. As you can see, variable names should be uppercased, prefixed with DRUSH_
, and periods replaced with dashes.
drush:\n paths:\n config:\n # Load any personal config files. Is silently skipped if not found. Filename must be drush.yml\n - ${env.HOME}/.drush/config/drush.yml\n
drush status --fields=drush-conf --format=yaml
These locations are always merged with include paths defined on the command line or in other configuration files. On the command line, paths may be separated by a colon :
on Unix-based systems or a semi-colon ;
on Windows, or multiple --include
options may be provided. Drush 8 and earlier did a deep search in ~/.drush
and /usr/share/drush/commands
when loading command files, so we mimic that here as an example.
drush:\n include:\n - '${env.HOME}/.drush/commands'\n - /usr/share/drush/commands\n
drush list
These locations are always merged with alias paths defined on the command line or in other configuration files. On the command line, paths may be separated by a colon :
on Unix-based systems or a semi-colon ;
on Windows, or multiple --alias-path
options may be provided. Note that Drush 8 and earlier did a deep search in ~/.drush
and /etc/drush
when loading alias files.
drush:\n paths:\n alias-path:\n - '${env.HOME}/.drush/sites'\n - /etc/drush/sites\n
- View all loaded site aliases: drush site:alias
"},{"location":"using-drush-configuration/#backup-directory","title":"Backup directory","text":"Specify a folder where Drush should store backup files, including temporary sql dump files created during sql:sync. If unspecified, defaults to $HOME/drush-backups
.
drush:\n paths:\n backup-dir: /tmp/drush-backups\n
"},{"location":"using-drush-configuration/#global-options","title":"Global options","text":"options:\n # Specify the base_url that should be used when generating links.\n uri: 'http://example.com/subdir'\n\n # Specify your Drupal core base directory (useful if you use symlinks).\n root: '/home/USER/workspace/drupal'\n\n # Enable verbose mode.\n verbose: true\n
"},{"location":"using-drush-configuration/#command-specific-options","title":"Command-specific options","text":"command:\n sql:\n cli:\n options:\n # Enable auto-complete in MySQL.\n extra: \"--auto-rehash\"\n dump:\n options:\n # Omit cache and similar tables (including during a sql:sync).\n structure-tables-key: common\n php:\n script:\n options:\n # Additional folders to search for scripts.\n script-path: 'sites/all/scripts:profiles/myprofile/scripts'\n core:\n rsync:\n options:\n # Ensure all rsync commands use verbose output.\n verbose: true\n\n site:\n install:\n options:\n # Set a predetermined username and password when using site:install.\n account-name: 'alice'\n account-pass: 'secret'\n
"},{"location":"using-drush-configuration/#non-options","title":"Non-options","text":"sql:\n # An explicit list of tables which should be included in sql-dump and sql-sync.\n tables:\n common:\n - user\n - permissions\n - role_permissions\n - role\n # List of tables whose *data* is skipped by the 'sql-dump' and 'sql-sync'\n # commands when the \"--structure-tables-key=common\" option is provided.\n # You may add specific tables to the existing array or add a new element.\n structure-tables:\n common:\n - cache\n - 'cache_*'\n - history\n - 'search_*'\n - 'sessions'\n - 'watchdog'\n # List of tables to be omitted entirely from SQL dumps made by the 'sql-dump'\n # and 'sql-sync' commands when the \"--skip-tables-key=common\" option is\n # provided on the command line. This is useful if your database contains\n # non-Drupal tables used by some other application or during a migration for\n # example. You may add new tables to the existing array or add a new element.\n skip-tables:\n common:\n - 'migration_*'\n\nssh:\n # Specify options to pass to ssh. The default is to prohibit\n # password authentication, and is included here, so you may add additional\n # parameters without losing the default configuration.\n options: '-o PasswordAuthentication=no'\n # This string is valid for Bash shell. Override in case you need something different. See https://github.com/drush-ops/drush/issues/3816.\n pipefail: 'set -o pipefail; '\n\nnotify:\n # Notify when command takes more than 30 seconds.\n duration: 30\n # Specify a command to run. Defaults to Notification Center (OSX) or libnotify (Linux)\n cmd: /path/to/program\n # See https://github.com/drush-ops/drush/blob/12.x/src/Commands/core/NotifyCommands.php for more settings.\n\nxh:\n # Start profiling via xhprof/tideways and show a link to the run report.\n link: http://xhprof.local\n # See https://github.com/drush-ops/drush/blob/12.x/src/Commands/core/XhprofCommands.php for more settings.\n profile-builtins: true\n profile-cpu: false\n profile-memory: false\n
"},{"location":"using-drush-configuration/#misc","title":"Misc","text":"drush10.yml
.Tip
Press the / key to Search for a command. Or use your browser's Find in Page feature.
Backup your code, files, and database into a single file.
The following paths would be excluded from a code archive:
composer info --path --format=json
)The following directories would be excluded from a file archive:
drush archive:dump
. Create a site archive file in a temporary directory containing code, database and Drupal files.drush archive:dump --destination=/path/to/archive.tar.gz
. Create /path/to/archive.tar.gz file containing code, database and Drupal files.drush archive:dump --destination=/path/to/archive.tar.gz --overwrite
. Create (or overwrite if exists) /path/to/archive.tar.gz file containing code, database and Drupal files.drush archive:dump --code --destination=/path/to/archive.tar.gz
. Create /path/to/archive.tar.gz file containing the code only.drush archive:dump --exclude-code-paths=foo_bar.txt,web/sites/.+/settings.php --destination=/path/to/archive.tar.gz
. Create /path/to/archive.tar.gz file containing code, database and Drupal files but excluding foo_bar.txt file and settings.php files if found in web/sites/* subdirectories.drush archive:dump --extra-dump=--no-data --destination=/path/to/archive.tar.gz
. Create /path/to/archive.tar.gz file and pass extra option to mysqldump command.drush archive:dump --files --destination=/path/to/archive.tar.gz
. Create /path/to/archive.tar.gz file containing the Drupal files only.drush archive:dump --database --destination=/path/to/archive.tar.gz
. Create /path/to/archive.tar.gz archive file containing the database dump only.drush topic
and pick the first choice.Legend
Restore (import) your code, files, and database.
"},{"location":"commands/archive_restore/#examples","title":"Examples","text":"drush archive:restore /path/to/archive.tar.gz
. Restore the site from /path/to/archive.tar.gz archive file.drush archive:restore /path/to/archive.tar.gz --destination-path=/path/to/restore
. Restore the site from /path/to/archive.tar.gz archive file into /path/to/restore directory.drush archive:restore /path/to/archive.tar.gz --code --destination-path=/path/to/restore
. Restore the code from /path/to/archive.tar.gz archive file into /path/to/restore directory.drush archive:restore /path/to/archive.tar.gz --code-source-path=/code/source/path
. Restore database and Drupal files from /path/to/archive.tar.gz archive file and the code from /code/source/path directory.drush archive:restore /path/to/archive.tar.gz --files --destination-path=/path/to/restore
. Restore the Drupal files from /path/to/archive.tar.gz archive file into /path/to/restore directorydrush archive:restore /path/to/archive.tar.gz --files-source-path=/files/source/path
. Restore code and database from /path/to/archive.tar.gz archive file and the Drupal files from /files/source/path directory.drush archive:restore /path/to/archive.tar.gz --files-destination-relative-path=web/site/foo-bar/files
. Restore the Drupal files from /path/to/archive.tar.gz archive file into web/site/foo-bar/files site's subdirectory.drush archive:restore /path/to/archive.tar.gz --db
. Restore the database from /path/to/archive.tar.gz archive file.drush archive:restore /path/to/archive.tar.gz --db-source-path=/path/to/database.sql
. Restore code and Drupal files from /path/to/archive.tar.gz archive file and the database from /path/to/database.sql dump file.drush archive:restore /path/to/archive.tar.gz --db-url=mysql://user:password@localhost/database_name --destination-path=/path/to/restore
. Restore code, database and Drupal files from /path/to/archive.tar.gz archive file into /path/to/restore directory using database URL.archive:dump
command: * 1) code (\"code\" directory); * 2) database dump file (\"database/database.sql\" file); * 3) Drupal files (\"files\" directory).drush topic
and pick the first choice.Legend
Display a link to a given path or open link in a browser.
"},{"location":"commands/browse/#examples","title":"Examples","text":"drush browse
. Open default web browser (if configured or detected) to the site front page.drush browse node/1
. Open web browser to the path node/1.drush @example.prod browse
. Open a browser to the web site specified in a site alias.drush topic
and pick the first choice.Legend
Clear a specific cache, or all Drupal caches.
"},{"location":"commands/cache_clear/#examples","title":"Examples","text":"drush cc bin
. Choose a bin to clear.drush cc bin entity,bootstrap
. Clear the entity and bootstrap cache bins.drush topic
and pick the first choice.Legend
Fetch a cached object and display it.
"},{"location":"commands/cache_get/#examples","title":"Examples","text":"drush cache:get hook_info bootstrap
. Display the data for the cache id \"hook_info\" from the \"bootstrap\" bin.drush cache:get update_available_releases update
. Display the data for the cache id \"update_available_releases\" from the \"update\" bin.drush topic
and pick the first choice.Legend
Rebuild all caches.
This is a copy of core/rebuild.php.
"},{"location":"commands/cache_rebuild/#options","title":"Options","text":"drush topic
and pick the first choice.Legend
Cache an object expressed in JSON or var_export() format.
"},{"location":"commands/cache_set/#arguments","title":"Arguments","text":"drush topic
and pick the first choice.Legend
Invalidate by cache tags.
"},{"location":"commands/cache_tags/#examples","title":"Examples","text":"drush cache:tag node:12,user:4
. Purge content associated with two cache tags.drush topic
and pick the first choice.Legend
Dump the shell completion script
The *%command.name% command dumps the shell completion script required to use shell autocompletion (currently, bash, fish, zsh completion are supported).
"},{"location":"commands/completion/#static-installation","title":"Static installationDump the script to a global completion file and restart your shell:
*%command.full_name% | sudo tee /etc/bash_completion.d/drush\n
Or dump the script to a local file and source it:
*%command.full_name% > completion.sh\n\n<comment># source the file whenever you use the project\n*source completion.sh\n\n<comment># or add this line at the end of your \"~/.bashrc\" file:\n*source /path/to/completion.sh\n
","text":""},{"location":"commands/completion/#dynamic-installation","title":"Dynamic installation Add this to the end of your shell configuration file (e.g. *\"~/.bashrc\"):
*eval \"$(/home/runner/work/drush/drush/drush completion )\"\n
","text":""},{"location":"commands/completion/#arguments","title":"Arguments","text":"drush topic
and pick the first choice.Legend
Delete a configuration key, or a whole object(s).
"},{"location":"commands/config_delete/#examples","title":"Examples","text":"drush config:delete system.site,system.rss
. Delete the system.site and system.rss config objects.drush config:delete system.site page.front
. Delete the 'page.front' key from the system.site object.drush topic
and pick the first choice.Legend
Open a config file in a text editor. Edits are imported after closing editor.
"},{"location":"commands/config_edit/#examples","title":"Examples","text":"drush config:edit image.style.large
. Edit the image style configurations.drush config:edit
. Choose a config file to edit.drush --bg config-edit image.style.large
. Return to shell prompt as soon as the editor window opens.drush topic
and pick the first choice.Legend
Export Drupal configuration to a directory.
"},{"location":"commands/config_export/#examples","title":"Examples","text":"drush config:export
. Export configuration files to the site's config directory.drush config:export --destination
. Export configuration; Save files in a backup directory named config-export.git add -p
after exporting. This lets you choose which config changes to sync for commit.git add -A
and git commit
after exporting. This commits everything that was exported without prompting.drush topic
and pick the first choice.Legend
Display a config value, or a whole configuration object.
"},{"location":"commands/config_get/#examples","title":"Examples","text":"drush config:get system.site
. Displays the system.site config.drush config:get system.site page.front
. Gets system.site:page.front value.drush topic
and pick the first choice.Legend
Import config from the config directory.
"},{"location":"commands/config_import/#examples","title":"Examples","text":"drush config:import
. Update Drupal's configuration so it matches the contents of the config directory.drush config:import --partial --source=/app/config
. Import from the /app/config directory which typically contains one or a few yaml files.cat tmp.yml | drush config:set --input-format=yaml user.mail ? -
. Update the user.mail config object in its entirety.drush topic
and pick the first choice.Legend
Export and transfer config from one environment to another.
"},{"location":"commands/config_pull/#examples","title":"Examples","text":"drush config:pull @prod @stage
. Export config from @prod and transfer to @stage.drush config:pull @prod @self:../config/sync
. Export config and transfer to a custom directory. Relative paths are calculated from Drupal root.drush topic
and pick the first choice.Legend
Save a config value directly. Does not perform a config import.
"},{"location":"commands/config_set/#examples","title":"Examples","text":"drush config:set system.site name MySite
. Sets a value for the key name of system.site config object.drush config:set system.site page.front /path/to/page
. Sets the given URL path as value for the config item with key page.front of system.site config object.drush config:set system.site '[]'
. Sets the given key to an empty array.drush config:set system.site 'NULL'
. Sets the given key to NULL.drush config:set --input-format=yaml user.role.authenticated permissions [foo,bar]
. Use a sequence as value for the key permissions of user.role.authenticated config object.drush config:set --input-format=yaml system.site page {403: '403', front: home}
. Use a mapping as value for the key page of system.site config object.drush config:set --input-format=yaml user.role.authenticated ? \"{label: 'Auth user', weight: 5}\"
. Update two top level keys (label, weight) in the system.site config object.cat tmp.yml | drush config:set --input-format=yaml user.mail ? -
. Update the user.mail config object in its entirety.drush topic
and pick the first choice.Legend
Display status of configuration (differences between the filesystem and database).
"},{"location":"commands/config_status/#examples","title":"Examples","text":"drush config:status
. Display configuration items that need to be synchronized.drush config:status --state=Identical
. Display configuration items that are in default state.drush config:status --state='Only in sync dir' --prefix=node.type.
. Display all content types that would be created in active storage on configuration import.drush config:status --state=Any --format=list
. List all config names.drush config:status 2>&1 | grep \"No differences\"
. Check there are no differences between database and exported config. Useful for CI.drush topic
and pick the first choice.Legend
Run all cron hooks in all active modules for specified site.
Consider using drush maint:status && drush core:cron
to avoid cache poisoning during maintenance mode.
drush topic
and pick the first choice.drush cron
. (docs:cron)Legend
Edit drush.yml, site alias, and Drupal settings.php files.
"},{"location":"commands/core_edit/#examples","title":"Examples","text":"drush core:edit
. Pick from a list of config/alias/settings files. Open selected in editor.drush --bg core-config
. Return to shell prompt as soon as the editor window opens.drush core:edit etc
. Edit the global configuration file.drush core:edit demo.alia
. Edit a particular alias file.drush core:edit sett
. Edit settings.php for the current Drupal site.drush core:edit --choice=2
. Edit the second file in the choice list.drush topic
and pick the first choice.Legend
Information about things that may be wrong in your Drupal installation.
"},{"location":"commands/core_requirements/#examples","title":"Examples","text":"drush core:requirements
. Show all status lines from the Status Report admin page.drush core:requirements --severity=2
. Show only the red lines from the Status Report admin page.drush topic
and pick the first choice.Legend
10.5+
View information about all routes or one route.
"},{"location":"commands/core_route/#examples","title":"Examples","text":"drush route
. View all routes.drush route --name=update.status
. View details about the update.status route.drush route --path=/user/1
. View details about the entity.user.canonical route.drush route --url=https://example.com/node/1
. View details about the entity.node.canonical route.drush topic
and pick the first choice.Legend
Rsync Drupal code or files to/from another server using ssh.
"},{"location":"commands/core_rsync/#examples","title":"Examples","text":"drush rsync @dev @stage
. Rsync Drupal root from Drush alias dev to the alias stage.drush rsync ./ @stage:%files/img
. Rsync all files in the current directory to the imgdirectory in the file storage folder on the Drush alias stage.drush rsync @live:%private @stage:%private
. Rsync private files from live to stage.drush rsync @dev @stage -- --exclude=*.sql --delete
. Rsync Drupal root from the Drush alias dev to the alias stage, excluding all .sql files and delete all files on the destination that are no longer on the source.drush rsync @dev @stage --ssh-options=\"-o StrictHostKeyChecking=no\" -- --delete
. Customize how rsync connects with remote host via SSH. rsync options like --delete are placed after a --.drush topic
and pick the first choice.Legend
An overview of the environment - Drush and Drupal.
"},{"location":"commands/core_status/#examples","title":"Examples","text":"drush core-status --field=files
. Emit just one field, not all the default fields.drush core-status --fields=*
. Emit all fields, not just the default ones.drush topic
and pick the first choice.Legend
Read detailed documentation on a given topic.
"},{"location":"commands/core_topic/#examples","title":"Examples","text":"drush topic
. Pick from all available topics.drush topic docs-repl
. Show documentation for the Drush interactive shelldrush docs:r
. Filter topics for those starting with 'docs-r'.drush topic
and pick the first choice.Legend
10.3+
Run several commands after performing a code deployment.
"},{"location":"commands/deploy/#examples","title":"Examples","text":"drush deploy -v -y
. Run updates with verbose logging and accept all prompts.drush topic
and pick the first choice.Legend
Prints information about pending deploy update hooks.
"},{"location":"commands/deploy_hook-status/#examples","title":"Examples","text":"drush deploy:hook-status
. Prints information about pending deploy hooks.drush topic
and pick the first choice.Legend
10.3+
Run pending deploy update hooks.
"},{"location":"commands/deploy_hook/#examples","title":"Examples","text":"drush deploy:hook
. Run pending deploy hooks.drush topic
and pick the first choice.Legend
10.6.1+
Mark all deploy hooks as having run.
"},{"location":"commands/deploy_mark-complete/#examples","title":"Examples","text":"drush deploy:mark-complete
. Skip all pending deploy hooks and mark them as complete.drush topic
and pick the first choice.Legend
Return the filesystem path for modules/themes and other key folders.
"},{"location":"commands/drupal_directory/#examples","title":"Examples","text":"cd $(drush dd devel)
. Navigate into the devel module directorycd $(drush dd)
. Navigate to the root of your Drupal sitecd $(drush dd files)
. Navigate to the files directory.drush dd @alias:%files
. Print the path to the files directory on the site @alias.edit $(drush dd devel)/devel.module
. Open devel module in your editordrush topic
and pick the first choice.Legend
12.5+
Create a content entity after prompting for field values.
When entering field values, one may submit an incomplete document and any entity violations will be helpfully reported at the top of the document. enter skip as a value in order to skip validation for that field. Timestamp values may be expressed via any string recognized by strtotime()
"},{"location":"commands/entity_create/#examples","title":"Examples","text":"drush entity:create node article --validate=0
. Create an article entity and skip validation entirely.drush entity:create node article --skip-fields=field_media_image,field_tags
. Create an article omitting two fields.drush entity:create user user --editor=nano
. Create a user using the Nano text editor.drush topic
and pick the first choice.Legend
Delete content entities.
To delete configuration entities, see config:delete command.
"},{"location":"commands/entity_delete/#examples","title":"Examples","text":"drush entity:delete node --bundle=article
. Delete all article entities.drush entity:delete shortcut
. Delete all shortcut entities.drush entity:delete node 22,24
. Delete nodes 22 and 24.drush entity:delete user
. Delete all users except uid=1.drush entity:delete node --exclude=9,14,81
. Delete all nodes except node 9, 14 and 81.drush entity:delete node --chunks=5
. Delete all node entities in steps of 5.drush topic
and pick the first choice.Legend
11.0+
Load and save entities.
"},{"location":"commands/entity_save/#examples","title":"Examples","text":"drush entity:save node --bundle=article
. Re-save all article entities.drush entity:save shortcut
. Re-save all shortcut entities.drush entity:save node 22,24
. Re-save nodes 22 and 24.drush entity:save node --exclude=9,14,81
. Re-save all nodes except node 9, 14 and 81.drush entity:save user
. Re-save all users.drush entity:save node --chunks=5
. Re-save all node entities in steps of 5.drush topic
and pick the first choice.Legend
11.0+
List all base fields of an entity type
"},{"location":"commands/field_base-info/#examples","title":"Examples","text":"field:base-info taxonomy_term
. List all base fields.field:base-info
. List all base fields and fill in the remaining information through prompts.drush topic
and pick the first choice.Legend
11.0+
Create a new base field override
"},{"location":"commands/field_base-override-create/#examples","title":"Examples","text":"field:base-field-override-create
. Create a base field override by answering the prompts.field:base-field-override-create taxonomy_term tag
. Create a base field override and fill in the remaining information through prompts.field:base-field-override-create taxonomy_term tag --field-name=name --field-label=Label --is-required=1
. Create a base field override in a completely non-interactive way.drush topic
and pick the first choice.Legend
11.0+
Create a new field
"},{"location":"commands/field_create/#examples","title":"Examples","text":"field:create
. Create a field by answering the prompts.field-create taxonomy_term tag
. Create a field and fill in the remaining information through prompts.field-create taxonomy_term tag --field-name=field_tag_label --field-label=Label --field-type=string --field-widget=string_textfield --is-required=1 --cardinality=2
. Create a field in a completely non-interactive way.drush topic
and pick the first choice.Legend
11.0+
Delete a field
"},{"location":"commands/field_delete/#examples","title":"Examples","text":"field:delete
. Delete a field by answering the prompts.field-delete taxonomy_term tag
. Delete a field and fill in the remaining information through prompts.field-delete taxonomy_term tag --field-name=field_tag_label
. Delete a field in a non-interactive way.field-delete taxonomy_term --field-name=field_tag_label --all-bundles
. Delete a field from all bundles.drush topic
and pick the first choice.Legend
Lists field formatters.
"},{"location":"commands/field_formatters/#examples","title":"Examples","text":"drush field:formatters --field-type=entity_reference
. Lists field formatters applicable for entity reference fields.drush topic
and pick the first choice.Legend
11.0+
List all configurable fields of an entity bundle
"},{"location":"commands/field_info/#examples","title":"Examples","text":"field:info taxonomy_term tag
. List all fields.field:info
. List all fields and fill in the remaining information through prompts.drush topic
and pick the first choice.Legend
Lists field types.
"},{"location":"commands/field_types/#examples","title":"Examples","text":"drush field:types
. List all registered field types.drush topic
and pick the first choice.Legend
Lists field widgets.
"},{"location":"commands/field_widgets/#examples","title":"Examples","text":"drush field:widgets --field-type=entity_reference
. Lists field widgets applicable for entity reference fields.drush topic
and pick the first choice.Legend
Generate boilerplate code for modules/plugins/services etc.
Drush asks questions so that the generated code is as polished as possible. After generating, Drush lists the files that were created.
See https://github.com/Chi-teck/drupal-code-generator for a README and bug reports.
"},{"location":"commands/generate/#examples","title":"Examples","text":"drush generate
. Pick from available generators and then run it.drush generate drush-command-file
. Generate a Drush commandfile for your module.drush generate controller --answer=Example --answer=example
. Generate a controller class and pre-fill the first two questions in the wizard.drush generate controller -vvv --dry-run
. Learn all the potential answers so you can re-run with several --answer options.drush topic
and pick the first choice.Legend
Display usage details for a command.
"},{"location":"commands/help/#examples","title":"Examples","text":"drush help pm:uninstall
. Show help for a command.drush help pmu
. Show help for a command using an alias.drush help --format=xml
. Show all available commands in XML format.drush help --format=json
. All available commands, in JSON format.drush topic
and pick the first choice.Legend
Create an image derivative.
"},{"location":"commands/image_derive/#examples","title":"Examples","text":"drush image:derive thumbnail core/themes/bartik/screenshot.png
. Save thumbnail sized derivative of logo image.drush topic
and pick the first choice.Legend
Flush all derived images for a given style.
"},{"location":"commands/image_flush/#examples","title":"Examples","text":"drush image:flush
. Pick an image style and then delete its derivatives.drush image:flush thumbnail,large
. Delete all thumbnail and large derivatives.drush image:flush --all
. Flush all derived images. They will be regenerated on demand.drush topic
and pick the first choice.Legend
Execute a JSONAPI request.
"},{"location":"commands/jn_get/#examples","title":"Examples","text":"drush jn:get jsonapi/node/article
. Get a list of articles back as JSON.drush jn:get jsonapi/node/article | jq
. Pretty print JSON by piping to jq. See https://stedolan.github.io/jq/ for lots more jq features.drush topic
and pick the first choice.Legend
List available commands.
"},{"location":"commands/list/#examples","title":"Examples","text":"drush list
. List all commands.drush list --filter=devel_generate
. Show only commands starting with devel-drush list --format=xml
. List all commands in Symfony compatible xml format.drush topic
and pick the first choice.Legend
Checks for available translation updates.
"},{"location":"commands/locale_check/#global-options","title":"Global Options","text":"drush topic
and pick the first choice.Legend
11.5+
Clears the translation status.
"},{"location":"commands/locale_clear-status/#global-options","title":"Global Options","text":"drush topic
and pick the first choice.Legend
Exports to a gettext translation file.
See Drupal Core: \\Drupal\\locale\\Form\\ExportForm::submitForm
"},{"location":"commands/locale_export/#examples","title":"Examples","text":"drush locale:export nl > nl.po
. Export the Dutch translations with all types.drush locale:export nl --types=customized,not-customized > nl.po
. Export the Dutch customized and not customized translations.drush locale:export --template > drupal.pot
. Export the source strings only as template file for translation.drush topic
and pick the first choice.Legend
12.2+
Imports multiple translation files from the defined directory.
"},{"location":"commands/locale_import-all/#examples","title":"Examples","text":"drush locale:import-all /var/www/translations
. Import all translations from the defined directory (non-recursively). Supported filename patterns are: {project}-{version}.{langcode}.po, {prefix}.{langcode}.po or {langcode}.po.drush locale:import-all /var/www/translations/custom --types=customized --override=all
. Import all custom translations from the defined directory (non-recursively) and override any existing translation. Supported filename patterns are: {project}-{version}.{langcode}.po, {prefix}.{langcode}.po or {langcode}.po.drush topic
and pick the first choice.Legend
Imports to a gettext translation file.
"},{"location":"commands/locale_import/#examples","title":"Examples","text":"drush locale-import nl drupal-8.4.2.nl.po
. Import the Dutch drupal core translation.drush locale-import --type=customized nl drupal-8.4.2.nl.po
. Import the Dutch drupal core translation. Treat imported strings as custom translations.drush locale-import --override=none nl drupal-8.4.2.nl.po
. Import the Dutch drupal core translation. Don't overwrite existing translations. Only append new translations.drush locale-import --override=not-customized nl drupal-8.4.2.nl.po
. Import the Dutch drupal core translation. Only override non-customized translations, customized translations are kept.drush locale-import nl custom-translations.po --type=customized --override=all
. Import customized Dutch translations and override any existing translation.drush topic
and pick the first choice.Legend
Imports the available translation updates.
"},{"location":"commands/locale_update/#options","title":"Options","text":"drush topic
and pick the first choice.Legend
11.5+
Get maintenance mode. Returns 1 if enabled, 0 if not.
Consider using maint:status instead when chaining commands.
"},{"location":"commands/maint_get/#examples","title":"Examples","text":"drush maint:get
. Print value of maintenance mode in Drupaldrush topic
and pick the first choice.Legend
11.5+
Set maintenance mode.
"},{"location":"commands/maint_set/#examples","title":"Examples","text":"drush maint:set 1
. Put site into Maintenance mode.drush maint:set 0
. Remove site from Maintenance mode.drush topic
and pick the first choice.Legend
11.5+
Fail if maintenance mode is enabled.
This commands fails with exit code of 3 when maintenance mode is on. This special exit code distinguishes from a failure to complete.
"},{"location":"commands/maint_status/#examples","title":"Examples","text":"drush maint:status && drush cron
. Only run cron when Drupal is not in maintenance mode.drush topic
and pick the first choice.Legend
10.4+
List the fields available for mapping in a source.
"},{"location":"commands/migrate_fields-source/#examples","title":"Examples","text":"migrate:fields-source article
. List fields for the source in the article migration.drush topic
and pick the first choice.Legend
10.4+
Perform one or more migration processes.
"},{"location":"commands/migrate_import/#examples","title":"Examples","text":"migrate:import --all
. Perform all migrationsmigrate:import --all --no-progress
. Perform all migrations but avoid the progress barmigrate:import --tag=user,main_content
. Import all migrations tagged with user and main_content tagsmigrate:import classification,article
. Import new terms and nodes using migration classification and articlemigrate:import user --limit=2
. Import no more than 2 users using the user migrationmigrate:import user --idlist=5
. Import the user record with source ID 5migrate:import node_revision --idlist=1:2,2:3,3:5
. Import the node revision record with source IDs [1,2], [2,3], and [3,5]migrate:import user --limit=50 --feedback=20
. Import 50 users and show process message every 20th recordmigrate:import --all --delete
. Perform all migrations and delete the destination items that are missing from sourcedrush topic
and pick the first choice.Legend
10.4+
View any messages associated with a migration.
"},{"location":"commands/migrate_messages/#examples","title":"Examples","text":"migrate:messages article
. Show all messages for the article migrationmigrate:messages node_revision --idlist=1:2,2:3,3:5
. Show messages related to node revision records with source IDs [1,2], [2,3], and [3,5].migrate:messages custom_node_revision --idlist=1:\"r:1\",2:\"r:3\"
. Show messages related to node revision records with source IDs [1,\"r:1\"], and [2,\"r:3\"].drush topic
and pick the first choice.Legend
10.4+
Reset an active migration's status to idle.
"},{"location":"commands/migrate_reset-status/#arguments","title":"Arguments","text":"drush topic
and pick the first choice.Legend
10.4+
Rollback one or more migrations.
"},{"location":"commands/migrate_rollback/#examples","title":"Examples","text":"migrate:rollback --all
. Rollback all migrationsmigrate:rollback --all --no-progress
. Rollback all migrations but avoid the progress barmigrate:rollback --tag=user,main_content
. Rollback all migrations tagged with user and main_content tagsmigrate:rollback classification,article
. Rollback terms and nodes imported by classification and article migrationsmigrate:rollback user --idlist=5
. Rollback imported user record with source ID 5drush topic
and pick the first choice.Legend
10.4+
List all migrations with current status.
"},{"location":"commands/migrate_status/#examples","title":"Examples","text":"migrate:status
. Retrieve status for all migrationsmigrate:status --tag
. Retrieve status for all migrations, grouped by tagmigrate:status --tag=user,main_content
. Retrieve status for all migrations tagged with user or main_contentmigrate:status classification,article
. Retrieve status for specific migrationsmigrate:status --field=id
. Retrieve a raw list of migration IDs.ms --fields=id,status --format=json
. Retrieve a Json serialized list of migrations, each item containing only the migration ID and its status.drush topic
and pick the first choice.Legend
10.4+
Stop an active migration operation.
"},{"location":"commands/migrate_stop/#arguments","title":"Arguments","text":"drush topic
and pick the first choice.Legend
Build a Markdown document for each available Drush command/generator.
This command is an early step when building the www.drush.org static site. Adapt it to build a similar site listing the commands that are available on your site. Also see Drush's Github Actions workflow.
"},{"location":"commands/mk_docs/#examples","title":"Examples","text":"drush mk:docs
. Build many .md files in the docs/commands and docs/generators directories.drush topic
and pick the first choice.Legend
Open an interactive shell on a Drupal site.
"},{"location":"commands/php_cli/#examples","title":"Examples","text":"$node = Node::load(1)
. Entity classes are available without their namespace. For example, Node::load(1) works instead of Drupal\\Node\\entity\\Node::load(1).$paragraph = Paragraph::loadRevision(1)
. Also, a loadRevision static method is made available for easier load of revisions.drush topic
and pick the first choice.Legend
Evaluate arbitrary php code after bootstrapping Drupal (if available).
"},{"location":"commands/php_eval/#examples","title":"Examples","text":"drush php:eval '$node = \\Drupal ode\\Entity\\Node::load(1); print $node->getTitle();'
. Loads node with nid 1 and then prints its title.drush php:eval \"\\Drupal::service('file_system')->copy('$HOME/Pictures/image.jpg', 'public://image.jpg');\"
. Copies a file whose path is determined by an environment's variable. Use of double quotes so the variable $HOME gets replaced by its value.drush php:eval \"node_access_rebuild();\"
. Rebuild node access permissions.drush topic
and pick the first choice.Legend
Run php a script after a full Drupal bootstrap.
A useful alternative to eval command when your php is lengthy or you can't be bothered to figure out bash quoting. If you plan to share a script with others, consider making a full Drush command instead, since that's more self-documenting. Drush provides commandline options to the script via a variable called $extra.
"},{"location":"commands/php_script/#examples","title":"Examples","text":"drush php:script example --script-path=/path/to/scripts:/another/path
. Run a script named example.php from specified pathsdrush php:script -
. Run PHP code from standard input.drush php:script
. List all available scripts.drush php:script foo -- apple --cider
. Run foo.php script with argument apple and option cider. Note the -- separator.drush topic
and pick the first choice.Legend
Enable one or more modules.
"},{"location":"commands/pm_install/#examples","title":"Examples","text":"drush pm:install --simulate content_moderation
. Display what modules would be installed but don't install them.drush topic
and pick the first choice.Legend
Show a list of available extensions (modules and themes).
"},{"location":"commands/pm_list/#options","title":"Options","text":"drush topic
and pick the first choice.Legend
Uninstall one or more modules and their dependent modules.
"},{"location":"commands/pm_uninstall/#examples","title":"Examples","text":"drush pm:uninstall --simulate field_ui
. Display what modules would be uninstalled but don't uninstall them.drush topic
and pick the first choice.Legend
Delete all items in a specific queue.
"},{"location":"commands/queue_delete/#arguments","title":"Arguments","text":"drush topic
and pick the first choice.Legend
Returns a list of all defined queues.
"},{"location":"commands/queue_list/#options","title":"Options","text":"drush topic
and pick the first choice.Legend
Run a specific queue by name.
"},{"location":"commands/queue_run/#arguments","title":"Arguments","text":"drush topic
and pick the first choice.Legend
Create a new role.
"},{"location":"commands/role_create/#examples","title":"Examples","text":"drush role:create 'test_role' 'Test role'
. Create a new role with a machine name of 'test_role', and a human-readable name of 'Test role'.drush topic
and pick the first choice.Legend
Delete a role.
"},{"location":"commands/role_delete/#examples","title":"Examples","text":"drush role:delete 'test_role'
. Delete the role 'test_role'.drush topic
and pick the first choice.Legend
Display roles and their permissions.
"},{"location":"commands/role_list/#examples","title":"Examples","text":"drush role:list --filter='administer nodes'
. Display a list of roles that have the administer nodes permission assigned.drush role:list --filter='rid=anonymous'
. Display only the anonymous role.drush topic
and pick the first choice.Legend
Grant specified permission(s) to a role.
"},{"location":"commands/role_perm_add/#examples","title":"Examples","text":"drush role:perm:add anonymous 'post comments'
. Allow anon users to post comments.drush role:perm:add anonymous 'post comments,access content'
. Allow anon users to post comments and access content.drush topic
and pick the first choice.Legend
Remove specified permission(s) from a role.
"},{"location":"commands/role_perm_remove/#examples","title":"Examples","text":"drush role:remove-perm anonymous
. Remove 2 permissions from anon users.drush topic
and pick the first choice.Legend
Runs PHP's built-in http server for development.
drush rs 8080
. Start a web server on 127.0.0.1, port 8080.drush rs 10.0.0.28:80
. Start runserver on 10.0.0.28, port 80.drush rs [::1]:80
. Start runserver on IPv6 localhost ::1, port 80.drush rs --dns localhost:8888/user
. Start runserver on localhost (using rDNS to determine binding IP), port 8888, and open /user in browser.drush rs /
. Start runserver on default IP/port (127.0.0.1, port 8888), and open / in browser.drush rs :9000/admin
. Start runserver on 127.0.0.1, port 9000, and open /admin in browser. Note that you need a colon when you specify port and path, but no IP.drush --quiet rs
. Silence logging the printing of web requests to the console.drush topic
and pick the first choice.Legend
Show site alias details, or a list of available site aliases.
"},{"location":"commands/site_alias/#examples","title":"Examples","text":"drush site:alias
. List all alias records known to drush.drush site:alias @dev
. Print an alias record for the alias dev.drush topic
and pick the first choice.Legend
Install Drupal along with modules/themes/configuration/profile.
"},{"location":"commands/site_install/#examples","title":"Examples","text":"drush si demo_umami --locale=da
. (Re)install using the Umami install profile. Set default language to Danish.drush si --db-url=mysql://user:pass@localhost:port/dbname
. Install using the specified DB params.drush si --db-url=sqlite://sites/example.com/files/.ht.sqlite
. Install using SQLitedrush si --db-url=sqlite://:memory:
. Install using SQLite in-memory database.drush si --account-pass=mom
. Re-install with specified uid1 password.drush si --existing-config
. Install based on the yml files stored in the config export/import directory.drush si standard install_configure_form.enable_update_status_emails=NULL
. Disable email notification during install and later. If your server has no mail transfer agent, this gets rid of an error during install.drush topic
and pick the first choice.Legend
Set a site alias that will persist for the current session.
Stores the site alias being used in the current session in a temporary file.
"},{"location":"commands/site_set/#examples","title":"Examples","text":"drush site:set @dev
. Set the current session to use the @dev alias.drush site:set user@server/path/to/drupal#sitename
. Set the current session to use a remote site via site specification.drush site:set /path/to/drupal#sitename
. Set the current session to use a local site via site specification.drush site:set -
. Go back to the previously-set site (like cd -
).drush site:set
. Without an argument, any existing site becomes unset.drush topic
and pick the first choice.Legend
Connect to a webserver via SSH, and optionally run a shell command.
"},{"location":"commands/site_ssh/#examples","title":"Examples","text":"drush @mysite ssh
. Open an interactive shell on @mysite's server.drush @prod ssh \"ls /tmp\"
. Run ls /tmp on @prod site.drush @prod ssh \"git pull\"
. Run git pull on the Drupal root directory on the @prod site.drush ssh \"git pull\"
. Run git pull on the local Drupal root directory.drush topic
and pick the first choice.Legend
Open a SQL command-line interface using Drupal's credentials.
"},{"location":"commands/sql_cli/#examples","title":"Examples","text":"drush sql:cli
. Open a SQL command-line interface using Drupal's credentials.drush sql:cli --extra=--progress-reports
. Open a SQL CLI and skip reading table information.drush sql:cli < example.sql
. Import sql statements from a file into the current database.drush topic
and pick the first choice.Legend
A string for connecting to the DB.
"},{"location":"commands/sql_connect/#examples","title":"Examples","text":"$(drush sql:connect) < example.sql
. Bash: Import SQL statements from a file into the current database.eval (drush sql:connect) < example.sql
. Fish: Import SQL statements from a file into the current database.drush topic
and pick the first choice.Legend
Create a database.
"},{"location":"commands/sql_create/#examples","title":"Examples","text":"drush sql:create
. Create the database for the current site.drush @site.test sql:create
. Create the database as specified for @site.test.drush sql:create --db-su=root --db-su-pw=rootpassword --db-url=\"mysql://drupal_db_user:drupal_db_password@127.0.0.1/drupal_db\"
. Create the database as specified in the db-url option.drush topic
and pick the first choice.Legend
Drop all tables in a given database.
"},{"location":"commands/sql_drop/#options","title":"Options","text":"drush topic
and pick the first choice.Legend
Exports the Drupal DB as SQL using mysqldump or equivalent.
--create-db is used by sql-sync, since including the DROP TABLE statements interferes with the import when the database is created.
"},{"location":"commands/sql_dump/#examples","title":"Examples","text":"drush sql:dump --result-file=../18.sql
. Save SQL dump to the directory above Drupal root.drush sql:dump --skip-tables-key=common
. Skip standard tables. See Drush configurationdrush sql:dump --extra-dump=--no-data
. Pass extra option to mysqldump command.drush topic
and pick the first choice.Legend
Execute a query against a database.
"},{"location":"commands/sql_query/#examples","title":"Examples","text":"drush sql:query \"SELECT * FROM users WHERE uid=1\"
. Browse user record. Table prefixes, if used, must be added to table names by hand.drush sql:query --db-prefix \"SELECT * FROM {users}\"
. Browse user record. Table prefixes are honored. Caution: All curly-braces will be stripped.$(drush sql:connect) < example.sql
. Import sql statements from a file into the current database.drush sql:query --file=example.sql
. Alternate way to import sql statements from a file.drush php:eval --format=json \"return \\Drupal::service('database')->query('SELECT * FROM users LIMIT 5')->fetchAll()\"
. Get data back in JSON format. See https://github.com/drush-ops/drush/issues/3071#issuecomment-347929777.$(drush sql:connect) -e \"SELECT * FROM users LIMIT 5;\"
. Results are formatted in a pretty table with borders and column headers.drush topic
and pick the first choice.Legend
Sanitize the database by removing or obfuscating user data.
Commandfiles may add custom operations by implementing:
- `#[CLI\\Hook(type: HookManager::ON_EVENT, target: SanitizeCommands::CONFIRMS)]`. Display summary to user before confirmation.\n- `#[CLI\\Hook(type: HookManager::POST_COMMAND_HOOK, target: SanitizeCommands::SANITIZE)]`. Run queries or call APIs to perform sanitizing\n
Several working commandfiles may be found at https://github.com/drush-ops/drush/tree/12.x/src/Drupal/Commands/sql
"},{"location":"commands/sql_sanitize/#examples","title":"Examples","text":"drush sql:sanitize --sanitize-password=no
. Sanitize database without modifying any passwords.drush sql:sanitize --allowlist-fields=field_biography,field_phone_number
. Sanitizes database but exempts two user fields from modification.drush topic
and pick the first choice.Legend
Copy DB data from a source site to a target site. Transfers data via rsync.
"},{"location":"commands/sql_sync/#examples","title":"Examples","text":"drush sql:sync @source @self
. Copy the database from the site with the alias 'source' to the local site.drush sql:sync @self @target
. Copy the database from the local site to the site with the alias 'target'.drush sql:sync #prod #dev
. Copy the database from the site in /sites/prod to the site in /sites/dev (multisite installation).drush topic
and pick the first choice.Legend
Delete a state entry.
"},{"location":"commands/state_delete/#examples","title":"Examples","text":"drush state:del system.cron_last
. Delete state entry for system.cron_last.drush topic
and pick the first choice.Legend
Display a state value.
"},{"location":"commands/state_get/#examples","title":"Examples","text":"drush state:get system.cron_last
. Displays last cron run timestampdrush state:get drupal_css_cache_files --format=yaml
. Displays an array of css files in yaml format.drush topic
and pick the first choice.Legend
Set a state value.
"},{"location":"commands/state_set/#examples","title":"Examples","text":"drush sset system.maintenance_mode 1 --input-format=integer
. Put site into Maintenance mode.drush state:set system.cron_last 1406682882 --input-format=integer
. Sets a timestamp for last cron run.php -r \"print json_encode(array('drupal', 'simpletest'));\" | drush state-set --input-format=json foo.name -
. Set a key to a complex value (e.g. array)drush state:set twig_debug TRUE
. Enable the Twig debug mode (since Drupal 10.1)drush state:set twig_autoreload TRUE
. Enable Twig auto reload (since Drupal 10.1)drush state:set twig_cache_disable TRUE
. Disable the Twig, page, render and dynamic page caches (since Drupal 10.1)drush state:set disable_rendered_output_cache_bins TRUE
. Disables render cache, dynamic page cache, and page cache. (since Drupal 10.1)drush topic
and pick the first choice.Legend
Install one or more themes.
"},{"location":"commands/theme_install/#arguments","title":"Arguments","text":"drush topic
and pick the first choice.Legend
Uninstall themes.
"},{"location":"commands/theme_uninstall/#arguments","title":"Arguments","text":"drush topic
and pick the first choice.Legend
Compile all Twig template(s).
"},{"location":"commands/twig_compile/#global-options","title":"Global Options","text":"drush topic
and pick the first choice.Legend
12.1+
Enables Twig debug and disables caching Twig templates.
"},{"location":"commands/twig_debug/#arguments","title":"Arguments","text":"drush topic
and pick the first choice.Legend
Find potentially unused Twig templates.
Immediately before running this command, web crawl your entire web site. Or use your Production PHPStorage dir for comparison.
"},{"location":"commands/twig_unused/#examples","title":"Examples","text":"drush twig:unused --field=template /var/www/mass.local/docroot/modules/custom,/var/www/mass.local/docroot/themes/custom
. Output a simple list of potentially unused templates.drush topic
and pick the first choice.Legend
Apply any database updates required (as with running update.php).
"},{"location":"commands/updatedb/#options","title":"Options","text":"drush topic
and pick the first choice.Legend
List any pending database updates.
"},{"location":"commands/updatedb_status/#options","title":"Options","text":"drush topic
and pick the first choice.Legend
Block the specified user(s).
"},{"location":"commands/user_block/#examples","title":"Examples","text":"drush user:block user3
. Block the user whose name is user3drush user:cancel user3 --delete-content
. Delete the user whose name is user3 and delete her content.drush user:cancel user3 --reassign-content
. Delete the user whose name is user3 and reassign her content to the anonymous user.drush topic
and pick the first choice.Legend
Block or delete user account(s) with the specified name(s).
drush user:cancel username
. Block the user account with the name username.drush user:cancel --delete-content username
. Delete the user account with the name username and delete all content created by that user.drush user:cancel --reassign-content username
. Delete the user account with the name username and assign all her content to the anonymous user.drush topic
and pick the first choice.Legend
Create a user account.
"},{"location":"commands/user_create/#examples","title":"Examples","text":"drush user:create newuser --mail='person@example.com' --password='letmein'
. Create a new user account with the name newuser, the email address person@example.com, and the password letmeindrush topic
and pick the first choice.Legend
Print information about the specified user(s).
"},{"location":"commands/user_information/#examples","title":"Examples","text":"drush user:information someguy,somegal
. Display information about the someguy and somegal user accounts.drush user:information --mail=someguy@somegal.com
. Display information for a given email account.drush user:information --uid=5
. Display information for a given user id.drush uinf --uid=$(drush sqlq \"SELECT GROUP_CONCAT(entity_id) FROM user__roles WHERE roles_target_id = 'administrator'\")
. Display information for all administrators.drush topic
and pick the first choice.Legend
Display a one time login link for user ID 1, or another user.
"},{"location":"commands/user_login/#examples","title":"Examples","text":"drush user:login
. Open browser to homepage, logged in as uid=1.drush user:login --name=ryan node/add/blog
. Open browser (if configured or detected) for a one-time login link for username ryan that redirects to node/add/blog.drush user:login --uid=123
. Open browser and login as user with uid \"123\".drush user:login --mail=foo@bar.com
. Open browser and login as user with mail \"foo@bar.com\".drush topic
and pick the first choice.Legend
Set the password for the user account with the specified name.
"},{"location":"commands/user_password/#examples","title":"Examples","text":"drush user:password someuser 'correct horse battery staple'
. Set the password for the username someuser. See https://xkcd.com/936drush topic
and pick the first choice.Legend
Add a role to the specified user accounts.
"},{"location":"commands/user_role_add/#examples","title":"Examples","text":"drush user:role:add 'editor' user3
. Add the editor role to user3drush topic
and pick the first choice.Legend
Remove a role from the specified user accounts.
"},{"location":"commands/user_role_remove/#examples","title":"Examples","text":"drush user:role:remove 'power_user' user3
. Remove the power_user role from user3drush topic
and pick the first choice.Legend
Unblock the specified user(s).
"},{"location":"commands/user_unblock/#examples","title":"Examples","text":"drush user:unblock user3
. Unblock the user whose name is user3drush topic
and pick the first choice.Legend
Show Drush version.
"},{"location":"commands/version/#options","title":"Options","text":"drush topic
and pick the first choice.Legend
Set several Views settings to more developer-oriented values.
"},{"location":"commands/views_dev/#global-options","title":"Global Options","text":"drush topic
and pick the first choice.Legend
Disable the specified views.
"},{"location":"commands/views_disable/#examples","title":"Examples","text":"drush vdis frontpage taxonomy_term
. Disable the frontpage and taxonomy_term views.drush topic
and pick the first choice.Legend
Enable the specified views.
"},{"location":"commands/views_enable/#examples","title":"Examples","text":"drush ven frontpage,taxonomy_term
. Enable the frontpage and taxonomy_term views.drush topic
and pick the first choice.Legend
Execute a view and show a count of the results, or the rendered HTML.
"},{"location":"commands/views_execute/#examples","title":"Examples","text":"drush views:execute my_view
. Show the rendered HTML for the default display for the my_view View.drush views:execute my_view page_1 3 --count
. Show a count of my_view:page_1 where the first contextual filter value is 3.drush views:execute my_view page_1 3,foo
. Show the rendered HTML of my_view:page_1 where the first two contextual filter values are 3 and 'foo' respectively.drush topic
and pick the first choice.Legend
Get a list of all views in the system.
"},{"location":"commands/views_list/#examples","title":"Examples","text":"drush vl
. Show a list of all available views.drush vl --name=blog
. Show a list of views which names contain 'blog'.drush vl --tags=tag1,tag2
. Show a list of views tagged with 'tag1' or 'tag2'.drush vl --status=enabled
. Show a list of enabled views.drush topic
and pick the first choice.Legend
Delete watchdog log records.
"},{"location":"commands/watchdog_delete/#examples","title":"Examples","text":"drush watchdog:delete all
. Delete all messages.drush watchdog:delete 64
. Delete messages with id 64.drush watchdog:delete \"cron run succesful\"
. Delete messages containing the string \"cron run succesful\".drush watchdog:delete --severity=Notice
. Delete all messages with a severity of notice.drush watchdog:delete --type=cron
. Delete all messages of type cron.drush topic
and pick the first choice.Legend
Interactively filter the watchdog message listing.
"},{"location":"commands/watchdog_list/#examples","title":"Examples","text":"drush watchdog:list
. Prompt for message type or severity, then run watchdog:show.drush topic
and pick the first choice.Legend
Show one log record by ID.
"},{"location":"commands/watchdog_show-one/#arguments","title":"Arguments","text":"drush topic
and pick the first choice.Legend
Show watchdog messages.
"},{"location":"commands/watchdog_show/#examples","title":"Examples","text":"drush watchdog:show
. Show a listing of most recent 10 messages.drush watchdog:show \"cron run successful\"
. Show a listing of most recent 10 messages containing the string cron run successful.drush watchdog:show --count=46
. Show a listing of most recent 46 messages.drush watchdog:show --severity=Notice
. Show a listing of most recent 10 messages with a severity of notice.drush watchdog:show --severity-min=Warning
. Show a listing of most recent 10 messages with a severity of warning or higher.drush watchdog:show --type=php
. Show a listing of most recent 10 messages of type phpdrush topic
and pick the first choice.Legend
10.6+
Tail watchdog messages.
"},{"location":"commands/watchdog_tail/#examples","title":"Examples","text":"drush watchdog:tail
. Continuously tail watchdog messages.drush watchdog:tail \"cron run successful\"
. Continuously tail watchdog messages, filtering on the string cron run successful.drush watchdog:tail --severity=Notice
. Continuously tail watchdog messages, filtering severity of notice.drush watchdog:tail --severity-min=Warning
. Continuously tail watchdog messages, filtering for a severity of warning or higher.drush watchdog:tail --type=php
. Continuously tail watchdog messages, filtering on type equals php.drush topic
and pick the first choice.Legend
12.0+
Get a value for a specific key in a YAML file.
See https://github.com/grasmash/yaml-cli for a README and bug reports.
"},{"location":"commands/yaml_get_value/#arguments","title":"Arguments","text":"drush topic
and pick the first choice.Legend
12.0+
Validates that a given YAML file has valid syntax.
See https://github.com/grasmash/yaml-cli for a README and bug reports.
"},{"location":"commands/yaml_lint/#arguments","title":"Arguments","text":"drush topic
and pick the first choice.Legend
12.0+
Unset a specific key in a YAML file.
See https://github.com/grasmash/yaml-cli for a README and bug reports.
"},{"location":"commands/yaml_unset_key/#arguments","title":"Arguments","text":"drush topic
and pick the first choice.Legend
12.0+
Update a specific key in a YAML file.
See https://github.com/grasmash/yaml-cli for a README and bug reports.
"},{"location":"commands/yaml_update_key/#arguments","title":"Arguments","text":"drush topic
and pick the first choice.Legend
12.0+
Update the value for a specific key in a YAML file.
See https://github.com/grasmash/yaml-cli for a README and bug reports.
"},{"location":"commands/yaml_update_value/#arguments","title":"Arguments","text":"drush topic
and pick the first choice.Legend
Drush is built by people like you! Please join us.
"},{"location":"contribute/CONTRIBUTING/#git-and-pull-requests","title":"Git and Pull requests","text":"13.x
branch. PR's should initially target this branch.composer run-script -l
for a list of helper scripts.composer cs
to check the project for coding style issues and run composer cbf
to fix them automatically where possible. These scripts use PHP_CodeSniffer
in background.drush topic
command.Drush's test suite (aka Unish) is based on PHPUnit. In order to maintain high quality, our tests are run on every push. See CircleCi.
"},{"location":"contribute/unish/#usage","title":"Usage","text":"git clone https://github.com/drush-ops/drush.git
cd drush
composer install
composer test
11.0+
Drush's own tests may be run within provided Docker containers via DDEV
ddev start
ddev exec drupal composer functional -- --filter testUserRole
composer unit
composer integration
composer functional
composer functional -- --filter testUserRole
composer functional -- --exclude-group slow
composer functional -- --log-junit results.xml
composer sut:si
. See composer.json for details.UNISH_DIRTY=1 composer functional -- --filter testUserRole
./drush @sut.dev status
@bootstrap full
, and it is not possible to test loading different Drush configuration files and so on. It is not possible to test argument / option parsing. The shutdown and error handlers are not installed, so PHP deprecation warnings will be evidenced in the integration tests.exec
ing the Drush executable. All functional tests therefore run in their own separate processes. The Drupal System Under Test is set up every time it is needed by any functional test. It is therefore okay if a functional test changes the state of the SUT. The codebase is re-used, so no destructive changes should be made to the code.Drush provides test traits that may be used to test your own Drush extensions. Adding the traits varies slightly depending how you package your Drush extension.
drush/drush
to your module's composer.json (require-dev
section).Once you successfully have use Drush\\TestTraits\\DrushTestTrait
in your test class, you are able to write simple tests that call your extension's commands and makes assertions against the output.
public function testMyCommand()\n {\n $this->drush('my:command', ['param'], ['flag' => 'value']);\n $this->assertOutputEquals('The parameter is \"param\" and the \"flag\" option is \"value\"');\n }\n
"},{"location":"examples/ArtCommands.php/","title":"ArtCommands.php","text":"<?php\n\nnamespace Drush\\Commands;\n\nuse Consolidation\\AnnotatedCommand\\AnnotationData;\nuse Consolidation\\AnnotatedCommand\\CommandData;\nuse Consolidation\\AnnotatedCommand\\Events\\CustomEventAwareInterface;\nuse Consolidation\\AnnotatedCommand\\Events\\CustomEventAwareTrait;\nuse Consolidation\\AnnotatedCommand\\Hooks\\HookManager;\nuse Consolidation\\OutputFormatters\\StructuredData\\RowsOfFields;\nuse Drush\\Attributes as CLI;\nuse Drush\\Style\\DrushStyle;\nuse Symfony\\Component\\Console\\Input\\InputInterface;\nuse Symfony\\Component\\Console\\Output\\OutputInterface;\n\n/**\n * Run these commands using the --include option - e.g. `drush --include=/path/to/drush/examples art sandwich`\n *\n * See [Drush Test Traits](https://github.com/drush-ops/drush/blob/12.x/docs/contribute/unish.md#about-the-test-suites) for info on testing Drush commands.\n */\n\nclass ArtCommands extends DrushCommands implements CustomEventAwareInterface\n{\n use CustomEventAwareTrait;\n\n /** @var string[] */\n protected ?array $arts;\n\n /**\n * Show a fabulous picture.\n */\n #[CLI\\Command(name: 'artwork:show', aliases: ['arts'])]\n #[CLI\\Argument(name: 'art', description: 'The name of the art to display')]\n #[CLI\\Usage(name: 'drush art sandwich', description: 'Show a marvelous picture of a sandwich with pickles.')]\n public function art($art = '')\n {\n $data = $this->getArt();\n $name = $data[$art]['name'];\n $description = $data[$art]['description'];\n $path = $data[$art]['path'];\n $msg = dt(\n 'Okay. Here is {art}: {description}',\n ['art' => $name, 'description' => $description]\n );\n $this->output()->writeln(\"\\n\" . $msg . \"\\n\");\n $this->printFile($path);\n }\n\n /**\n * Show a table of information about available art.\n */\n #[CLI\\Command(name: 'artwork:list', aliases: ['artls'])]\n #[CLI\\FieldLabels(labels: ['name' => 'Name', 'description' => 'Description', 'path' => 'Path'])]\n #[CLI\\DefaultTableFields(fields: ['name', 'description'])]\n #[CLI\\FilterDefaultField(field: 'name')]\n public function listArt($options = ['format' => 'table']): RowsOfFields\n {\n $data = $this->getArt();\n return new RowsOfFields($data);\n }\n\n /**\n * Commandfiles may also add topics. These will appear in\n * the list of topics when `drush topic` is executed.\n * To view the topic below, run `drush --include=/full/path/to/examples topic`\n */\n\n /**\n * Ruminations on the true meaning and philosophy of artwork.\n */\n #[CLI\\Command(name: 'artwork:explain')]\n #[CLI\\Topics(isTopic: true, path: __DIR__ . '/art-topic.md')]\n #[CLI\\Help(hidden: true)]\n public function ruminate(): void\n {\n self::printFile($this->commandData);\n }\n\n /**\n * Return the available built-in art. Any Drush commandfile may provide\n * more art by implementing a 'drush-art' on-event hook. This on-event\n * hook is defined in the 'findArt' method below.\n */\n #[CLI\\Hook(type: HookManager::ON_EVENT, target: 'drush-art')]\n public function builtInArt()\n {\n return [\n 'drush' => [\n 'name' => 'Drush',\n 'description' => 'The Drush logo.',\n 'path' => __DIR__ . '/art/drush-nocolor.txt',\n ],\n 'sandwich' => [\n 'name' => 'Sandwich',\n 'description' => 'A tasty meal with bread often consumed at lunchtime.',\n 'path' => __DIR__ . '/art/sandwich-nocolor.txt',\n ],\n ];\n }\n\n #[CLI\\Hook(type: HookManager::INTERACT, target: 'artwork:show')]\n public function interact(InputInterface $input, OutputInterface $output, AnnotationData $annotationData)\n {\n $io = new DrushStyle($input, $output);\n\n // If the user did not specify any artwork, then prompt for one.\n $art = $input->getArgument('art');\n if (empty($art)) {\n $data = $this->getArt();\n $selections = $this->convertArtListToKeyValue($data);\n $selection = $io->choice('Select art to display', $selections);\n $input->setArgument('art', $selection);\n }\n }\n\n #[CLI\\Hook(type: HookManager::ARGUMENT_VALIDATOR, target: 'artwork:show')]\n public function artValidate(CommandData $commandData)\n {\n $art = $commandData->input()->getArgument('art');\n $data = $this->getArt();\n if (!isset($data[$art])) {\n throw new \\Exception(dt('I do not have any art called \"{name}\".', ['name' => $art]));\n }\n }\n\n /**\n * Get a list of available artwork. Cache result for future fast access.\n */\n protected function getArt(): array\n {\n if (!isset($this->arts)) {\n $this->arts = $this->findArt();\n }\n return $this->arts;\n }\n\n /**\n * Use custom defined on-event hook 'drush-art' to find available artwork.\n */\n protected function findArt()\n {\n $arts = [];\n $handlers = $this->getCustomEventHandlers('drush-art');\n foreach ($handlers as $handler) {\n $handlerResult = $handler();\n $arts = array_merge($arts, $handlerResult);\n }\n return $arts;\n }\n\n /**\n * Given a list of artwork, convert to a 'key' => 'Name: Description' array.\n */\n protected function convertArtListToKeyValue(array $data): array\n {\n $result = [];\n foreach ($data as $key => $item) {\n $result[$key] = $item['name'] . ': ' . $item['description'];\n }\n return $result;\n }\n}\n
"},{"location":"examples/PolicyCommands.php/","title":"PolicyCommands.php","text":"<?php\n\nnamespace Drush\\Commands;\n\nuse Consolidation\\AnnotatedCommand\\CommandData;\nuse Consolidation\\AnnotatedCommand\\Hooks\\HookManager;\nuse Drush\\Attributes as CLI;\nuse Drush\\Commands\\core\\RsyncCommands;\nuse Drush\\Commands\\core\\UpdateDBCommands;\nuse Drush\\Commands\\DrushCommands;\nuse Drush\\Commands\\sql\\SqlSyncCommands;\nuse Symfony\\Component\\Console\\Input\\InputOption;\n\n/**\n * Load this commandfile using the --include option - e.g. `drush --include=/path/to/drush/examples`\n *\n * See [Drush Test Traits](https://github.com/drush-ops/drush/blob/12.x/docs/contribute/unish.md#about-the-test-suites) for info on testing Drush commands.\n */\n\nclass PolicyCommands extends DrushCommands\n{\n /**\n * Prevent catastrophic braino. Note that this file has to be local to the\n * machine that initiates the sql:sync command.\n *\n * @throws \\Exception\n */\n #[CLI\\Hook(type: HookManager::ARGUMENT_VALIDATOR, target: SqlSyncCommands::SYNC)]\n public function sqlSyncValidate(CommandData $commandData)\n {\n if ($commandData->input()->getArgument('target') == '@prod') {\n throw new \\Exception(dt('Per !file, you may never overwrite the production database.', ['!file' => __FILE__]));\n }\n }\n\n /**\n * Limit rsync operations to production site.\n */\n #[CLI\\Hook(type: HookManager::ARGUMENT_VALIDATOR, target: RsyncCommands::RSYNC)]\n public function rsyncValidate(CommandData $commandData)\n {\n if (preg_match(\"/^@prod/\", $commandData->input()->getArgument('target'))) {\n throw new \\Exception(dt('Per !file, you may never rsync to the production site.', ['!file' => __FILE__]));\n }\n }\n\n /**\n * Unauthorized may not execute updates.\n */\n #[CLI\\Hook(type: HookManager::ARGUMENT_VALIDATOR, target: UpdateDBCommands::UPDATEDB)]\n public function validateUpdateDb(CommandData $commandData)\n {\n if (!$commandData->input()->getOption('secret') == 'mysecret') {\n throw new \\Exception(dt('UpdateDb command requires a secret token per site policy.'));\n }\n }\n\n #[CLI\\Hook(type: HookManager::OPTION_HOOK, target: UpdateDBCommands::UPDATEDB)]\n #[CLI\\Option(name: 'secret', description: 'A required token else user may not run updatedb command.')]\n public function optionsetUpdateDb($options = ['secret' => self::REQ])\n {\n }\n}\n
"},{"location":"examples/SiteAliasAlterCommands.php/","title":"SiteAliasAlterCommands.php","text":"<?php\n\nnamespace Drush\\Commands;\n\nuse Consolidation\\AnnotatedCommand\\AnnotationData;\nuse Consolidation\\AnnotatedCommand\\Hooks\\HookManager;\nuse Consolidation\\SiteAlias\\SiteAliasManagerAwareInterface;\nuse Consolidation\\SiteAlias\\SiteAliasManagerAwareTrait;\nuse Drush\\Attributes as CLI;\nuse Symfony\\Component\\Console\\Input\\InputInterface;\n\n/**\n * Load this example by using the --include option - e.g. `drush --include=/path/to/drush/examples`\n */\nclass SiteAliasAlterCommands extends DrushCommands implements SiteAliasManagerAwareInterface\n{\n use SiteAliasManagerAwareTrait;\n\n /**\n * A few example alterations to site aliases.\n */\n #[CLI\\Hook(type: HookManager::PRE_INITIALIZE, target: '*')]\n public function alter(InputInterface $input, AnnotationData $annotationData)\n {\n $self = $this->siteAliasManager()->getSelf();\n if ($self->isRemote()) {\n // Always pass along ssh keys.\n if (!$self->has('ssh.options')) {\n // Don't edit the alias - edit the general config service instead.\n $this->getConfig()->set('ssh.options', '-o ForwardAgent=yes');\n }\n\n // Change the SSH user.\n $input->setOption('remote-user', 'mw2');\n\n // Test to see if specific environment really exists in wildcard\n // aliases, but only if the target is a specific host.\n $host = $self->get('host');\n if (preg_match('#\\.myserver.com$#', $host)) {\n $ip = gethostbyname($host);\n // If the return value of gethostbyname equals its input parameter,\n // that indicates failure.\n if ($host == $ip) {\n $aliasName = $self->name();\n throw new \\Exception(\"The alias $aliasName refers to an environment that does not exist.\");\n }\n }\n }\n }\n}\n
"},{"location":"examples/SyncViaHttpCommands.php/","title":"SyncViaHttpCommands.php","text":"<?php\n\nnamespace Drush\\Commands;\n\nuse Consolidation\\AnnotatedCommand\\CommandData;\nuse Consolidation\\AnnotatedCommand\\Hooks\\HookManager;\nuse Drush\\Attributes as CLI;\nuse Drush\\Commands\\DrushCommands;\nuse Drush\\Commands\\sql\\SqlSyncCommands;\nuse Drush\\Drush;\nuse Drush\\Exec\\ExecTrait;\nuse Symfony\\Component\\Filesystem\\Filesystem;\n\n/**\n * Load this commandfile using the --include option - e.g. `drush --include=/path/to/drush/examples`\n */\n\nclass SyncViaHttpCommands extends DrushCommands\n{\n /**\n * When a hook extends a command with additional options, it must\n * implement declare those option(s) in a @hook option like this one. Doing so will add\n * the option to the help text for the modified command, and will also\n * allow the new option to be specified on the command line. Without\n * this, Drush will fail with an error when a user attempts to use\n * an unknown option.\n */\n #[CLI\\Hook(type: HookManager::OPTION_HOOK, target: SqlSyncCommands::SYNC)]\n #[CLI\\Option(name: 'http-sync', description: 'Copy the database via http instead of rsync. Value is the url that the existing database dump can be found at.')]\n #[CLI\\Option(name: 'http-sync-user', description: 'Username for the protected directory containing the sql dump.')]\n #[CLI\\Option(name: 'http-sync-password', description: 'Password for the same directory.')]\n public function optionsetSqlSync()\n {\n }\n\n /**\n * During the pre hook, determine if the http-sync option has been\n * specified. If it has been, then disable the normal ssh + rsync\n * dump-and-transfer that sql-sync usually does, and transfer the\n * database dump via an http download.\n */\n #[CLI\\Hook(type: HookManager::PRE_COMMAND_HOOK, target: SqlSyncCommands::SYNC)]\n public function preSqlSync(CommandData $commandData)\n {\n $sql_dump_download_url = $commandData->input()->getOption('http-sync');\n if (!empty($sql_dump_download_url)) {\n $user = $commandData->input()->getOption('http-sync-user');\n $password = $commandData->input()->getOption('http-sync-password');\n $source_dump_file = $this->downloadFile($sql_dump_download_url, $user, $password);\n $commandData->input()->setOption('target-dump', $source_dump_file);\n $commandData->input()->setOption('no-dump', true);\n $commandData->input()->setOption('no-sync', true);\n }\n }\n\n /**\n * Downloads a file.\n *\n * Optionally uses user authentication, using either wget or curl, as available.\n */\n protected function downloadFile($url, $user = false, $password = false, $destination = false, $overwrite = true)\n {\n static $use_wget;\n if ($use_wget === null) {\n $use_wget = ExecTrait::programExists('wget');\n }\n\n $destination_tmp = drush_tempnam('download_file');\n if ($use_wget) {\n $args = ['wget', '-q', '--timeout=30'];\n if ($user && $password) {\n $args = array_merge($args, [\"--user=$user\", \"--password=$password\", '-O', $destination_tmp, $url]);\n } else {\n $args = array_merge($args, ['-O', $destination_tmp, $url]);\n }\n } else {\n $args = ['curl', '-s', '-L', '--connect-timeout 30'];\n if ($user && $password) {\n $args = array_merge($args, ['--user', \"$user:$password\", '-o', $destination_tmp, $url]);\n } else {\n $args = array_merge($args, ['-o', $destination_tmp, $url]);\n }\n }\n $process = Drush::process($args);\n $process->mustRun();\n\n if (!Drush::simulate()) {\n if (!drush_file_not_empty($destination_tmp) && $file = @file_get_contents($url)) {\n @file_put_contents($destination_tmp, $file);\n }\n if (!drush_file_not_empty($destination_tmp)) {\n // Download failed.\n throw new \\Exception(dt(\"The URL !url could not be downloaded.\", ['!url' => $url]));\n }\n }\n if ($destination) {\n $fs = new Filesystem();\n $fs->rename($destination_tmp, $destination, $overwrite);\n return $destination;\n }\n return $destination_tmp;\n }\n}\n
"},{"location":"examples/XkcdCommands.php/","title":"XkcdCommands.php","text":"<?php\n\nnamespace Drush\\Commands;\n\nuse Drush\\Attributes as CLI;\nuse Drush\\Exec\\ExecTrait;\n\n/**\n * Run these commands using the --include option - e.g. `drush --include=/path/to/drush/examples xkcd`\n *\n * For an example of a Drush extension with tests for Drush:\n * - https://github.com/drush-ops/example-drush-extension\n */\n\nclass XkcdCommands extends DrushCommands\n{\n use ExecTrait;\n\n /**\n * Retrieve and display xkcd cartoons.\n */\n #[CLI\\Command(name: 'xkcd:fetch', aliases: ['xkcd'])]\n #[CLI\\Option(name: 'search', description: 'Optional argument to retrieve the cartoons matching an index number, keyword search or \"random\". If omitted the latest cartoon will be retrieved.')]\n #[CLI\\Option(name: 'image-viewer', description: 'Command to use to view images (e.g. xv, firefox). Defaults to \"display\" (from ImageMagick).')]\n #[CLI\\Option(name: 'google-custom-search-api-key', description: 'Google Custom Search API Key, available from https://code.google.com/apis/console/. Default key limited to 100 queries/day globally.')]\n #[CLI\\Usage(name: 'drush xkcd', description: 'Retrieve and display the latest cartoon.')]\n #[CLI\\Usage(name: 'drush xkcd sandwich', description: 'Retrieve and display cartoons about sandwiches.')]\n #[CLI\\Usage(name: 'drush xkcd 123 --image-viewer=eog', description: 'Retrieve and display cartoon #123 in eog.')]\n #[CLI\\Usage(name: 'drush xkcd random --image-viewer=firefox', description: 'Retrieve and display a random cartoon in Firefox.')]\n public function fetch($search = null, $options = ['image-viewer' => 'open', 'google-custom-search-api-key' => 'AIzaSyDpE01VDNNT73s6CEeJRdSg5jukoG244ek'])\n {\n $this->doFetch($search, $options);\n }\n\n /**\n * @param $search\n * @param array $options\n * @throws \\Exception\n */\n protected function doFetch($search, array $options): void\n {\n if (empty($search)) {\n $this->startBrowser('http://xkcd.com');\n } elseif (is_numeric($search)) {\n $this->startBrowser('http://xkcd.com/' . $search);\n } elseif ($search == 'random') {\n $xkcd_response = @json_decode(file_get_contents('http://xkcd.com/info.0.json'));\n if (!empty($xkcd_response->num)) {\n $this->startBrowser('http://xkcd.com/' . rand(1, $xkcd_response->num));\n }\n } else {\n // This uses an API key with a limited number of searches per.\n $search_response = @json_decode(file_get_contents('https://www.googleapis.com/customsearch/v1?key=' . $options['google-custom-search-api-key'] . '&cx=012652707207066138651:zudjtuwe28q&q=' . $search));\n if (!empty($search_response->items)) {\n foreach ($search_response->items as $item) {\n $this->startBrowser($item->link);\n }\n } else {\n throw new \\Exception(dt('The search failed or produced no results.'));\n }\n }\n }\n}\n
"},{"location":"examples/example.drush.yml/","title":"drush.yml","text":"#\n# A minimalist Drush config file.\n# See https://www.drush.org/latest/using-drush-configuration/ for lots more documentation.\n#\n\n# Preflight configuration.\ndrush:\ninclude:\n- '${env.HOME}/.drush/commands'\n- /usr/share/drush/commands\npaths:\nconfig:\n# Load additional config files. Is silently skipped if not found. Filename must be drush.yml\n- ${env.HOME}/.drush/config/drush.yml\nalias-path:\n- '${env.HOME}/.drush/sites'\n- /etc/drush/sites\n\n# Global options.\noptions:\n# Specify the base_url that should be used when generating links.\n# uri: 'http://example.com/subdir'\n\n# Command-specific options.\ncommand:\nsql:\ndump:\noptions:\n# Uncomment to omit cache and similar tables (including during a sql:sync).\n# structure-tables-key: common\n\n# Non-options.\nssh:\n# Specify options to pass to ssh. The default is to prohibit\n# password authentication, and is included here, so you may add additional\n# parameters without losing the default configuration.\noptions: '-o PasswordAuthentication=no'\n# This string is valid for Bash shell. Override in case you need something different. See https://github.com/drush-ops/drush/issues/3816.\npipefail: 'set -o pipefail; '\n
"},{"location":"examples/example.prompt.sh/","title":"prompt.sh","text":"# -*- mode: shell-script; mode: flyspell-prog; ispell-local-dictionary: \"american\" -*-\n#\n# Example PS1 prompt.\n#\n# Note: This file does a lot, and is designed for Bash. If you want to show the\n# currently set alias in your prompt, use the first 2 values below as an example.\n\n# This section can be used for the POWERLEVEL9K theme for Oh My Zsh.\n#FILE=\"${TMPDIR:-/tmp/}/drush-env-${USER}/drush-drupal-site-$$\"\n#POWERLEVEL9K_CUSTOM_DRUSH=\"[ -r $FILE ] && cat $FILE\"\n#POWERLEVEL9K_CUSTOM_DRUSH_BACKGROUND=\"green\"\n#POWERLEVEL9K_LEFT_PROMPT_ELEMENTS=(context dir vcs custom_drush)\n\n#\n# Note that your Bash session must already have the __git_ps1 function available.\n# Typically this is provided by git-prompt.sh, see instructions for downloading\n# and including this file here:\n# https://github.com/git/git/blob/10.x/contrib/completion/git-prompt.sh\n#\n# Features:\n#\n# Displays Git repository and Drush alias status in your prompt.\n\n__drush_ps1() {\nf=\"${TMPDIR:-/tmp/}/drush-env-${USER}/drush-drupal-site-$$\"\nif [ -f $f ]\nthen\n__DRUPAL_SITE=$(cat \"$f\")\nelse\n__DRUPAL_SITE=\"$DRUPAL_SITE\"\nfi\n\n# Set DRUSH_PS1_SHOWCOLORHINTS to a non-empty value and define a\n# __drush_ps1_colorize_alias() function for color hints in your Drush PS1\n# prompt. See example.prompt.sh for an example implementation.\nif [ -n \"${__DRUPAL_SITE-}\" ] && [ -n \"${DRUSH_PS1_SHOWCOLORHINTS-}\" ]; then\n__drush_ps1_colorize_alias\n fi\n\n[[ -n \"$__DRUPAL_SITE\" ]] && printf \"${1:- (%s)}\" \"$__DRUPAL_SITE\"\n}\n\nif [ -n \"$(type -t __git_ps1)\" ] && [ \"$(type -t __git_ps1)\" = function ] && [ \"$(type -t __drush_ps1)\" ] && [ \"$(type -t __drush_ps1)\" = function ]; then\n\n# This line enables color hints in your Drush prompt. Modify the below\n# __drush_ps1_colorize_alias() to customize your color theme.\nDRUSH_PS1_SHOWCOLORHINTS=true\n\n# Git offers various prompt customization options as well as seen in\n# https://github.com/git/git/blob/10.x/contrib/completion/git-prompt.sh.\n# Adjust the following lines to enable the corresponding features:\n#\nGIT_PS1_SHOWDIRTYSTATE=true\nGIT_PS1_SHOWUPSTREAM=auto\n # GIT_PS1_SHOWSTASHSTATE=true\n# GIT_PS1_SHOWUNTRACKEDFILES=true\nGIT_PS1_SHOWCOLORHINTS=true\n\n# The following line sets your bash prompt according to this example:\n#\n# username@hostname ~/working-directory (git-branch)[@drush-alias] $\n#\n# See http://ss64.com/bash/syntax-prompt.html for customization options.\nexport PROMPT_COMMAND='__git_ps1 \"\\u@\\h \\w\" \"$(__drush_ps1 \"[%s]\") \\\\\\$ \"'\n\n# PROMPT_COMMAND is used in the example above rather than PS1 because neither\n# Git nor Drush color hints are compatible with PS1. If you don't want color\n# hints, however, and prefer to use PS1, you can still do so by commenting out\n# the PROMPT_COMMAND line above and uncommenting the PS1 line below:\n#\n# export PS1='\\u@\\h \\w$(__git_ps1 \" (%s)\")$(__drush_ps1 \"[%s]\")\\$ '\n\n__drush_ps1_colorize_alias() {\nif [[ -n ${ZSH_VERSION-} ]]; then\nlocal COLOR_BLUE='%F{blue}'\nlocal COLOR_CYAN='%F{cyan}'\nlocal COLOR_GREEN='%F{green}'\nlocal COLOR_MAGENTA='%F{magenta}'\nlocal COLOR_RED='%F{red}'\nlocal COLOR_WHITE='%F{white}'\nlocal COLOR_YELLOW='%F{yellow}'\nlocal COLOR_NONE='%f'\nelse\n# Using \\[ and \\] around colors is necessary to prevent issues with\n# command line editing/browsing/completion.\nlocal COLOR_BLUE='\\[\\e[94m\\]'\nlocal COLOR_CYAN='\\[\\e[36m\\]'\nlocal COLOR_GREEN='\\[\\e[32m\\]'\nlocal COLOR_MAGENTA='\\[\\e[35m\\]'\nlocal COLOR_RED='\\[\\e[91m\\]'\nlocal COLOR_WHITE='\\[\\e[37m\\]'\nlocal COLOR_YELLOW='\\[\\e[93m\\]'\nlocal COLOR_NONE='\\[\\e[0m\\]'\nfi\n\n# Customize your color theme below.\ncase \"$__DRUPAL_SITE\" in\n*.live|*.prod) local ENV_COLOR=\"$COLOR_RED\" ;;\n*.stage|*.test) local ENV_COLOR=\"$COLOR_YELLOW\" ;;\n*.local) local ENV_COLOR=\"$COLOR_GREEN\" ;;\n*) local ENV_COLOR=\"$COLOR_BLUE\" ;;\nesac\n\n__DRUPAL_SITE=\"${ENV_COLOR}${__DRUPAL_SITE}${COLOR_NONE}\"\n}\n\nfi\n
"},{"location":"examples/example.site.yml/","title":"site.yml","text":"#\n# A minimalist Drush site alias file.\n# See https://www.drush.org/latest/site-aliases/ for lots more documentation.\n#\n# File: self.site.yml\nlive:\nhost: www.domain.com\nuser: www-admin\nroot: /other/path/to/drupal\nuri: http://www.example.com\nssh:\noptions: '-p 100'\npaths:\ndrush-script: '/path/to/drush'\nenv-vars:\nPATH: /bin:/usr/bin:/home/www-admin/.composer/vendor/bin\nDRUPAL_ENV: live\ncommand:\nsite:\ninstall:\noptions:\nadmin-password: 'secret-secret'\nstage:\nhost: stage.domain.com\nuser: www-admin\nroot: /other/path/to/drupal\nuri: http://stage.example.com\n
"},{"location":"examples/git-bisect.example.sh/","title":"git-bisect.sh","text":"#!/usr/bin/env sh\n\n#\n# Git bisect is a helpful way to discover which commit an error\n# occurred in. This example file gives simple instructions for\n# using git bisect with Drush to quickly find erroneous commits\n# in Drush commands or Drupal modules, presuming that you can\n# trigger the error condition via Drush (e.g. using `drush php-eval`).\n#\n# Follow these simple steps:\n#\n# $ git bisect start\n# $ git bisect bad # Tell git that the current commit does not work\n# $ git bisect good bcadd5a # Tell drush that the commithash 12345 worked fine\n# $ git bisect run mytestscript.sh\n#\n# 'git bisect run' will continue to call 'git bisect good' and 'git bisect bad',\n# based on whether the script's exit code was 0 or 1, respectively.\n#\n# Replace 'mytestscript.sh' in the example above with a custom script that you\n# write yourself. Use the example script at the end of this document as a\n# guide. Replace the example command with one that calls the Drush command\n# that you would like to test, and replace the 'grep' string with a value\n# that appears when the error exists in the commit, but does not appear when\n# commit is okay.\n#\n# If you are using Drush to test Drupal or an external Drush module, use:\n#\n# $ git bisect run drush mycommand --strict=2\n#\n# This presumes that there is one or more '[warning]' or '[error]'\n# messages emitted when there is a problem, and no warnings or errors\n# when the commit is okay. Omit '--strict=2' to ignore warnings, and\n# signal failure only when 'error' messages are emitted.\n#\n# If you need to test for an error condition explicitly, to find errors\n# that do not return any warning or error log messages on their own, you\n# can use the Drush php-eval command to force an error when `myfunction()`\n# returns FALSE. Replace 'myfunction()' with the name of an appropriate\n# function in your module that can be used to detect the error condition\n# you are looking for.\n#\n# $ git bisect run drush ev 'if(!myfunction()) { return drush_set_error(\"ERR\"); }'\n#\ndrush mycommand --myoption 2>&1 | grep -q 'string that indicates there was a problem'\nif [ $? == 0 ] ; then\nexit 1\nelse\nexit 0\nfi\n
"},{"location":"examples/helloworld.script/","title":"Helloworld.script","text":"<?php\n\n//\n// This example demonstrates how to write a drush\n// script. These scripts are run with the php:script command.\n//\nuse Drush\\Drush;\n\n$this->output()->writeln(\"Hello world!\");\n$this->output()->writeln(\"The extra options/arguments to this command were:\");\n$this->output()->writeln(print_r($extra, true));\n\n//\n// We can check which site was bootstrapped via\n// the '@self' alias, which is defined only if\n// there is a bootstrapped site.\n//\n$self = Drush::aliasManager()->getSelf();;\nif (!$self->hasRoot()) {\n $this->output()->writeln('No bootstrapped site.');\n}\nelse {\n $this->output()->writeln('The following site is bootstrapped:');\n $this->output()->writeln(print_r($self->legacyRecord(), true));\n}\n
"},{"location":"generators/all/","title":"All generators","text":"Tip
Press the / key to Search for a command. Or use your browser's Find in Page feature.
Generates a composer.json file
"},{"location":"generators/composer/#examples","title":"Examples","text":"drush generate composer
. Generates a composer.json fileGenerates a controller
"},{"location":"generators/controller/#examples","title":"Examples","text":"drush generate controller
. Generates a controllerGenerates a Drush site alias file.
"},{"location":"generators/drush_alias-file/#examples","title":"Examples","text":"drush generate drush:alias-file
. Generates a Drush site alias file.Generates a Drush command file.
"},{"location":"generators/drush_command-file/#examples","title":"Examples","text":"drush generate drush:command-file
. Generates a Drush command file.Generates Drush generator
"},{"location":"generators/drush_generator/#examples","title":"Examples","text":"drush generate drush:generator
. Generates Drush generatorGenerates Symfony console command
"},{"location":"generators/drush_symfony-command/#examples","title":"Examples","text":"drush generate drush:symfony-command
. Generates Symfony console command11.0+
Generate a bundle class for a content entity.
"},{"location":"generators/entity_bundle-class/#examples","title":"Examples","text":"drush generate entity:bundle-class
. Generate a bundle class for a content entity.Generates configuration entity
"},{"location":"generators/entity_configuration/#examples","title":"Examples","text":"drush generate entity:configuration
. Generates configuration entityGenerates content entity
"},{"location":"generators/entity_content/#examples","title":"Examples","text":"drush generate entity:content
. Generates content entityGenerates a field
"},{"location":"generators/field/#examples","title":"Examples","text":"drush generate field
. Generates a fieldGenerates a configuration form
"},{"location":"generators/form_config/#examples","title":"Examples","text":"drush generate form:config
. Generates a configuration formGenerates a confirmation form
"},{"location":"generators/form_confirm/#examples","title":"Examples","text":"drush generate form:confirm
. Generates a confirmation formGenerates simple form
"},{"location":"generators/form_simple/#examples","title":"Examples","text":"drush generate form:simple
. Generates simple formGenerates a hook
"},{"location":"generators/hook/#examples","title":"Examples","text":"drush generate hook
. Generates a hookGenerates an install file
"},{"location":"generators/install-file/#examples","title":"Examples","text":"drush generate install-file
. Generates an install fileGenerates Drupal JavaScript file
"},{"location":"generators/javascript/#examples","title":"Examples","text":"drush generate javascript
. Generates Drupal JavaScript fileGenerates a layout
"},{"location":"generators/layout/#examples","title":"Examples","text":"drush generate layout
. Generates a layoutGenerates an Apache site configuration file
"},{"location":"generators/misc_apache-virtual-host/#examples","title":"Examples","text":"drush generate misc:apache-virtual-host
. Generates an Apache site configuration fileGenerates an Nginx site configuration file
"},{"location":"generators/misc_nginx-virtual-host/#examples","title":"Examples","text":"drush generate misc:nginx-virtual-host
. Generates an Nginx site configuration fileGenerates Drupal module
"},{"location":"generators/module/#examples","title":"Examples","text":"drush generate module
. Generates Drupal moduleGenerates PhpStorm metadata
"},{"location":"generators/phpstorm-meta/#examples","title":"Examples","text":"drush generate phpstorm-meta
. Generates PhpStorm metadataGenerates action plugin
"},{"location":"generators/plugin_action/#examples","title":"Examples","text":"drush generate plugin:action
. Generates action pluginGenerates block plugin
"},{"location":"generators/plugin_block/#examples","title":"Examples","text":"drush generate plugin:block
. Generates block pluginGenerates CKEditor plugin
"},{"location":"generators/plugin_ckeditor/#examples","title":"Examples","text":"drush generate plugin:ckeditor
. Generates CKEditor pluginGenerates condition plugin
"},{"location":"generators/plugin_condition/#examples","title":"Examples","text":"drush generate plugin:condition
. Generates condition pluginGenerates constraint plugin
"},{"location":"generators/plugin_constraint/#examples","title":"Examples","text":"drush generate plugin:constraint
. Generates constraint pluginGenerates entity reference selection plugin
"},{"location":"generators/plugin_entity-reference-selection/#examples","title":"Examples","text":"drush generate plugin:entity-reference-selection
. Generates entity reference selection pluginGenerates field formatter plugin
"},{"location":"generators/plugin_field_formatter/#examples","title":"Examples","text":"drush generate plugin:field:formatter
. Generates field formatter pluginGenerates field type plugin
"},{"location":"generators/plugin_field_type/#examples","title":"Examples","text":"drush generate plugin:field:type
. Generates field type pluginGenerates field widget plugin
"},{"location":"generators/plugin_field_widget/#examples","title":"Examples","text":"drush generate plugin:field:widget
. Generates field widget pluginGenerates filter plugin
"},{"location":"generators/plugin_filter/#examples","title":"Examples","text":"drush generate plugin:filter
. Generates filter pluginGenerates plugin manager
"},{"location":"generators/plugin_manager/#examples","title":"Examples","text":"drush generate plugin:manager
. Generates plugin managerGenerates menu-link plugin
"},{"location":"generators/plugin_menu-link/#examples","title":"Examples","text":"drush generate plugin:menu-link
. Generates menu-link pluginGenerates migrate destination plugin
"},{"location":"generators/plugin_migrate_destination/#examples","title":"Examples","text":"drush generate plugin:migrate:destination
. Generates migrate destination pluginGenerates migrate process plugin
"},{"location":"generators/plugin_migrate_process/#examples","title":"Examples","text":"drush generate plugin:migrate:process
. Generates migrate process pluginGenerates migrate source plugin
"},{"location":"generators/plugin_migrate_source/#examples","title":"Examples","text":"drush generate plugin:migrate:source
. Generates migrate source pluginGenerates queue worker plugin
"},{"location":"generators/plugin_queue-worker/#examples","title":"Examples","text":"drush generate plugin:queue-worker
. Generates queue worker pluginGenerates rest resource plugin
"},{"location":"generators/plugin_rest-resource/#examples","title":"Examples","text":"drush generate plugin:rest-resource
. Generates rest resource pluginGenerates views default argument plugin
"},{"location":"generators/plugin_views_argument-default/#examples","title":"Examples","text":"drush generate plugin:views:argument-default
. Generates views default argument pluginGenerates views field plugin
"},{"location":"generators/plugin_views_field/#examples","title":"Examples","text":"drush generate plugin:views:field
. Generates views field pluginGenerates views style plugin
"},{"location":"generators/plugin_views_style/#examples","title":"Examples","text":"drush generate plugin:views:style
. Generates views style pluginGenerates README file
"},{"location":"generators/readme/#examples","title":"Examples","text":"drush generate readme
. Generates README fileGenerates Drupal render element
"},{"location":"generators/render-element/#examples","title":"Examples","text":"drush generate render-element
. Generates Drupal render elementGenerates a service provider
"},{"location":"generators/service-provider/#examples","title":"Examples","text":"drush generate service-provider
. Generates a service providerGenerates an access checker service
"},{"location":"generators/service_access-checker/#examples","title":"Examples","text":"drush generate service:access-checker
. Generates an access checker serviceGenerates a breadcrumb builder service
"},{"location":"generators/service_breadcrumb-builder/#examples","title":"Examples","text":"drush generate service:breadcrumb-builder
. Generates a breadcrumb builder serviceGenerates a cache context service
"},{"location":"generators/service_cache-context/#examples","title":"Examples","text":"drush generate service:cache-context
. Generates a cache context serviceGenerates a custom Drupal service
"},{"location":"generators/service_custom/#examples","title":"Examples","text":"drush generate service:custom
. Generates a custom Drupal serviceGenerates an event subscriber
"},{"location":"generators/service_event-subscriber/#examples","title":"Examples","text":"drush generate service:event-subscriber
. Generates an event subscriberGenerates a logger service
"},{"location":"generators/service_logger/#examples","title":"Examples","text":"drush generate service:logger
. Generates a logger serviceGenerates a middleware
"},{"location":"generators/service_middleware/#examples","title":"Examples","text":"drush generate service:middleware
. Generates a middlewareGenerates a param converter service
"},{"location":"generators/service_param-converter/#examples","title":"Examples","text":"drush generate service:param-converter
. Generates a param converter serviceGenerates a path processor service
"},{"location":"generators/service_path-processor/#examples","title":"Examples","text":"drush generate service:path-processor
. Generates a path processor serviceGenerates a request policy service
"},{"location":"generators/service_request-policy/#examples","title":"Examples","text":"drush generate service:request-policy
. Generates a request policy serviceGenerates a response policy service
"},{"location":"generators/service_response-policy/#examples","title":"Examples","text":"drush generate service:response-policy
. Generates a response policy serviceGenerates a route subscriber
"},{"location":"generators/service_route-subscriber/#examples","title":"Examples","text":"drush generate service:route-subscriber
. Generates a route subscriberGenerates a theme negotiator
"},{"location":"generators/service_theme-negotiator/#examples","title":"Examples","text":"drush generate service:theme-negotiator
. Generates a theme negotiatorGenerates Twig extension service
"},{"location":"generators/service_twig-extension/#examples","title":"Examples","text":"drush generate service:twig-extension
. Generates Twig extension serviceGenerates a uninstall validator service
"},{"location":"generators/service_uninstall-validator/#examples","title":"Examples","text":"drush generate service:uninstall-validator
. Generates a uninstall validator serviceGenerates Drupal SDC theme component
"},{"location":"generators/single-directory-component/#examples","title":"Examples","text":"drush generate single-directory-component
. Generates Drupal SDC theme componentGenerates a browser based test
"},{"location":"generators/test_browser/#examples","title":"Examples","text":"drush generate test:browser
. Generates a browser based testGenerates a kernel based test
"},{"location":"generators/test_kernel/#examples","title":"Examples","text":"drush generate test:kernel
. Generates a kernel based testGenerates a nightwatch test
"},{"location":"generators/test_nightwatch/#examples","title":"Examples","text":"drush generate test:nightwatch
. Generates a nightwatch testGenerates a unit test
"},{"location":"generators/test_unit/#examples","title":"Examples","text":"drush generate test:unit
. Generates a unit testGenerates a test that supports JavaScript
"},{"location":"generators/test_webdriver/#examples","title":"Examples","text":"drush generate test:webdriver
. Generates a test that supports JavaScriptGenerates Drupal theme
"},{"location":"generators/theme/#examples","title":"Examples","text":"drush generate theme
. Generates Drupal themeGenerates Drupal theme-settings.php file
"},{"location":"generators/theme_settings/#examples","title":"Examples","text":"drush generate theme:settings
. Generates Drupal theme-settings.php fileGenerates a breakpoints yml file
"},{"location":"generators/yml_breakpoints/#examples","title":"Examples","text":"drush generate yml:breakpoints
. Generates a breakpoints yml fileGenerates a links.action yml file
"},{"location":"generators/yml_links_action/#examples","title":"Examples","text":"drush generate yml:links:action
. Generates a links.action yml fileGenerates links.contextual yml file
"},{"location":"generators/yml_links_contextual/#examples","title":"Examples","text":"drush generate yml:links:contextual
. Generates links.contextual yml fileGenerates a links.menu yml file
"},{"location":"generators/yml_links_menu/#examples","title":"Examples","text":"drush generate yml:links:menu
. Generates a links.menu yml fileGenerates a links.task yml file
"},{"location":"generators/yml_links_task/#examples","title":"Examples","text":"drush generate yml:links:task
. Generates a links.task yml fileGenerates a migration yml file
"},{"location":"generators/yml_migration/#examples","title":"Examples","text":"drush generate yml:migration
. Generates a migration yml fileGenerates module libraries yml file
"},{"location":"generators/yml_module-libraries/#examples","title":"Examples","text":"drush generate yml:module-libraries
. Generates module libraries yml fileGenerates a permissions yml file
"},{"location":"generators/yml_permissions/#examples","title":"Examples","text":"drush generate yml:permissions
. Generates a permissions yml fileGenerates a routing yml file
"},{"location":"generators/yml_routing/#examples","title":"Examples","text":"drush generate yml:routing
. Generates a routing yml fileGenerates a services yml file
"},{"location":"generators/yml_services/#examples","title":"Examples","text":"drush generate yml:services
. Generates a services yml fileGenerates theme libraries yml file
"},{"location":"generators/yml_theme-libraries/#examples","title":"Examples","text":"drush generate yml:theme-libraries
. Generates theme libraries yml fileDrush is a command line shell and Unix scripting interface for Drupal. Drush core ships with lots of useful commands and generators. Similarly, it runs update.php, executes SQL queries, runs content migrations, and misc utilities like cron or cache rebuild. Drush can be extended by 3rd party commandfiles.
"},{"location":"#resources","title":"Resources","text":"
A: The Drupal Shell.
"},{"location":"#how-do-i-pronounce-drush","title":"How do I pronounce Drush?","text":"Some people pronounce the dru with a long 'u' like Drupal. Fidelity points go to them, but they are in the minority. Most pronounce Drush so that it rhymes with hush, rush, flush, etc. This is the preferred pronunciation.
"},{"location":"#credits","title":"Credits","text":"When preparing to run a command, Drush works by bootstrapping the Drupal environment in very much the same way that is done during a normal page request from the web server, so most Drush commands run in the context of a fully-initialized website.
For efficiency and convenience, some Drush commands can work without first bootstrapping a Drupal site, or by only partially bootstrapping a site. This is faster than a full bootstrap. It is also a matter of convenience, because some commands are useful even when you don't have a working Drupal site.
Commands may specify their bootstrap level with via an attribute or an annotation. Commands supplied by Drupal modules are always full
.
use Drush\\Attributes as CLI;\n\n#[CLI\\Bootstrap(level: DrupalBootLevels::NONE)]\npublic function fetch($search = null, $options = ['image-viewer' => 'open', 'google-custom-search-api-key' => 'AIza']) {\n $this->doFetch($search, $options);\n}\n
/**\n * @bootstrap none\n*/\npublic function fetch($search = null, $options = ['image-viewer' => 'open', 'google-custom-search-api-key' => 'AIza']) {\n $this->doFetch($search, $options);\n}\n
Prior to bootstrapping, Drush goes through the preflight process, where the following things occur:
Preflight
bootstrap @full
. Bootstrapping is done from a Symfony Console command hook. The different bootstrap levels are described below.
"},{"location":"bootstrap/#none","title":"none","text":"Only run Drush preflight, without considering Drupal at all. Any code that operates on the Drush installation, and not specifically any Drupal directory, should bootstrap to this phase. This Attribute and value may also be used on a command class when it wants to load before Drupal bootstrap is started. Commands that ship inside Drupal modules always bootstrap to full, regardless of none value.
"},{"location":"bootstrap/#root","title":"root","text":"Set up and test for a valid Drupal root, either through the --root options, or evaluated based on the current working directory. Any code that interacts with an entire Drupal installation, and not a specific site on the Drupal installation should use this bootstrap phase.
"},{"location":"bootstrap/#site","title":"site","text":"Set up a Drupal site directory and the correct environment variables to allow Drupal to find the configuration file. If no site is specified with the --uri options, Drush will assume the site is 'default', which mimics Drupal's behaviour. Note that it is necessary to specify a full URI, e.g. --uri=http://example.com, in order for certain Drush commands and Drupal modules to behave correctly. See the Drush configuration for more information. Any code that needs to modify or interact with a specific Drupal site's settings.php file should bootstrap to this phase.
"},{"location":"bootstrap/#configuration","title":"configuration","text":"Load the settings from the Drupal sites directory. This phase is analogous to the DRUPAL_BOOTSTRAP_CONFIGURATION bootstrap phase in Drupal itself, and this is also the first step where Drupal specific code is included. This phase is commonly used for code that interacts with the Drupal install API, as both install.php and update.php start at this phase.
"},{"location":"bootstrap/#database","title":"database","text":"Connect to the Drupal database using the database credentials loaded during the previous bootstrap phase. This phase is analogous to the DRUPAL_BOOTSTRAP_DATABASE bootstrap phase in Drupal. Any code that needs to interact with the Drupal database API needs to be bootstrapped to at least this phase.
"},{"location":"bootstrap/#full","title":"full","text":"Fully initialize Drupal. This is analogous to the DRUPAL_BOOTSTRAP_FULL bootstrap phase in Drupal. Any code that interacts with the general Drupal API should be bootstrapped to this phase.
"},{"location":"bootstrap/#max","title":"max","text":"This is not an actual bootstrap phase. Commands that use the \"max\" bootstrap level will cause Drush to bootstrap as far as possible, and then run the command regardless of the bootstrap phase that was reached. This is useful for Drush commands that work without a bootstrapped site, but that provide additional information or capabilities in the presence of a bootstrapped site. For example, drush status
will show progressively more information the farther the site bootstraps.
Tip
<module-name>/src/Drush/<Commands|Generators>
directory. The Drush
subdirectory is a new requirement.Creating a new Drush command is easy. Follow the steps below.
drush generate drush:command-file
.drush generate module
to create a new module.The following are both valid ways to declare a command:
PHP8 AttributesAnnotationsuse Drush\\Attributes as CLI;\n\n/**\n * Retrieve and display xkcd cartoons (attribute variant).\n */\n#[CLI\\Command(name: 'xkcd:fetch-attributes', aliases: ['xkcd-attributes'])]\n#[CLI\\Argument(name: 'search', description: 'Optional argument to retrieve the cartoons matching an index, keyword, or \"random\".')]\n#[CLI\\Option(name: 'image-viewer', description: 'Command to use to view images (e.g. xv, firefox).', suggestedValues: ['open', 'xv', 'firefox'])]\n#[CLI\\Option(name: 'google-custom-search-api-key', description: 'Google Custom Search API Key')]\n#[CLI\\Usage(name: 'drush xkcd', description: 'Retrieve and display the latest cartoon')]\n#[CLI\\Usage(name: 'drush xkcd sandwich', description: 'Retrieve and display cartoons about sandwiches.')]\npublic function fetch($search = null, $options = ['image-viewer' => 'open', 'google-custom-search-api-key' => 'AIza']) {\n $this->doFetch($search, $options);\n}\n
/**\n * @command xkcd:fetch\n * @param $search Optional argument to retrieve the cartoons matching an index number, keyword, or \"random\".\n * @option image-viewer Command to use to view images (e.g. xv, firefox).\n * @option google-custom-search-api-key Google Custom Search API Key.\n * @usage drush xkcd\n * Retrieve and display the latest cartoon.\n * @usage drush xkcd sandwich\n * Retrieve and display cartoons about sandwiches.\n * @aliases xkcd\n*/\npublic function fetch($search = null, $options = ['image-viewer' => 'open', 'google-custom-search-api-key' => 'AIza']) {\n $this->doFetch($search, $options);\n}\n
Drush command info (annotations/attributes) can be altered from other modules. This is done by creating and registering command info alterers. Alterers are classes that are able to intercept and manipulate an existing command annotation.
In the module that wants to alter a command info, add a class that:
Drupal\\<module-name>\\Drush\\CommandInfoAlterers
and the class file should be located under the src/Drush/CommandInfoAlterers
directory.Foo
can be whatever string you want. The file must end in CommandInfoAlterer.php
.\\Consolidation\\AnnotatedCommand\\CommandInfoAltererInterface
.alterCommandInfo()
method.For an example, see WootCommandInfoAlterer provided by the testing 'woot' module.
"},{"location":"commands/#symfony-console-commands","title":"Symfony Console Commands","text":"Drush lists and runs Symfony Console commands, in addition to more typical annotated commands. See this test and this commandfile.
"},{"location":"commands/#auto-discovered-commands-psr4","title":"Auto-discovered commands (PSR4)","text":"Such commands are auto-discovered by their class PSR4 namespace and class/file name suffix. Drush will auto-discover commands if:
Drush\\Commands
. For instance, if a Drush command provider third party library maps this PSR4 autoload entry: \"autoload\": {\n\"psr-4\": {\n\"My\\\\Custom\\\\Library\\\\\": \"src\"\n}\n}\n
then the Drush global commands class namespace should be My\\Custom\\Library\\Drush\\Commands
and the class file should be located under the src/Drush/Commands
directory.*DrushCommands
, e.g. FooDrushCommands
.Auto-discovered commandfiles should declare their Drush version compatibility via a conflict
directive. For example, a Composer-managed site-wide command that works with both Drush 11 and Drush 12 might contain something similar to the following in its composer.json file:
\"conflict\": {\n\"drush/drush\": \"<11.0\",\n}\n
Using require
in place of conflict
is not recommended. Symlinked packages
While it is good practice to make your custom commands into a Composer package, please beware that symlinked packages (by using the composer repository type Path) will not be discovered by Drush. When in development, it is recommended to specify your package's path in your drush.yml
to have quick access to your commands.
Commandfiles that are installed in a Drupal site and are not bundled inside a Drupal module are called site-wide commandfiles. Site-wide commands may either be added directly to the Drupal site's repository (e.g. for site-specific policy files), or via composer require
. See the examples/Commands folder for examples. In general, it's preferable to use modules to carry your Drush commands.
Here are some examples of valid commandfile names and namespaces:
Note: Make sure you do not include src
in the path to your command. Your command may not be discovered and have additional problems.
If a commandfile is added via a Composer package, then it may declare any dependencies that it may need in its composer.json file. Site-wide commandfiles that are committed directly to a site's repository only have access to the dependencies already available in the site.
A site-wide commandfile should have tests that run with each (major) version of Drush that is supported. You may model your test suite after the example drush extension project.
"},{"location":"commands/#global-commands-discovered-by-configuration","title":"Global commands discovered by configuration","text":"Deprecation
Configuration discovery has been deprecated and will be removed in a future version of Drush. It is recommended that you avoid global Drush commands, and favor site-wide or PSR4 discovered commandfiles instead. If you really need commands that are not part of any Drupal site, consider making a stand-alone script or custom .phar instead. See ahoy, Robo and g1a/starter as potential starting points.
Global commandfiles discoverable by configuration are not supported by default; in order to enable them, you must configure your drush.yml
configuration file to add an include
search location.
For example:
drush:\npaths:\ninclude:\n- '${env.home}/.drush/commands'\n
With this configuration in place, global commands may be placed as described in the Site-Wide Drush Commands section above. Global commandfiles may not declare any dependencies of their own; they may only use those dependencies already available via the autoloader. Tip
Example
can be whatever string you want.Commands.php
Commands
must be one of:Drush provides commands to export, pull, and import Drupal configuration files.
"},{"location":"config-exporting/#simple-value-changes","title":"Simple - value changes","text":"It is not necessary to alter configuration values to make simple value changes to configuration variables, as this may be done by the configuration override system.
The configuration override system allows you to change configuration values for a given instance of a site (e.g. the development server) by setting configuration variables in the site's settings.php file. For example, to change the name of a local development site:
$config['system.site']['name'] = 'Local Install of Awesome Widgets, Inc.';\n
Note that the configuration override system is a Drupal feature, not a Drush feature. It should be the preferred method for changing configuration values on a per-environment basis; however, it does not work for some things, such as enabling and disabling modules."},{"location":"config-exporting/#advanced-variation-by-environment","title":"Advanced - variation by environment","text":"Drupal cron tasks are often set up to be run via a wget/curl call to cron.php; this same task can also be accomplished via the cron command, which circumvents the need to provide a web server interface to cron.
"},{"location":"cron/#quick-start","title":"Quick start","text":"If you just want to get started quickly, here is a crontab entry that will run cron once every hour at ten minutes after the hour:
10 * * * * cd [DOCROOT] && /usr/bin/env PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin COLUMNS=72 ../vendor/bin/drush --uri=your.drupalsite.org --quiet maint:status && /vendor/bin/drush --uri=your.drupalsite.org --quiet cron\n
You should set up crontab to run your cron tasks as the same user that runs the web server; for example, if you run your web server as the user www-data:
sudo crontab -u www-data -e\n
You might need to edit the crontab entry shown above slightly for your particular setup; for example, if you have installed Drush to some directory other than /usr/local/drush, then you will need to adjust the path to drush appropriately. We'll break down the meaning of each section of the crontab entry in the documentation that continues below.
"},{"location":"cron/#setting-the-schedule","title":"Setting the schedule","text":"See man 5 crontab
for information on how to format the information in a crontab entry. In the example above, the schedule for the crontab is set by the string 10 * * * *
. These fields are the minute, hour, day of month, month and day of week; *
means essentially 'all values', so 10 * * * *
will run any time the minute == 10 (once every hour).
We use /usr/bin/env to run Drush so that we can set up some necessary environment variables that Drush needs to execute. By default, cron will run each command with an empty PATH, which would not work well with Drush. To find out what your PATH needs to be, just type:
echo $PATH\n
Take the value that is output and place it into your crontab entry in the place of the one shown above. You can remove any entry that is known to not be of interest to Drush (e.g. /usr/games), or is only useful in a graphic environment (e.g. /usr/X11/bin).
"},{"location":"cron/#setting-columns","title":"Setting COLUMNS","text":"When running Drush in a terminal, the number of columns will be automatically determined by Drush by way of the tput command, which queries the active terminal to determine what the width of the screen is. When running Drush from cron, there will not be any terminal set, and the call to tput will produce an error message. Spurious error messages are undesirable, as cron is often configured to send email whenever any output is produced, so it is important to make an effort to insure that successful runs of cron complete with no output.
In some cases, Drush is smart enough to recognize that there is no terminal -- if the terminal value is empty or \"dumb\", for example. However, there are some \"non-terminal\" values that Drush does not recognize, such as \"unknown.\" If you manually set COLUMNS
, then Drush will respect your setting and will not attempt to call tput.
By default, Drush will print a success message when the run of cron is completed. The --quiet flag will suppress these and other progress messages, again avoiding an unnecessary email message.
"},{"location":"cron/#specifying-the-drupal-site-to-run","title":"Specifying the Drupal site to run","text":"There are many ways to tell Drush which Drupal site to select for the active command, and any may be used here. The example uses cd [DOCROOT]
, but you could also use the --root and --uri flags.
The call to maint:status checks to see if the site is in maintenance mode. If yes, cron will not run and the command returns a failure. It is not safe to run cron while the site is in maintenance. See https://drupal.slack.com/archives/C45SW3FLM/p1675287662331809.
"},{"location":"dependency-injection/","title":"Dependency Injection","text":"Drush command files obtain references to the resources they need through a technique called dependency injection. When using this programing paradigm, a class by convention will never use the new
operator to instantiate dependencies. Instead, it will store the other objects it needs in class variables, and provide a way for other code to assign an object to that variable.
Tip
Drush 11 and prior required dependency injection via a drush.services.yml file. This approach is deprecated in Drush 12+.
"},{"location":"dependency-injection/#autowire","title":"Autowire","text":"12.5+
Command files may inject Drush and Drupal services by adding the AutowireTrait to the class (example: MaintCommands). This enables your Constructor parameter type hints determine the the injected service. When a type hint is insufficient, an #[Autowire] Attribute on the constructor property (with service: named argument) directs AutoWireTrait to the right service.
If your command is not found by Drush, add the -vvv
option for debug info about any service instantiation errors. If Autowire is still insufficient, a commandfile may implement its own create()
method (see below).
11.6+
Command files not using Autowire may inject services by adding a create() method to the commandfile. The passed in Container is a League container with a delegate to the Drupal container. Note that the type hint should be to Psr\\Container\\ContanierInterface
not Symfony\\Component\\DependencyInjection\\ContainerInterface
. A create() method and constructor will look something like this:
class WootStaticFactoryCommands extends DrushCommands\n{\n protected $configFactory;\n\n protected function __construct($configFactory)\n {\n $this->configFactory = $configFactory;\n }\n\n public static function create(Psr\\Container\\ContainerInterface $container): self\n {\n return new static($container->get('config.factory'));\n }\n
See the Drupal Documentation for details on how to inject Drupal services into your command file. This approach mimics Drupal's blocks, forms, and controllers."},{"location":"dependency-injection/#createearly-method","title":"createEarly() method","text":"12.0+
The createEarly()
method was deprecated in Drush 12.5. Instead put a #[CLI\\Bootstrap(DrupalBootLevels::NONE)]
Attribute on the command class and inject dependencies via the usual __construct
with AutowireTrait.
Note also that Drush commands packaged with Drupal modules are not discovered until after Drupal bootstraps, and therefore cannot use createEarly()
. This mechanism is only usable by PSR-4 discovered commands packaged with Composer projects that are not Drupal modules.
A command class may implement the following interfaces. When doing so, implement the corresponding trait to satisfy the interface.
10.3+
The deploy command standardizes how Drupal deployments work. The intent is your deployment script updates the codebase for the target site and then this command performs the following:
drush updatedb --no-cache-clear\ndrush cache:rebuild\ndrush config:import\ndrush cache:rebuild\ndrush deploy:hook\n
"},{"location":"deploycommand/#authoring-update-functions","title":"Authoring update functions","text":"Below are the 3 types of update functions run by this command, in order. Choose the most appropriate for your need.
Function Drupal API Purpose HOOK_update_n() Not allowed Low level changes. HOOK_post_update_NAME() Allowed Runs before config is imported. HOOK_deploy_NAME() Allowed Runs after config is imported."},{"location":"deploycommand/#configuration","title":"Configuration","text":"If you need to customize this command, you should use Drush configuration for the subcommands listed above (e.g. updatedb, config:import, etc.).
"},{"location":"generators/","title":"Overview","text":"Tip
Drush 11 and prior required generators to define a drush.services.yml file. This is no longer used with Drush 12+ generators. See docs for injecting dependencies..
Generators jump start your coding by building all the boring boilerplate code for you. After running the generate command, you have a guide for where to insert your custom logic.
Drush's generators reuse classes provided by the excellent Drupal Code Generator project. See its Commands directory for inspiration.
"},{"location":"generators/#writing-custom-generators","title":"Writing Custom Generators","text":"Drupal modules may supply their own Generators, just like they can supply Commands.
See Woot module, which Drush uses for testing. Specifically,
Generators that don't ship inside Drupal modules are called global generators. For example see CustomDrushGenerator. In general, it is better to use modules to carry your generators. If you still prefer using a global generator, please note:
Drush\\Generators
. For instance, if a Drush generator provider third party library maps this PSR4 autoload entry: \"autoload\": {\n\"psr-4\": {\n\"My\\\\Custom\\\\Library\\\\\": \"src\"\n}\n}\n
then the Drush global generator class namespace should be My\\Custom\\Library\\Drush\\Generators
and the class file should be located under the src/Drush/Generators
directory.Foo
can be whatever string you want. The file must end in Generator.php
.Sitewide generators (as opposed to auto-discovered PSR4) have a namespace that starts with \\Drush\\Generators
, the directory above Generators must be one of: 1. A Folder listed in the --include option. include may be provided via config or via CLI. 1. ../drush
, /drush
or /sites/all/drush
. These paths are relative to Drupal root.
All commandfiles may implement methods that are called by Drush at various times in the request cycle. To implement one, add a #[CLI\\Hook(type: HookManager::ARGUMENT_VALIDATOR, target: 'pm:install')]
(for example) to the top of your method. The class constants for hooks are located in HookManager.
Drush commands can define custom events that other command files can hook. You can find examples in CacheCommands and SanitizeCommands
First, the command must implement CustomEventAwareInterface and use CustomEventAwareTrait, as described in the dependency injection documentation.
Then, the command may ask the provided hook manager to return a list of handlers with a certain attribute. In the example below, the my-event
label is used:
/**\n * This command uses a custom event 'my-event' to collect data. Note that\n * the event handlers will not be found unless the hook manager is\n * injected into this command handler object via `setHookManager()`\n * (defined in CustomEventAwareTrait).\n */\n #[CLI\\Command(name: 'example:command')] \n public function exampleCommand()\n {\n $myEventHandlers = $this->getCustomEventHandlers('my-event');\n $result = [];\n foreach ($myEventHandlers as $handler) {\n $result[] = $handler();\n }\n sort($result);\n return implode(',', $result);\n }\n
Other commandfiles may provide implementations via a PHP8 Attribute or an Annotation.
PHP8 AttributesAnnotations/**\n * #[CLI\\Hook(type: HookManager::ON_EVENT, target: 'my-event')]\n */\npublic function hookOne()\n{\n return 'one';\n}\n
/**\n * @hook on-event my-event\n */\npublic function hookOne()\n{\n return 'one';\n}\n
"},{"location":"install/","title":"Install","text":"Tip
Drush only supports one install method. It requires that your Drupal site be built with Composer and Drush be listed as a dependency.
See the Drush 8 or Drush 9 docs for installing prior versions of Drush.
composer require drush/drush
to add it.vendor/bin/drush
. To simplify things, add ./vendor/bin
to your $PATH
, allowing you to call Drush via drush
from the project root. If you have only one Drupal codebase on your system, you may put /path/to/vendor/bin
in your $PATH
; now you can call Drush from everywhere, without having to change to project root.drush completion --help
for more details. Note
PATH=/path/to/php:$PATH
drush status ...`$this->io()
.$this->io()->choice()
and $this->io()->confirm()
.10.4+
The Migrate API delivers services for migrating data from a source system to Drupal. This API is provided by the core migrate
module. In order to migrate data to Drupal, you'll need to create migrations for each type of destination data.
These commands are an alternative to https://www.drupal.org/project/migrate_tools. Don't use that module if you use these commands.
"},{"location":"migrate/#defining-migrations","title":"Defining migrations","text":"Learn how to create migrations from the Drupal official documentation:
Drush provides a set of commands that allows to run migration operations such as importing, checking the current status of migrations, rolling-back migrations, stopping an ongoing migration, etc. Such commands are available only when the migrate
module is enabled. In order the get a full list of migrate commands, type:
drush --filter=migrate\n
To get help on each command run drush with the command name as parameter and the --help
option. For example next command will show details about the migrate:import Drush command:
drush migrate:import --help\n
"},{"location":"output-formats-filters/","title":"Output Formats, Fields and Filters","text":"Drush utilizes a powerful formatting and filtering system that provides the user with a lot of control over how output from various commands is rendered.
The --format
option may be used to select the data format used to print the output of a command. Most commands that produce informative output about some object or system can transform their data into different formats. For example, the version command may be printed in a human-readable table (the default), or in a json array:
$ drush version\n Drush version : 10.3.1\n$ drush version --format=json\n{\n\"drush-version\": \"10.3.1\"\n}\n
The available output formats are shown in the help
for each command: $ drush help version\nShow drush version.\n\nOptions:\n --format=<json> Select output format. Available: json, string, var_export, yaml. Default is key-value.\n
"},{"location":"output-formats-filters/#output-fields","title":"Output Fields","text":"If you wish to limit the number of columns produced by a command, use the --fields
option. List the field names in the order they should be displayed:
$ drush views:list --fields=machine-name,status\n+-------------------+----------+\n| Machine name | Status |\n+-------------------+----------+\n| block_content | Enabled |\n| comment | Enabled |\n| comments_recent | Enabled |\n| content | Enabled |\n| content_recent | Enabled |\n| files | Enabled |\n| frontpage | Enabled |\n| taxonomy_term | Enabled |\n| user_admin_people | Enabled |\n| watchdog | Enabled |\n| who_s_new | Enabled |\n| who_s_online | Enabled |\n| archive | Disabled |\n| glossary | Disabled |\n+-------------------+----------+\n
The available field names are shown in the help
text: $ drush help views:list\nGet a list of all views in the system.\n\nOptions:\n --fields=FIELDS Available fields: Machine name (machine-name), Name (label), Description (description), Status (status), Tag (tag) [default: \"machine-name,label,description,status\"]
Fields may be named either using their human-readable name, or via their machine name. Note also that some commands do not display all of their available data columns by default. To show all available fields, use --fields=*
There is also a singular form --field
available. If this form is used, it will also force the output format to string
.
$ drush views:list --field=machine-name \nblock_content\ncomment\ncomments_recent\ncontent\ncontent_recent\nfiles\nfrontpage\ntaxonomy_term\nuser_admin_people\nwatchdog\nwho_s_new\nwho_s_online\narchive\nglossary\n
"},{"location":"output-formats-filters/#output-filters","title":"Output Filters","text":"A number of Drush commands that output tabular data support a --filter
option that allows rows from the output to be selected with simple logic expressions.
In its simplest form, the --filter
option takes a string that indicates the value to filter by in the command's default filter field. For example, the role:list command specifies perms
as its default filter; the output of the role:list
command may be limited to only those roles that have a specified permission:
$ drush role:list --filter='post comments'\nauthenticated:\n label: 'Authenticated user'\nperms:\n - 'access comments'\n- 'access content'\n- 'access shortcuts'\n- 'access site-wide contact form'\n- 'access user contact forms'\n- 'post comments'\n- 'search content'\n- 'skip comment approval'\n- 'use text format basic_html'\n
Note that not all commands have a default filter field. Other fields in the output may be searched by using a simple expression in the --filter
term. For example, to list only the enabled extensions with the pm:list
command, you could run:
$ drush pm:list --filter='status=enabled'\n
To search for fields that contain a string using the operator *=
, or match a regular expression with the ~=
operator. For example, to find all views whose machine name contains the word content: drush views:list --filter='machine-name*=content'\n
To use a regular expression to find any core requirement notice whose title contains either php or gd drush core:requirements --filter='title~=#(php|gd)#i'\n
Finally, filter expressions may also use logical-and (&&
) or logical-or (||
) operations to separate multiple terms. Parenthesis are not supported. For example, to search both the title
and severity
fields in the core:requirements
command: drush core:requirements --filter='title~=#(php|gd)#i&&severity=warning'\n
The =
and *=
operators always use case-insensitive comparisons. The ~=
operator is case-sensitive, unless the i
PCRE modifier is used, as shown in the previous example.
Using the --filter
feature is similar to using grep
. The main difference is that the filter feature does a semantic search, which is to say that it explicitly compares against the data in specific fields. In comparison, the grep
command does a line-based search.
Show only results where the severity is warning:
drush core:requirements --filter='severity=warning'
Show only lines that contain the string warning (either in the severity field, or somewhere else on the line):
drush core:requirements | grep -i warning
The table below compares and contrasts the two ways of searching.
Feature --filter grep Regular expressions Yes, with~=
Yes Word-wrapped field data Searched correctly Might cause false negative Search just one field Yes Might get false positives Search multiple fields Yes, with ||
/&&
Yes (line-based searching) Searching hides header No Yes (unless it matches)"},{"location":"repl/","title":"REPL (a custom shell for Drupal)","text":"The php:cli command is interactive PHP REPL with your bootstrapped site (remote or local). It\u2019s a Drupal code playground. You can do quick code experimentation, grab some data, or run Drush commands. This can also help with debugging certain issues. See this blog post for an introduction. Run help
for a list of commands.
Any global PsySH configuration is loaded by Drush. If you prefer a config file that is specific to the project (and can be checked in with other source code), set the environment variable PSYSH_CONFIG=</path/to/config-file>
. This file then takes precedence over any global file.
Entity classes are available without their namespace. For example, Node::load() works instead of Drupal\\Node\\entity\\Noad::load().
"},{"location":"site-alias-manager/","title":"Site Alias Manager","text":"The Site Alias Manager (SAM) service is used to retrieve information about one or all of the site aliases for the current installation.
$this->siteAliasManager->getself()
.In its most basic form, the Drush site alias feature provides a way for teams to share short names that refer to the live and staging sites (usually remote) for a given Drupal site.
Add an alias file called $PROJECT/drush/sites/self.site.yml
, where $PROJECT
is the project root (location of composer.json file). The site alias file should be named self.site.yml
because this name is special, and is used to define the different environments (usually remote) of the current Drupal site.
The contents of the alias file should look something like the example below:
# File: self.site.yml\nlive:\n host: server.domain.com\n user: www-admin\n root: /other/path/to/live/drupal\n uri: http://example.com\nstage:\n host: server.domain.com\n user: www-admin\n root: /other/path/to/stage/drupal\n uri: http://stage.example.com\n
The top-level element names (live
and stage
in the example above) are used to identify the different environments available for this site. These may be used on the command line to select a different target environment to operate on by prepending an @
character, e.g. @live
or @stage
.
Following these steps, a cache:rebuild on the live environment would be:
$ drush @live cache:rebuild\n
All of the available aliases for a site's environments may be listed via:
$ drush site:alias @self\n
The elements of a site alias are:
host
option must be omitted for local sites, as this option controls various operations, such as whether or not rsync parameters are for local or remote machines, and so on.user
item and specify a user in the ~/.ssh/config
file.Drush typically uses ssh to run commands on remote systems; all team members should install ssh keys on the target servers (e.g. via ssh-add
).
It is also possible to create site alias files that reference other sites on the same local system. Site alias files for other local sites are usually stored in the directory ~/.drush/sites
; however, Drush does not search this location for alias files by default. To use this location, you must add the path in your Drush configuration file. For example, to re-add both of the default user alias path from Drush 8, put the following in your ~/.drush/drush.yml
configuration file:
drush:\n paths:\n alias-path:\n - '${env.HOME}/.drush/sites'\n - /etc/drush/sites\n
A canonical alias named example that points to a local Drupal site named at http://example.com like this:
# File: example.site.yml\ndev:\n root: /path/to/drupal\n uri: http://example.com\n
Note that the first part of the filename (in this case example defines the name of the site alias, and the top-level key dev defines the name of the environment.
With these definitions in place, it is possible to run commands targeting the dev environment of the target site via:
$ drush @example.dev status\n
This command is equivalent to the longer form: $ drush --root=/path/to/drupal --uri=http://example.com status\n
See Additional Site Alias Options for more information."},{"location":"site-aliases/#altering-aliases","title":"Altering aliases:","text":"See examples/Commands/SiteAliasAlterCommands.php) for an example.
"},{"location":"site-aliases/#site-specifications","title":"Site specifications:","text":"When a site alias name is provided on the command line, a site specification may be used instead. A site specification is a site alias that is not saved on the filesystem but instead is provided directly e.g. drush user@server/path/to/drupal#uri core:status
. See example site specifications.
Site aliases may reference environment variables, just like any Drush config file. For example, ${env.PROJECT_SSH_USER}
will be replaced by the value of the PROJECT_SSH_USER
environment value.
SSH site aliases may set environment variables via the env-vars
key. See below.
Aliases are commonly used to define short names for local or remote Drupal installations; however, an alias is really nothing more than a collection of options.
docker-compose
exec rather than ssh
.kubectl
exec rather than ssh
.ssh
command itself, e.g. -p 100
ssh --t
option) based on whether the local Drush command is running interactively or not. To force Drush to always or never create a tty, set the ssh.tty
option to true or false, respectively.--no-dump
will be selected whenever the @stage
alias is used in any of the following ways:drush @stage sql-sync @self @live
drush sql-sync @stage @live
drush sql-sync @live @stage
Complex example:
# File: remote.site.yml\nlive:\n host: server.domain.com\n user: www-admin\n root: /other/path/to/drupal\n uri: http://example.com\n ssh:\n options: '-p 100'\n paths:\n drush-script: '/path/to/drush'\n env-vars:\n PATH: /bin:/usr/bin:/home/www-admin/.composer/vendor/bin\n DRUPAL_ENV: live\n command:\n site:\n install:\n options:\n admin-password: 'secret-secret'\n
"},{"location":"site-aliases/#site-alias-files-for-service-providers","title":"Site Alias Files for Service Providers","text":"There are a number of service providers that manage Drupal sites as a service. Drush allows service providers to create collections of site alias files to reference all of the sites available to a single user. In order to do this, a new location must be defined in your Drush configuration file:
drush:\n paths:\n alias-path:\n - '${env.HOME}/.drush/sites/provider-name'\n
Site aliases stored in this directory may then be referenced by its full alias name, including its location, e.g.:
$ drush @provider-name.example.dev\n
Such alias files may still be referenced by their shorter name, e.g. @example.dev
. Note that it is necessary to individually list every location where site alias files may be stored; Drush never does recursive (deep) directory searches for alias files. The site:alias
command may also be used to list all of the sites and environments in a given location, e.g.:
$ drush site:alias @provider-name\n
Add the option --format=list
to show only the names of each site and environment without also showing the values in each alias record."},{"location":"site-aliases/#wildcard-aliases-for-service-providers","title":"Wildcard Aliases for Service Providers","text":"Some service providers that manage Drupal sites allow customers to create multiple \"environments\" for a site. It is common for these providers to also have a feature to automatically create Drush aliases for all of a user's sites. Rather than write one record for every environment in that site, it is also possible to write a single wildcard alias that represents all possible environments. This is possible if the contents of each environment alias are identical save for the name of the environment in one or more values. The variable ${env-name}
will be substituted with the environment name wherever it appears.
Example wildcard record:
# File: remote-example.site.yml\n'*':\n host: ${env-name}.server.domain.com\n user: www-admin\n root: /path/to/${env-name}\n uri: http://${env-name}.remote-example.com\n
With a wildcard record, any environment name may be used, and will always match. This is not desirable in instances where the specified environment does not exist (e.g. if the user made a typo). An alias alter hook in a policy file may be used to catch these mistakes and report an error. See SiteAliasAlterCommands for an example on how to do this.
"},{"location":"site-aliases/#docker-compose","title":"Docker Compose","text":"The example below shows drush calling into a Docker hosted site. See the https://github.com/consolidation/site-alias and https://github.com/consolidation/site-process projects for more developer information about transports.
An example appears below. Edit to suit:
# File: mysite.site.yml\nlocal:\nThis environment is an example of the DockerCompose transport.\n docker:\n service: drupal\n exec:\n options: --user USER\nstage:\n uri: http://stage.example.com\n root: /path/to/remote/drupal/root\n host: mystagingserver.myisp.com\n user: publisher\n os: Linux\n paths:\n - files: sites/mydrupalsite.com/files\n - custom: /my/custom/path\n command:\n sql:\n sync:\n options:\n no-dump: true\ndev:\n root: /path/to/docroot\n uri: https://dev.example.com\n
"},{"location":"site-aliases/#kubernetes","title":"Kubernetes","text":"Drush provides transport for running drush commands on your Kubernetes cluster via kubectl. See an example and options below.
prod: \n kubectl:\n namespace: 'my-drupal-namespace'\n resource: 'pods/my-drupal-pod' \n container: 'drupal'\n
"},{"location":"site-aliases/#key-options","title":"Key options","text":"Note that most options typically passed to rsync via drush rsync
are \"passthrough options\", which is to say they appear after the --
separator on the command line. Passthrough options are actually arguments, and it is not possible to set default arguments in an alias record. The drush rsync
command does support two options, --mode
and --exclude-paths
, which are interpreted directly by Drush. Default values for these options may be specified in an alias record, as shown below.
dev:\n root: /path/to/docroot\n uri: https://dev.example.com\n command:\n core:\n rsync:\n options:\n mode: rlptz\n exclude-paths: 'css:imagecache:ctools:js:tmp:php:styles'\n
"},{"location":"usage/","title":"Usage","text":"Drush can be run in your shell by typing drush
from within your project root directory or anywhere within Drupal.
$ drush [options] <command> [argument1] [argument2]\n
Use the help command to get a list of available options and commands:
$ drush help pm:list\n
For even more documentation, use the topic command:
$ drush topic\n
"},{"location":"usage/#using-the-uri-option-and-root-options","title":"Using the --uri option and --root options.","text":"For multi-site installations, use a site alias or the --uri option to target a particular site.
$ drush --uri=http://example.com pm:install\n
If you are outside the Composer project and not using a site alias, you need to specify --root and --uri for Drush to locate and bootstrap the right Drupal site.
"},{"location":"usage/#site-aliases","title":"Site Aliases","text":"Drush lets you run commands on a remote server. Once defined, aliases can be referenced with the @ nomenclature, i.e.
# Run pending updates on staging site.\n$ drush @staging updatedb\n# Synchronize staging files to production\n$ drush rsync @staging:%files/ @live:%files\n# Synchronize database from production to local, excluding the cache table\n$ drush sql:sync --structure-tables-key=custom @live @self\n
See Site aliases for more information.
"},{"location":"using-drush-configuration/","title":"Drush Configuration","text":"Drush configuration is useful to cut down on typing out lengthy and repetitive command line options, and to avoid mistakes.
"},{"location":"using-drush-configuration/#directories-and-discovery","title":"Directories and Discovery","text":"drush.yml files are discovered as below, in order of precedence:
sites/{example.com}/drush.yml
).sites/all/drush
, WEBROOT/drush
, or PROJECTROOT/drush
.--config
option.~/.drush/drush.yml
)./etc/drush/drush.yml
or C:\\ProgramData\\Drush\\drush.yml
).If a configuration file is found in any of the above locations, it will be loaded and merged with other configuration files in the search list. Run drush status --fields=drush-conf
to see all discovered config files.
Your Drush config file may reference environment variables using a syntax like ${env.HOME}
. For example see the drush.paths
examples below.
An alternative way to populate Drush configuration is to define environment variables that correspond to config keys. For example, to populate the options.uri
config item, create an environment variable DRUSH_OPTIONS_URI=http://example.com
. As you can see, variable names should be uppercased, prefixed with DRUSH_
, and periods replaced with underscores.
drush:\n paths:\n config:\n # Load any personal config files. Is silently skipped if not found. Filename must be drush.yml\n - ${env.HOME}/.drush/config/drush.yml\n
drush status --fields=drush-conf --format=yaml
These locations are always merged with include paths defined on the command line or in other configuration files. On the command line, paths may be separated by a colon :
on Unix-based systems or a semi-colon ;
on Windows, or multiple --include
options may be provided. Drush 8 and earlier did a deep search in ~/.drush
and /usr/share/drush/commands
when loading command files, so we mimic that here as an example.
drush:\n include:\n - '${env.HOME}/.drush/commands'\n - /usr/share/drush/commands\n
drush list
These locations are always merged with alias paths defined on the command line or in other configuration files. On the command line, paths may be separated by a colon :
on Unix-based systems or a semi-colon ;
on Windows, or multiple --alias-path
options may be provided. Note that Drush 8 and earlier did a deep search in ~/.drush
and /etc/drush
when loading alias files.
drush:\n paths:\n alias-path:\n - '${env.HOME}/.drush/sites'\n - /etc/drush/sites\n
- View all loaded site aliases: drush site:alias
"},{"location":"using-drush-configuration/#backup-directory","title":"Backup directory","text":"Specify a folder where Drush should store backup files, including temporary sql dump files created during sql:sync. If unspecified, defaults to $HOME/drush-backups
.
drush:\n paths:\n backup-dir: /tmp/drush-backups\n
"},{"location":"using-drush-configuration/#global-options","title":"Global options","text":"options:\n # Specify the base_url that should be used when generating links.\n uri: 'http://example.com/subdir'\n\n # Specify your Drupal core base directory (useful if you use symlinks).\n root: '/home/USER/workspace/drupal'\n\n # Enable verbose mode.\n verbose: true\n
"},{"location":"using-drush-configuration/#command-specific-options","title":"Command-specific options","text":"command:\n sql:\n cli:\n options:\n # Enable auto-complete in MySQL.\n extra: \"--auto-rehash\"\n dump:\n options:\n # Omit cache and similar tables (including during a sql:sync).\n structure-tables-key: common\n php:\n script:\n options:\n # Additional folders to search for scripts.\n script-path: 'sites/all/scripts:profiles/myprofile/scripts'\n core:\n rsync:\n options:\n # Ensure all rsync commands use verbose output.\n verbose: true\n\n site:\n install:\n options:\n # Set a predetermined username and password when using site:install.\n account-name: 'alice'\n account-pass: 'secret'\n
"},{"location":"using-drush-configuration/#non-options","title":"Non-options","text":"sql:\n # An explicit list of tables which should be included in sql-dump and sql-sync.\n tables:\n common:\n - user\n - permissions\n - role_permissions\n - role\n # List of tables whose *data* is skipped by the 'sql-dump' and 'sql-sync'\n # commands when the \"--structure-tables-key=common\" option is provided.\n # You may add specific tables to the existing array or add a new element.\n structure-tables:\n common:\n - cache\n - 'cache_*'\n - history\n - 'search_*'\n - 'sessions'\n - 'watchdog'\n # List of tables to be omitted entirely from SQL dumps made by the 'sql-dump'\n # and 'sql-sync' commands when the \"--skip-tables-key=common\" option is\n # provided on the command line. This is useful if your database contains\n # non-Drupal tables used by some other application or during a migration for\n # example. You may add new tables to the existing array or add a new element.\n skip-tables:\n common:\n - 'migration_*'\n\nssh:\n # Specify options to pass to ssh. The default is to prohibit\n # password authentication, and is included here, so you may add additional\n # parameters without losing the default configuration.\n options: '-o PasswordAuthentication=no'\n # This string is valid for Bash shell. Override in case you need something different. See https://github.com/drush-ops/drush/issues/3816.\n pipefail: 'set -o pipefail; '\n\nnotify:\n # Notify when command takes more than 30 seconds.\n duration: 30\n # Specify a command to run. Defaults to Notification Center (OSX) or libnotify (Linux)\n cmd: /path/to/program\n # See https://github.com/drush-ops/drush/blob/12.x/src/Commands/core/NotifyCommands.php for more settings.\n\nxh:\n # Start profiling via xhprof/tideways and show a link to the run report.\n link: http://xhprof.local\n # See https://github.com/drush-ops/drush/blob/12.x/src/Commands/core/XhprofCommands.php for more settings.\n profile-builtins: true\n profile-cpu: false\n profile-memory: false\n
"},{"location":"using-drush-configuration/#misc","title":"Misc","text":"drush10.yml
.Tip
Press the / key to Search for a command. Or use your browser's Find in Page feature.
Backup your code, files, and database into a single file.
The following paths would be excluded from a code archive:
composer info --path --format=json
)The following directories would be excluded from a file archive:
drush archive:dump
. Create a site archive file in a temporary directory containing code, database and Drupal files.drush archive:dump --destination=/path/to/archive.tar.gz
. Create /path/to/archive.tar.gz file containing code, database and Drupal files.drush archive:dump --destination=/path/to/archive.tar.gz --overwrite
. Create (or overwrite if exists) /path/to/archive.tar.gz file containing code, database and Drupal files.drush archive:dump --code --destination=/path/to/archive.tar.gz
. Create /path/to/archive.tar.gz file containing the code only.drush archive:dump --exclude-code-paths=foo_bar.txt,web/sites/.+/settings.php --destination=/path/to/archive.tar.gz
. Create /path/to/archive.tar.gz file containing code, database and Drupal files but excluding foo_bar.txt file and settings.php files if found in web/sites/* subdirectories.drush archive:dump --extra-dump=--no-data --destination=/path/to/archive.tar.gz
. Create /path/to/archive.tar.gz file and pass extra option to mysqldump command.drush archive:dump --files --destination=/path/to/archive.tar.gz
. Create /path/to/archive.tar.gz file containing the Drupal files only.drush archive:dump --database --destination=/path/to/archive.tar.gz
. Create /path/to/archive.tar.gz archive file containing the database dump only.drush topic
and pick the first choice.Legend
Restore (import) your code, files, and database.
"},{"location":"commands/archive_restore/#examples","title":"Examples","text":"drush archive:restore /path/to/archive.tar.gz
. Restore the site from /path/to/archive.tar.gz archive file.drush archive:restore /path/to/archive.tar.gz --destination-path=/path/to/restore
. Restore the site from /path/to/archive.tar.gz archive file into /path/to/restore directory.drush archive:restore /path/to/archive.tar.gz --code --destination-path=/path/to/restore
. Restore the code from /path/to/archive.tar.gz archive file into /path/to/restore directory.drush archive:restore /path/to/archive.tar.gz --code-source-path=/code/source/path
. Restore database and Drupal files from /path/to/archive.tar.gz archive file and the code from /code/source/path directory.drush archive:restore /path/to/archive.tar.gz --files --destination-path=/path/to/restore
. Restore the Drupal files from /path/to/archive.tar.gz archive file into /path/to/restore directorydrush archive:restore /path/to/archive.tar.gz --files-source-path=/files/source/path
. Restore code and database from /path/to/archive.tar.gz archive file and the Drupal files from /files/source/path directory.drush archive:restore /path/to/archive.tar.gz --files-destination-relative-path=web/site/foo-bar/files
. Restore the Drupal files from /path/to/archive.tar.gz archive file into web/site/foo-bar/files site's subdirectory.drush archive:restore /path/to/archive.tar.gz --db
. Restore the database from /path/to/archive.tar.gz archive file.drush archive:restore /path/to/archive.tar.gz --db-source-path=/path/to/database.sql
. Restore code and Drupal files from /path/to/archive.tar.gz archive file and the database from /path/to/database.sql dump file.drush archive:restore /path/to/archive.tar.gz --db-url=mysql://user:password@localhost/database_name --destination-path=/path/to/restore
. Restore code, database and Drupal files from /path/to/archive.tar.gz archive file into /path/to/restore directory using database URL.archive:dump
command: * 1) code (\"code\" directory); * 2) database dump file (\"database/database.sql\" file); * 3) Drupal files (\"files\" directory).drush topic
and pick the first choice.Legend
Display a link to a given path or open link in a browser.
"},{"location":"commands/browse/#examples","title":"Examples","text":"drush browse
. Open default web browser (if configured or detected) to the site front page.drush browse node/1
. Open web browser to the path node/1.drush @example.prod browse
. Open a browser to the web site specified in a site alias.drush topic
and pick the first choice.Legend
Clear a specific cache, or all Drupal caches.
"},{"location":"commands/cache_clear/#examples","title":"Examples","text":"drush cc bin
. Choose a bin to clear.drush cc bin entity,bootstrap
. Clear the entity and bootstrap cache bins.drush topic
and pick the first choice.Legend
Fetch a cached object and display it.
"},{"location":"commands/cache_get/#examples","title":"Examples","text":"drush cache:get hook_info bootstrap
. Display the data for the cache id \"hook_info\" from the \"bootstrap\" bin.drush cache:get update_available_releases update
. Display the data for the cache id \"update_available_releases\" from the \"update\" bin.drush topic
and pick the first choice.Legend
Rebuild all caches.
This is a copy of core/rebuild.php.
"},{"location":"commands/cache_rebuild/#options","title":"Options","text":"drush topic
and pick the first choice.Legend
Cache an object expressed in JSON or var_export() format.
"},{"location":"commands/cache_set/#arguments","title":"Arguments","text":"drush topic
and pick the first choice.Legend
Invalidate by cache tags.
"},{"location":"commands/cache_tags/#examples","title":"Examples","text":"drush cache:tag node:12,user:4
. Purge content associated with two cache tags.drush topic
and pick the first choice.Legend
Dump the shell completion script
The *%command.name% command dumps the shell completion script required to use shell autocompletion (currently, bash, fish, zsh completion are supported).
"},{"location":"commands/completion/#static-installation","title":"Static installationDump the script to a global completion file and restart your shell:
*%command.full_name% | sudo tee /etc/bash_completion.d/drush\n
Or dump the script to a local file and source it:
*%command.full_name% > completion.sh\n\n<comment># source the file whenever you use the project\n*source completion.sh\n\n<comment># or add this line at the end of your \"~/.bashrc\" file:\n*source /path/to/completion.sh\n
","text":""},{"location":"commands/completion/#dynamic-installation","title":"Dynamic installation Add this to the end of your shell configuration file (e.g. *\"~/.bashrc\"):
*eval \"$(/home/runner/work/drush/drush/drush completion )\"\n
","text":""},{"location":"commands/completion/#arguments","title":"Arguments","text":"drush topic
and pick the first choice.Legend
Delete a configuration key, or a whole object(s).
"},{"location":"commands/config_delete/#examples","title":"Examples","text":"drush config:delete system.site,system.rss
. Delete the system.site and system.rss config objects.drush config:delete system.site page.front
. Delete the 'page.front' key from the system.site object.drush topic
and pick the first choice.Legend
Open a config file in a text editor. Edits are imported after closing editor.
"},{"location":"commands/config_edit/#examples","title":"Examples","text":"drush config:edit image.style.large
. Edit the image style configurations.drush config:edit
. Choose a config file to edit.drush --bg config-edit image.style.large
. Return to shell prompt as soon as the editor window opens.drush topic
and pick the first choice.Legend
Export Drupal configuration to a directory.
"},{"location":"commands/config_export/#examples","title":"Examples","text":"drush config:export
. Export configuration files to the site's config directory.drush config:export --destination
. Export configuration; Save files in a backup directory named config-export.git add -p
after exporting. This lets you choose which config changes to sync for commit.git add -A
and git commit
after exporting. This commits everything that was exported without prompting.drush topic
and pick the first choice.Legend
Display a config value, or a whole configuration object.
"},{"location":"commands/config_get/#examples","title":"Examples","text":"drush config:get system.site
. Displays the system.site config.drush config:get system.site page.front
. Gets system.site:page.front value.drush topic
and pick the first choice.Legend
Import config from the config directory.
"},{"location":"commands/config_import/#examples","title":"Examples","text":"drush config:import
. Update Drupal's configuration so it matches the contents of the config directory.drush config:import --partial --source=/app/config
. Import from the /app/config directory which typically contains one or a few yaml files.cat tmp.yml | drush config:set --input-format=yaml user.mail ? -
. Update the user.mail config object in its entirety.drush topic
and pick the first choice.Legend
Export and transfer config from one environment to another.
"},{"location":"commands/config_pull/#examples","title":"Examples","text":"drush config:pull @prod @stage
. Export config from @prod and transfer to @stage.drush config:pull @prod @self:../config/sync
. Export config and transfer to a custom directory. Relative paths are calculated from Drupal root.drush topic
and pick the first choice.Legend
Save a config value directly. Does not perform a config import.
"},{"location":"commands/config_set/#examples","title":"Examples","text":"drush config:set system.site name MySite
. Sets a value for the key name of system.site config object.drush config:set system.site page.front /path/to/page
. Sets the given URL path as value for the config item with key page.front of system.site config object.drush config:set system.site '[]'
. Sets the given key to an empty array.drush config:set system.site 'NULL'
. Sets the given key to NULL.drush config:set --input-format=yaml user.role.authenticated permissions [foo,bar]
. Use a sequence as value for the key permissions of user.role.authenticated config object.drush config:set --input-format=yaml system.site page {403: '403', front: home}
. Use a mapping as value for the key page of system.site config object.drush config:set --input-format=yaml user.role.authenticated ? \"{label: 'Auth user', weight: 5}\"
. Update two top level keys (label, weight) in the system.site config object.cat tmp.yml | drush config:set --input-format=yaml user.mail ? -
. Update the user.mail config object in its entirety.drush topic
and pick the first choice.Legend
Display status of configuration (differences between the filesystem and database).
"},{"location":"commands/config_status/#examples","title":"Examples","text":"drush config:status
. Display configuration items that need to be synchronized.drush config:status --state=Identical
. Display configuration items that are in default state.drush config:status --state='Only in sync dir' --prefix=node.type.
. Display all content types that would be created in active storage on configuration import.drush config:status --state=Any --format=list
. List all config names.drush config:status 2>&1 | grep \"No differences\"
. Check there are no differences between database and exported config. Useful for CI.drush topic
and pick the first choice.Legend
Run all cron hooks in all active modules for specified site.
Consider using drush maint:status && drush core:cron
to avoid cache poisoning during maintenance mode.
drush topic
and pick the first choice.drush cron
. (docs:cron)Legend
Edit drush.yml, site alias, and Drupal settings.php files.
"},{"location":"commands/core_edit/#examples","title":"Examples","text":"drush core:edit
. Pick from a list of config/alias/settings files. Open selected in editor.drush --bg core-config
. Return to shell prompt as soon as the editor window opens.drush core:edit etc
. Edit the global configuration file.drush core:edit demo.alia
. Edit a particular alias file.drush core:edit sett
. Edit settings.php for the current Drupal site.drush core:edit --choice=2
. Edit the second file in the choice list.drush topic
and pick the first choice.Legend
Information about things that may be wrong in your Drupal installation.
"},{"location":"commands/core_requirements/#examples","title":"Examples","text":"drush core:requirements
. Show all status lines from the Status Report admin page.drush core:requirements --severity=2
. Show only the red lines from the Status Report admin page.drush topic
and pick the first choice.Legend
10.5+
View information about all routes or one route.
"},{"location":"commands/core_route/#examples","title":"Examples","text":"drush route
. View all routes.drush route --name=update.status
. View details about the update.status route.drush route --path=/user/1
. View details about the entity.user.canonical route.drush route --url=https://example.com/node/1
. View details about the entity.node.canonical route.drush topic
and pick the first choice.Legend
Rsync Drupal code or files to/from another server using ssh.
"},{"location":"commands/core_rsync/#examples","title":"Examples","text":"drush rsync @dev @stage
. Rsync Drupal root from Drush alias dev to the alias stage.drush rsync ./ @stage:%files/img
. Rsync all files in the current directory to the imgdirectory in the file storage folder on the Drush alias stage.drush rsync @live:%private @stage:%private
. Rsync private files from live to stage.drush rsync @dev @stage -- --exclude=*.sql --delete
. Rsync Drupal root from the Drush alias dev to the alias stage, excluding all .sql files and delete all files on the destination that are no longer on the source.drush rsync @dev @stage --ssh-options=\"-o StrictHostKeyChecking=no\" -- --delete
. Customize how rsync connects with remote host via SSH. rsync options like --delete are placed after a --.drush topic
and pick the first choice.Legend
An overview of the environment - Drush and Drupal.
"},{"location":"commands/core_status/#examples","title":"Examples","text":"drush core-status --field=files
. Emit just one field, not all the default fields.drush core-status --fields=*
. Emit all fields, not just the default ones.drush topic
and pick the first choice.Legend
Read detailed documentation on a given topic.
"},{"location":"commands/core_topic/#examples","title":"Examples","text":"drush topic
. Pick from all available topics.drush topic docs-repl
. Show documentation for the Drush interactive shelldrush docs:r
. Filter topics for those starting with 'docs-r'.drush topic
and pick the first choice.Legend
10.3+
Run several commands after performing a code deployment.
"},{"location":"commands/deploy/#examples","title":"Examples","text":"drush deploy -v -y
. Run updates with verbose logging and accept all prompts.drush topic
and pick the first choice.Legend
Prints information about pending deploy update hooks.
"},{"location":"commands/deploy_hook-status/#examples","title":"Examples","text":"drush deploy:hook-status
. Prints information about pending deploy hooks.drush topic
and pick the first choice.Legend
10.3+
Run pending deploy update hooks.
"},{"location":"commands/deploy_hook/#examples","title":"Examples","text":"drush deploy:hook
. Run pending deploy hooks.drush topic
and pick the first choice.Legend
10.6.1+
Mark all deploy hooks as having run.
"},{"location":"commands/deploy_mark-complete/#examples","title":"Examples","text":"drush deploy:mark-complete
. Skip all pending deploy hooks and mark them as complete.drush topic
and pick the first choice.Legend
Return the filesystem path for modules/themes and other key folders.
"},{"location":"commands/drupal_directory/#examples","title":"Examples","text":"cd $(drush dd devel)
. Navigate into the devel module directorycd $(drush dd)
. Navigate to the root of your Drupal sitecd $(drush dd files)
. Navigate to the files directory.drush dd @alias:%files
. Print the path to the files directory on the site @alias.edit $(drush dd devel)/devel.module
. Open devel module in your editordrush topic
and pick the first choice.Legend
12.5+
Create a content entity after prompting for field values.
When entering field values, one may submit an incomplete document and any entity violations will be helpfully reported at the top of the document. enter skip as a value in order to skip validation for that field. Timestamp values may be expressed via any string recognized by strtotime()
"},{"location":"commands/entity_create/#examples","title":"Examples","text":"drush entity:create node article --validate=0
. Create an article entity and skip validation entirely.drush entity:create node article --skip-fields=field_media_image,field_tags
. Create an article omitting two fields.drush entity:create user user --editor=nano
. Create a user using the Nano text editor.drush topic
and pick the first choice.Legend
Delete content entities.
To delete configuration entities, see config:delete command.
"},{"location":"commands/entity_delete/#examples","title":"Examples","text":"drush entity:delete node --bundle=article
. Delete all article entities.drush entity:delete shortcut
. Delete all shortcut entities.drush entity:delete node 22,24
. Delete nodes 22 and 24.drush entity:delete user
. Delete all users except uid=1.drush entity:delete node --exclude=9,14,81
. Delete all nodes except node 9, 14 and 81.drush entity:delete node --chunks=5
. Delete all node entities in steps of 5.drush topic
and pick the first choice.Legend
11.0+
Load and save entities.
"},{"location":"commands/entity_save/#examples","title":"Examples","text":"drush entity:save node --bundle=article
. Re-save all article entities.drush entity:save shortcut
. Re-save all shortcut entities.drush entity:save node 22,24
. Re-save nodes 22 and 24.drush entity:save node --exclude=9,14,81
. Re-save all nodes except node 9, 14 and 81.drush entity:save user
. Re-save all users.drush entity:save node --chunks=5
. Re-save all node entities in steps of 5.drush topic
and pick the first choice.Legend
11.0+
List all base fields of an entity type
"},{"location":"commands/field_base-info/#examples","title":"Examples","text":"field:base-info taxonomy_term
. List all base fields.field:base-info
. List all base fields and fill in the remaining information through prompts.drush topic
and pick the first choice.Legend
11.0+
Create a new base field override
"},{"location":"commands/field_base-override-create/#examples","title":"Examples","text":"field:base-field-override-create
. Create a base field override by answering the prompts.field:base-field-override-create taxonomy_term tag
. Create a base field override and fill in the remaining information through prompts.field:base-field-override-create taxonomy_term tag --field-name=name --field-label=Label --is-required=1
. Create a base field override in a completely non-interactive way.drush topic
and pick the first choice.Legend
11.0+
Create a new field
"},{"location":"commands/field_create/#examples","title":"Examples","text":"field:create
. Create a field by answering the prompts.field-create taxonomy_term tag
. Create a field and fill in the remaining information through prompts.field-create taxonomy_term tag --field-name=field_tag_label --field-label=Label --field-type=string --field-widget=string_textfield --is-required=1 --cardinality=2
. Create a field in a completely non-interactive way.drush topic
and pick the first choice.Legend
11.0+
Delete a field
"},{"location":"commands/field_delete/#examples","title":"Examples","text":"field:delete
. Delete a field by answering the prompts.field-delete taxonomy_term tag
. Delete a field and fill in the remaining information through prompts.field-delete taxonomy_term tag --field-name=field_tag_label
. Delete a field in a non-interactive way.field-delete taxonomy_term --field-name=field_tag_label --all-bundles
. Delete a field from all bundles.drush topic
and pick the first choice.Legend
Lists field formatters.
"},{"location":"commands/field_formatters/#examples","title":"Examples","text":"drush field:formatters --field-type=entity_reference
. Lists field formatters applicable for entity reference fields.drush topic
and pick the first choice.Legend
11.0+
List all configurable fields of an entity bundle
"},{"location":"commands/field_info/#examples","title":"Examples","text":"field:info taxonomy_term tag
. List all fields.field:info
. List all fields and fill in the remaining information through prompts.drush topic
and pick the first choice.Legend
Lists field types.
"},{"location":"commands/field_types/#examples","title":"Examples","text":"drush field:types
. List all registered field types.drush topic
and pick the first choice.Legend
Lists field widgets.
"},{"location":"commands/field_widgets/#examples","title":"Examples","text":"drush field:widgets --field-type=entity_reference
. Lists field widgets applicable for entity reference fields.drush topic
and pick the first choice.Legend
Generate boilerplate code for modules/plugins/services etc.
Drush asks questions so that the generated code is as polished as possible. After generating, Drush lists the files that were created.
See https://github.com/Chi-teck/drupal-code-generator for a README and bug reports.
"},{"location":"commands/generate/#examples","title":"Examples","text":"drush generate
. Pick from available generators and then run it.drush generate drush-command-file
. Generate a Drush commandfile for your module.drush generate controller --answer=Example --answer=example
. Generate a controller class and pre-fill the first two questions in the wizard.drush generate controller -vvv --dry-run
. Learn all the potential answers so you can re-run with several --answer options.drush topic
and pick the first choice.Legend
Display usage details for a command.
"},{"location":"commands/help/#examples","title":"Examples","text":"drush help pm:uninstall
. Show help for a command.drush help pmu
. Show help for a command using an alias.drush help --format=xml
. Show all available commands in XML format.drush help --format=json
. All available commands, in JSON format.drush topic
and pick the first choice.Legend
Create an image derivative.
"},{"location":"commands/image_derive/#examples","title":"Examples","text":"drush image:derive thumbnail core/themes/bartik/screenshot.png
. Save thumbnail sized derivative of logo image.drush topic
and pick the first choice.Legend
Flush all derived images for a given style.
"},{"location":"commands/image_flush/#examples","title":"Examples","text":"drush image:flush
. Pick an image style and then delete its derivatives.drush image:flush thumbnail,large
. Delete all thumbnail and large derivatives.drush image:flush --all
. Flush all derived images. They will be regenerated on demand.drush topic
and pick the first choice.Legend
Execute a JSONAPI request.
"},{"location":"commands/jn_get/#examples","title":"Examples","text":"drush jn:get jsonapi/node/article
. Get a list of articles back as JSON.drush jn:get jsonapi/node/article | jq
. Pretty print JSON by piping to jq. See https://stedolan.github.io/jq/ for lots more jq features.drush topic
and pick the first choice.Legend
List available commands.
"},{"location":"commands/list/#examples","title":"Examples","text":"drush list
. List all commands.drush list --filter=devel_generate
. Show only commands starting with devel-drush list --format=xml
. List all commands in Symfony compatible xml format.drush topic
and pick the first choice.Legend
Checks for available translation updates.
"},{"location":"commands/locale_check/#global-options","title":"Global Options","text":"drush topic
and pick the first choice.Legend
11.5+
Clears the translation status.
"},{"location":"commands/locale_clear-status/#global-options","title":"Global Options","text":"drush topic
and pick the first choice.Legend
Exports to a gettext translation file.
See Drupal Core: \\Drupal\\locale\\Form\\ExportForm::submitForm
"},{"location":"commands/locale_export/#examples","title":"Examples","text":"drush locale:export nl > nl.po
. Export the Dutch translations with all types.drush locale:export nl --types=customized,not-customized > nl.po
. Export the Dutch customized and not customized translations.drush locale:export --template > drupal.pot
. Export the source strings only as template file for translation.drush topic
and pick the first choice.Legend
12.2+
Imports multiple translation files from the defined directory.
"},{"location":"commands/locale_import-all/#examples","title":"Examples","text":"drush locale:import-all /var/www/translations
. Import all translations from the defined directory (non-recursively). Supported filename patterns are: {project}-{version}.{langcode}.po, {prefix}.{langcode}.po or {langcode}.po.drush locale:import-all /var/www/translations/custom --types=customized --override=all
. Import all custom translations from the defined directory (non-recursively) and override any existing translation. Supported filename patterns are: {project}-{version}.{langcode}.po, {prefix}.{langcode}.po or {langcode}.po.drush topic
and pick the first choice.Legend
Imports to a gettext translation file.
"},{"location":"commands/locale_import/#examples","title":"Examples","text":"drush locale-import nl drupal-8.4.2.nl.po
. Import the Dutch drupal core translation.drush locale-import --type=customized nl drupal-8.4.2.nl.po
. Import the Dutch drupal core translation. Treat imported strings as custom translations.drush locale-import --override=none nl drupal-8.4.2.nl.po
. Import the Dutch drupal core translation. Don't overwrite existing translations. Only append new translations.drush locale-import --override=not-customized nl drupal-8.4.2.nl.po
. Import the Dutch drupal core translation. Only override non-customized translations, customized translations are kept.drush locale-import nl custom-translations.po --type=customized --override=all
. Import customized Dutch translations and override any existing translation.drush topic
and pick the first choice.Legend
Imports the available translation updates.
"},{"location":"commands/locale_update/#options","title":"Options","text":"drush topic
and pick the first choice.Legend
11.5+
Get maintenance mode. Returns 1 if enabled, 0 if not.
Consider using maint:status instead when chaining commands.
"},{"location":"commands/maint_get/#examples","title":"Examples","text":"drush maint:get
. Print value of maintenance mode in Drupaldrush topic
and pick the first choice.Legend
11.5+
Set maintenance mode.
"},{"location":"commands/maint_set/#examples","title":"Examples","text":"drush maint:set 1
. Put site into Maintenance mode.drush maint:set 0
. Remove site from Maintenance mode.drush topic
and pick the first choice.Legend
11.5+
Fail if maintenance mode is enabled.
This commands fails with exit code of 3 when maintenance mode is on. This special exit code distinguishes from a failure to complete.
"},{"location":"commands/maint_status/#examples","title":"Examples","text":"drush maint:status && drush cron
. Only run cron when Drupal is not in maintenance mode.drush topic
and pick the first choice.Legend
10.4+
List the fields available for mapping in a source.
"},{"location":"commands/migrate_fields-source/#examples","title":"Examples","text":"migrate:fields-source article
. List fields for the source in the article migration.drush topic
and pick the first choice.Legend
10.4+
Perform one or more migration processes.
"},{"location":"commands/migrate_import/#examples","title":"Examples","text":"migrate:import --all
. Perform all migrationsmigrate:import --all --no-progress
. Perform all migrations but avoid the progress barmigrate:import --tag=user,main_content
. Import all migrations tagged with user and main_content tagsmigrate:import classification,article
. Import new terms and nodes using migration classification and articlemigrate:import user --limit=2
. Import no more than 2 users using the user migrationmigrate:import user --idlist=5
. Import the user record with source ID 5migrate:import node_revision --idlist=1:2,2:3,3:5
. Import the node revision record with source IDs [1,2], [2,3], and [3,5]migrate:import user --limit=50 --feedback=20
. Import 50 users and show process message every 20th recordmigrate:import --all --delete
. Perform all migrations and delete the destination items that are missing from sourcedrush topic
and pick the first choice.Legend
10.4+
View any messages associated with a migration.
"},{"location":"commands/migrate_messages/#examples","title":"Examples","text":"migrate:messages article
. Show all messages for the article migrationmigrate:messages node_revision --idlist=1:2,2:3,3:5
. Show messages related to node revision records with source IDs [1,2], [2,3], and [3,5].migrate:messages custom_node_revision --idlist=1:\"r:1\",2:\"r:3\"
. Show messages related to node revision records with source IDs [1,\"r:1\"], and [2,\"r:3\"].drush topic
and pick the first choice.Legend
10.4+
Reset an active migration's status to idle.
"},{"location":"commands/migrate_reset-status/#arguments","title":"Arguments","text":"drush topic
and pick the first choice.Legend
10.4+
Rollback one or more migrations.
"},{"location":"commands/migrate_rollback/#examples","title":"Examples","text":"migrate:rollback --all
. Rollback all migrationsmigrate:rollback --all --no-progress
. Rollback all migrations but avoid the progress barmigrate:rollback --tag=user,main_content
. Rollback all migrations tagged with user and main_content tagsmigrate:rollback classification,article
. Rollback terms and nodes imported by classification and article migrationsmigrate:rollback user --idlist=5
. Rollback imported user record with source ID 5drush topic
and pick the first choice.Legend
10.4+
List all migrations with current status.
"},{"location":"commands/migrate_status/#examples","title":"Examples","text":"migrate:status
. Retrieve status for all migrationsmigrate:status --tag
. Retrieve status for all migrations, grouped by tagmigrate:status --tag=user,main_content
. Retrieve status for all migrations tagged with user or main_contentmigrate:status classification,article
. Retrieve status for specific migrationsmigrate:status --field=id
. Retrieve a raw list of migration IDs.ms --fields=id,status --format=json
. Retrieve a Json serialized list of migrations, each item containing only the migration ID and its status.drush topic
and pick the first choice.Legend
10.4+
Stop an active migration operation.
"},{"location":"commands/migrate_stop/#arguments","title":"Arguments","text":"drush topic
and pick the first choice.Legend
Build a Markdown document for each available Drush command/generator.
This command is an early step when building the www.drush.org static site. Adapt it to build a similar site listing the commands that are available on your site. Also see Drush's Github Actions workflow.
"},{"location":"commands/mk_docs/#examples","title":"Examples","text":"drush mk:docs
. Build many .md files in the docs/commands and docs/generators directories.drush topic
and pick the first choice.Legend
Open an interactive shell on a Drupal site.
"},{"location":"commands/php_cli/#examples","title":"Examples","text":"$node = Node::load(1)
. Entity classes are available without their namespace. For example, Node::load(1) works instead of Drupal\\Node\\entity\\Node::load(1).$paragraph = Paragraph::loadRevision(1)
. Also, a loadRevision static method is made available for easier load of revisions.drush topic
and pick the first choice.Legend
Evaluate arbitrary php code after bootstrapping Drupal (if available).
"},{"location":"commands/php_eval/#examples","title":"Examples","text":"drush php:eval '$node = \\Drupal ode\\Entity\\Node::load(1); print $node->getTitle();'
. Loads node with nid 1 and then prints its title.drush php:eval \"\\Drupal::service('file_system')->copy('$HOME/Pictures/image.jpg', 'public://image.jpg');\"
. Copies a file whose path is determined by an environment's variable. Use of double quotes so the variable $HOME gets replaced by its value.drush php:eval \"node_access_rebuild();\"
. Rebuild node access permissions.drush topic
and pick the first choice.Legend
Run php a script after a full Drupal bootstrap.
A useful alternative to eval command when your php is lengthy or you can't be bothered to figure out bash quoting. If you plan to share a script with others, consider making a full Drush command instead, since that's more self-documenting. Drush provides commandline options to the script via a variable called $extra.
"},{"location":"commands/php_script/#examples","title":"Examples","text":"drush php:script example --script-path=/path/to/scripts:/another/path
. Run a script named example.php from specified pathsdrush php:script -
. Run PHP code from standard input.drush php:script
. List all available scripts.drush php:script foo -- apple --cider
. Run foo.php script with argument apple and option cider. Note the -- separator.drush topic
and pick the first choice.Legend
Enable one or more modules.
"},{"location":"commands/pm_install/#examples","title":"Examples","text":"drush pm:install --simulate content_moderation
. Display what modules would be installed but don't install them.drush topic
and pick the first choice.Legend
Show a list of available extensions (modules and themes).
"},{"location":"commands/pm_list/#options","title":"Options","text":"drush topic
and pick the first choice.Legend
Uninstall one or more modules and their dependent modules.
"},{"location":"commands/pm_uninstall/#examples","title":"Examples","text":"drush pm:uninstall --simulate field_ui
. Display what modules would be uninstalled but don't uninstall them.drush topic
and pick the first choice.Legend
Delete all items in a specific queue.
"},{"location":"commands/queue_delete/#arguments","title":"Arguments","text":"drush topic
and pick the first choice.Legend
Returns a list of all defined queues.
"},{"location":"commands/queue_list/#options","title":"Options","text":"drush topic
and pick the first choice.Legend
Run a specific queue by name.
"},{"location":"commands/queue_run/#arguments","title":"Arguments","text":"drush topic
and pick the first choice.Legend
Create a new role.
"},{"location":"commands/role_create/#examples","title":"Examples","text":"drush role:create 'test_role' 'Test role'
. Create a new role with a machine name of 'test_role', and a human-readable name of 'Test role'.drush topic
and pick the first choice.Legend
Delete a role.
"},{"location":"commands/role_delete/#examples","title":"Examples","text":"drush role:delete 'test_role'
. Delete the role 'test_role'.drush topic
and pick the first choice.Legend
Display roles and their permissions.
"},{"location":"commands/role_list/#examples","title":"Examples","text":"drush role:list --filter='administer nodes'
. Display a list of roles that have the administer nodes permission assigned.drush role:list --filter='rid=anonymous'
. Display only the anonymous role.drush topic
and pick the first choice.Legend
Grant specified permission(s) to a role.
"},{"location":"commands/role_perm_add/#examples","title":"Examples","text":"drush role:perm:add anonymous 'post comments'
. Allow anon users to post comments.drush role:perm:add anonymous 'post comments,access content'
. Allow anon users to post comments and access content.drush topic
and pick the first choice.Legend
Remove specified permission(s) from a role.
"},{"location":"commands/role_perm_remove/#examples","title":"Examples","text":"drush role:remove-perm anonymous
. Remove 2 permissions from anon users.drush topic
and pick the first choice.Legend
Runs PHP's built-in http server for development.
drush rs 8080
. Start a web server on 127.0.0.1, port 8080.drush rs 10.0.0.28:80
. Start runserver on 10.0.0.28, port 80.drush rs [::1]:80
. Start runserver on IPv6 localhost ::1, port 80.drush rs --dns localhost:8888/user
. Start runserver on localhost (using rDNS to determine binding IP), port 8888, and open /user in browser.drush rs /
. Start runserver on default IP/port (127.0.0.1, port 8888), and open / in browser.drush rs :9000/admin
. Start runserver on 127.0.0.1, port 9000, and open /admin in browser. Note that you need a colon when you specify port and path, but no IP.drush --quiet rs
. Silence logging the printing of web requests to the console.drush topic
and pick the first choice.Legend
Show site alias details, or a list of available site aliases.
"},{"location":"commands/site_alias/#examples","title":"Examples","text":"drush site:alias
. List all alias records known to drush.drush site:alias @dev
. Print an alias record for the alias dev.drush topic
and pick the first choice.Legend
Install Drupal along with modules/themes/configuration/profile.
"},{"location":"commands/site_install/#examples","title":"Examples","text":"drush si demo_umami --locale=da
. (Re)install using the Umami install profile. Set default language to Danish.drush si --db-url=mysql://user:pass@localhost:port/dbname
. Install using the specified DB params.drush si --db-url=sqlite://sites/example.com/files/.ht.sqlite
. Install using SQLitedrush si --db-url=sqlite://:memory:
. Install using SQLite in-memory database.drush si --account-pass=mom
. Re-install with specified uid1 password.drush si --existing-config
. Install based on the yml files stored in the config export/import directory.drush si standard install_configure_form.enable_update_status_emails=NULL
. Disable email notification during install and later. If your server has no mail transfer agent, this gets rid of an error during install.drush topic
and pick the first choice.Legend
Set a site alias that will persist for the current session.
Stores the site alias being used in the current session in a temporary file.
"},{"location":"commands/site_set/#examples","title":"Examples","text":"drush site:set @dev
. Set the current session to use the @dev alias.drush site:set user@server/path/to/drupal#sitename
. Set the current session to use a remote site via site specification.drush site:set /path/to/drupal#sitename
. Set the current session to use a local site via site specification.drush site:set -
. Go back to the previously-set site (like cd -
).drush site:set
. Without an argument, any existing site becomes unset.drush topic
and pick the first choice.Legend
Connect to a webserver via SSH, and optionally run a shell command.
"},{"location":"commands/site_ssh/#examples","title":"Examples","text":"drush @mysite ssh
. Open an interactive shell on @mysite's server.drush @prod ssh \"ls /tmp\"
. Run ls /tmp on @prod site.drush @prod ssh \"git pull\"
. Run git pull on the Drupal root directory on the @prod site.drush ssh \"git pull\"
. Run git pull on the local Drupal root directory.drush topic
and pick the first choice.Legend
Open a SQL command-line interface using Drupal's credentials.
"},{"location":"commands/sql_cli/#examples","title":"Examples","text":"drush sql:cli
. Open a SQL command-line interface using Drupal's credentials.drush sql:cli --extra=--progress-reports
. Open a SQL CLI and skip reading table information.drush sql:cli < example.sql
. Import sql statements from a file into the current database.drush topic
and pick the first choice.Legend
A string for connecting to the DB.
"},{"location":"commands/sql_connect/#examples","title":"Examples","text":"$(drush sql:connect) < example.sql
. Bash: Import SQL statements from a file into the current database.eval (drush sql:connect) < example.sql
. Fish: Import SQL statements from a file into the current database.drush topic
and pick the first choice.Legend
Create a database.
"},{"location":"commands/sql_create/#examples","title":"Examples","text":"drush sql:create
. Create the database for the current site.drush @site.test sql:create
. Create the database as specified for @site.test.drush sql:create --db-su=root --db-su-pw=rootpassword --db-url=\"mysql://drupal_db_user:drupal_db_password@127.0.0.1/drupal_db\"
. Create the database as specified in the db-url option.drush topic
and pick the first choice.Legend
Drop all tables in a given database.
"},{"location":"commands/sql_drop/#options","title":"Options","text":"drush topic
and pick the first choice.Legend
Exports the Drupal DB as SQL using mysqldump or equivalent.
--create-db is used by sql-sync, since including the DROP TABLE statements interferes with the import when the database is created.
"},{"location":"commands/sql_dump/#examples","title":"Examples","text":"drush sql:dump --result-file=../18.sql
. Save SQL dump to the directory above Drupal root.drush sql:dump --skip-tables-key=common
. Skip standard tables. See Drush configurationdrush sql:dump --extra-dump=--no-data
. Pass extra option to mysqldump command.drush topic
and pick the first choice.Legend
Execute a query against a database.
"},{"location":"commands/sql_query/#examples","title":"Examples","text":"drush sql:query \"SELECT * FROM users WHERE uid=1\"
. Browse user record. Table prefixes, if used, must be added to table names by hand.drush sql:query --db-prefix \"SELECT * FROM {users}\"
. Browse user record. Table prefixes are honored. Caution: All curly-braces will be stripped.$(drush sql:connect) < example.sql
. Import sql statements from a file into the current database.drush sql:query --file=example.sql
. Alternate way to import sql statements from a file.drush php:eval --format=json \"return \\Drupal::service('database')->query('SELECT * FROM users LIMIT 5')->fetchAll()\"
. Get data back in JSON format. See https://github.com/drush-ops/drush/issues/3071#issuecomment-347929777.$(drush sql:connect) -e \"SELECT * FROM users LIMIT 5;\"
. Results are formatted in a pretty table with borders and column headers.drush topic
and pick the first choice.Legend
Sanitize the database by removing or obfuscating user data.
Commandfiles may add custom operations by implementing:
- `#[CLI\\Hook(type: HookManager::ON_EVENT, target: SanitizeCommands::CONFIRMS)]`. Display summary to user before confirmation.\n- `#[CLI\\Hook(type: HookManager::POST_COMMAND_HOOK, target: SanitizeCommands::SANITIZE)]`. Run queries or call APIs to perform sanitizing\n
Several working commandfiles may be found at https://github.com/drush-ops/drush/tree/12.x/src/Drupal/Commands/sql
"},{"location":"commands/sql_sanitize/#examples","title":"Examples","text":"drush sql:sanitize --sanitize-password=no
. Sanitize database without modifying any passwords.drush sql:sanitize --allowlist-fields=field_biography,field_phone_number
. Sanitizes database but exempts two user fields from modification.drush topic
and pick the first choice.Legend
Copy DB data from a source site to a target site. Transfers data via rsync.
"},{"location":"commands/sql_sync/#examples","title":"Examples","text":"drush sql:sync @source @self
. Copy the database from the site with the alias 'source' to the local site.drush sql:sync @self @target
. Copy the database from the local site to the site with the alias 'target'.drush sql:sync #prod #dev
. Copy the database from the site in /sites/prod to the site in /sites/dev (multisite installation).drush topic
and pick the first choice.Legend
Delete a state entry.
"},{"location":"commands/state_delete/#examples","title":"Examples","text":"drush state:del system.cron_last
. Delete state entry for system.cron_last.drush topic
and pick the first choice.Legend
Display a state value.
"},{"location":"commands/state_get/#examples","title":"Examples","text":"drush state:get system.cron_last
. Displays last cron run timestampdrush state:get drupal_css_cache_files --format=yaml
. Displays an array of css files in yaml format.drush topic
and pick the first choice.Legend
Set a state value.
"},{"location":"commands/state_set/#examples","title":"Examples","text":"drush sset system.maintenance_mode 1 --input-format=integer
. Put site into Maintenance mode.drush state:set system.cron_last 1406682882 --input-format=integer
. Sets a timestamp for last cron run.php -r \"print json_encode(array('drupal', 'simpletest'));\" | drush state-set --input-format=json foo.name -
. Set a key to a complex value (e.g. array)drush state:set twig_debug TRUE
. Enable the Twig debug mode (since Drupal 10.1)drush state:set twig_autoreload TRUE
. Enable Twig auto reload (since Drupal 10.1)drush state:set twig_cache_disable TRUE
. Disable the Twig, page, render and dynamic page caches (since Drupal 10.1)drush state:set disable_rendered_output_cache_bins TRUE
. Disables render cache, dynamic page cache, and page cache. (since Drupal 10.1)drush topic
and pick the first choice.Legend
Install one or more themes.
"},{"location":"commands/theme_install/#arguments","title":"Arguments","text":"drush topic
and pick the first choice.Legend
Uninstall themes.
"},{"location":"commands/theme_uninstall/#arguments","title":"Arguments","text":"drush topic
and pick the first choice.Legend
Compile all Twig template(s).
"},{"location":"commands/twig_compile/#global-options","title":"Global Options","text":"drush topic
and pick the first choice.Legend
12.1+
Enables Twig debug and disables caching Twig templates.
"},{"location":"commands/twig_debug/#arguments","title":"Arguments","text":"drush topic
and pick the first choice.Legend
Find potentially unused Twig templates.
Immediately before running this command, web crawl your entire web site. Or use your Production PHPStorage dir for comparison.
"},{"location":"commands/twig_unused/#examples","title":"Examples","text":"drush twig:unused --field=template /var/www/mass.local/docroot/modules/custom,/var/www/mass.local/docroot/themes/custom
. Output a simple list of potentially unused templates.drush topic
and pick the first choice.Legend
Apply any database updates required (as with running update.php).
"},{"location":"commands/updatedb/#options","title":"Options","text":"drush topic
and pick the first choice.Legend
List any pending database updates.
"},{"location":"commands/updatedb_status/#options","title":"Options","text":"drush topic
and pick the first choice.Legend
Block the specified user(s).
"},{"location":"commands/user_block/#examples","title":"Examples","text":"drush user:block user3
. Block the user whose name is user3drush user:cancel user3 --delete-content
. Delete the user whose name is user3 and delete her content.drush user:cancel user3 --reassign-content
. Delete the user whose name is user3 and reassign her content to the anonymous user.drush topic
and pick the first choice.Legend
Block or delete user account(s) with the specified name(s).
drush user:cancel username
. Block the user account with the name username.drush user:cancel --delete-content username
. Delete the user account with the name username and delete all content created by that user.drush user:cancel --reassign-content username
. Delete the user account with the name username and assign all her content to the anonymous user.drush topic
and pick the first choice.Legend
Create a user account.
"},{"location":"commands/user_create/#examples","title":"Examples","text":"drush user:create newuser --mail='person@example.com' --password='letmein'
. Create a new user account with the name newuser, the email address person@example.com, and the password letmeindrush topic
and pick the first choice.Legend
Print information about the specified user(s).
"},{"location":"commands/user_information/#examples","title":"Examples","text":"drush user:information someguy,somegal
. Display information about the someguy and somegal user accounts.drush user:information --mail=someguy@somegal.com
. Display information for a given email account.drush user:information --uid=5
. Display information for a given user id.drush uinf --uid=$(drush sqlq \"SELECT GROUP_CONCAT(entity_id) FROM user__roles WHERE roles_target_id = 'administrator'\")
. Display information for all administrators.drush topic
and pick the first choice.Legend
Display a one time login link for user ID 1, or another user.
"},{"location":"commands/user_login/#examples","title":"Examples","text":"drush user:login
. Open browser to homepage, logged in as uid=1.drush user:login --name=ryan node/add/blog
. Open browser (if configured or detected) for a one-time login link for username ryan that redirects to node/add/blog.drush user:login --uid=123
. Open browser and login as user with uid \"123\".drush user:login --mail=foo@bar.com
. Open browser and login as user with mail \"foo@bar.com\".drush topic
and pick the first choice.Legend
Set the password for the user account with the specified name.
"},{"location":"commands/user_password/#examples","title":"Examples","text":"drush user:password someuser 'correct horse battery staple'
. Set the password for the username someuser. See https://xkcd.com/936drush topic
and pick the first choice.Legend
Add a role to the specified user accounts.
"},{"location":"commands/user_role_add/#examples","title":"Examples","text":"drush user:role:add 'editor' user3
. Add the editor role to user3drush topic
and pick the first choice.Legend
Remove a role from the specified user accounts.
"},{"location":"commands/user_role_remove/#examples","title":"Examples","text":"drush user:role:remove 'power_user' user3
. Remove the power_user role from user3drush topic
and pick the first choice.Legend
Unblock the specified user(s).
"},{"location":"commands/user_unblock/#examples","title":"Examples","text":"drush user:unblock user3
. Unblock the user whose name is user3drush topic
and pick the first choice.Legend
Show Drush version.
"},{"location":"commands/version/#options","title":"Options","text":"drush topic
and pick the first choice.Legend
Set several Views settings to more developer-oriented values.
"},{"location":"commands/views_dev/#global-options","title":"Global Options","text":"drush topic
and pick the first choice.Legend
Disable the specified views.
"},{"location":"commands/views_disable/#examples","title":"Examples","text":"drush vdis frontpage taxonomy_term
. Disable the frontpage and taxonomy_term views.drush topic
and pick the first choice.Legend
Enable the specified views.
"},{"location":"commands/views_enable/#examples","title":"Examples","text":"drush ven frontpage,taxonomy_term
. Enable the frontpage and taxonomy_term views.drush topic
and pick the first choice.Legend
Execute a view and show a count of the results, or the rendered HTML.
"},{"location":"commands/views_execute/#examples","title":"Examples","text":"drush views:execute my_view
. Show the rendered HTML for the default display for the my_view View.drush views:execute my_view page_1 3 --count
. Show a count of my_view:page_1 where the first contextual filter value is 3.drush views:execute my_view page_1 3,foo
. Show the rendered HTML of my_view:page_1 where the first two contextual filter values are 3 and 'foo' respectively.drush topic
and pick the first choice.Legend
Get a list of all views in the system.
"},{"location":"commands/views_list/#examples","title":"Examples","text":"drush vl
. Show a list of all available views.drush vl --name=blog
. Show a list of views which names contain 'blog'.drush vl --tags=tag1,tag2
. Show a list of views tagged with 'tag1' or 'tag2'.drush vl --status=enabled
. Show a list of enabled views.drush topic
and pick the first choice.Legend
Delete watchdog log records.
"},{"location":"commands/watchdog_delete/#examples","title":"Examples","text":"drush watchdog:delete all
. Delete all messages.drush watchdog:delete 64
. Delete messages with id 64.drush watchdog:delete \"cron run succesful\"
. Delete messages containing the string \"cron run succesful\".drush watchdog:delete --severity=Notice
. Delete all messages with a severity of notice.drush watchdog:delete --type=cron
. Delete all messages of type cron.drush topic
and pick the first choice.Legend
Interactively filter the watchdog message listing.
"},{"location":"commands/watchdog_list/#examples","title":"Examples","text":"drush watchdog:list
. Prompt for message type or severity, then run watchdog:show.drush topic
and pick the first choice.Legend
Show one log record by ID.
"},{"location":"commands/watchdog_show-one/#arguments","title":"Arguments","text":"drush topic
and pick the first choice.Legend
Show watchdog messages.
"},{"location":"commands/watchdog_show/#examples","title":"Examples","text":"drush watchdog:show
. Show a listing of most recent 10 messages.drush watchdog:show \"cron run successful\"
. Show a listing of most recent 10 messages containing the string cron run successful.drush watchdog:show --count=46
. Show a listing of most recent 46 messages.drush watchdog:show --severity=Notice
. Show a listing of most recent 10 messages with a severity of notice.drush watchdog:show --severity-min=Warning
. Show a listing of most recent 10 messages with a severity of warning or higher.drush watchdog:show --type=php
. Show a listing of most recent 10 messages of type phpdrush topic
and pick the first choice.Legend
10.6+
Tail watchdog messages.
"},{"location":"commands/watchdog_tail/#examples","title":"Examples","text":"drush watchdog:tail
. Continuously tail watchdog messages.drush watchdog:tail \"cron run successful\"
. Continuously tail watchdog messages, filtering on the string cron run successful.drush watchdog:tail --severity=Notice
. Continuously tail watchdog messages, filtering severity of notice.drush watchdog:tail --severity-min=Warning
. Continuously tail watchdog messages, filtering for a severity of warning or higher.drush watchdog:tail --type=php
. Continuously tail watchdog messages, filtering on type equals php.drush topic
and pick the first choice.Legend
12.0+
Get a value for a specific key in a YAML file.
See https://github.com/grasmash/yaml-cli for a README and bug reports.
"},{"location":"commands/yaml_get_value/#arguments","title":"Arguments","text":"drush topic
and pick the first choice.Legend
12.0+
Validates that a given YAML file has valid syntax.
See https://github.com/grasmash/yaml-cli for a README and bug reports.
"},{"location":"commands/yaml_lint/#arguments","title":"Arguments","text":"drush topic
and pick the first choice.Legend
12.0+
Unset a specific key in a YAML file.
See https://github.com/grasmash/yaml-cli for a README and bug reports.
"},{"location":"commands/yaml_unset_key/#arguments","title":"Arguments","text":"drush topic
and pick the first choice.Legend
12.0+
Update a specific key in a YAML file.
See https://github.com/grasmash/yaml-cli for a README and bug reports.
"},{"location":"commands/yaml_update_key/#arguments","title":"Arguments","text":"drush topic
and pick the first choice.Legend
12.0+
Update the value for a specific key in a YAML file.
See https://github.com/grasmash/yaml-cli for a README and bug reports.
"},{"location":"commands/yaml_update_value/#arguments","title":"Arguments","text":"drush topic
and pick the first choice.Legend
Drush is built by people like you! Please join us.
"},{"location":"contribute/CONTRIBUTING/#git-and-pull-requests","title":"Git and Pull requests","text":"13.x
branch. PR's should initially target this branch.composer run-script -l
for a list of helper scripts.composer cs
to check the project for coding style issues and run composer cbf
to fix them automatically where possible. These scripts use PHP_CodeSniffer
in background.drush topic
command.Drush's test suite (aka Unish) is based on PHPUnit. In order to maintain high quality, our tests are run on every push. See CircleCi.
"},{"location":"contribute/unish/#usage","title":"Usage","text":"git clone https://github.com/drush-ops/drush.git
cd drush
composer install
composer test
11.0+
Drush's own tests may be run within provided Docker containers via DDEV
ddev start
ddev exec drupal composer functional -- --filter testUserRole
composer unit
composer integration
composer functional
composer functional -- --filter testUserRole
composer functional -- --exclude-group slow
composer functional -- --log-junit results.xml
composer sut:si
. See composer.json for details.UNISH_DIRTY=1 composer functional -- --filter testUserRole
./drush @sut.dev status
@bootstrap full
, and it is not possible to test loading different Drush configuration files and so on. It is not possible to test argument / option parsing. The shutdown and error handlers are not installed, so PHP deprecation warnings will be evidenced in the integration tests.exec
ing the Drush executable. All functional tests therefore run in their own separate processes. The Drupal System Under Test is set up every time it is needed by any functional test. It is therefore okay if a functional test changes the state of the SUT. The codebase is re-used, so no destructive changes should be made to the code.Drush provides test traits that may be used to test your own Drush extensions. Adding the traits varies slightly depending how you package your Drush extension.
drush/drush
to your module's composer.json (require-dev
section).Once you successfully have use Drush\\TestTraits\\DrushTestTrait
in your test class, you are able to write simple tests that call your extension's commands and makes assertions against the output.
public function testMyCommand()\n {\n $this->drush('my:command', ['param'], ['flag' => 'value']);\n $this->assertOutputEquals('The parameter is \"param\" and the \"flag\" option is \"value\"');\n }\n
"},{"location":"examples/ArtCommands.php/","title":"ArtCommands.php","text":"<?php\n\nnamespace Drush\\Commands;\n\nuse Consolidation\\AnnotatedCommand\\AnnotationData;\nuse Consolidation\\AnnotatedCommand\\CommandData;\nuse Consolidation\\AnnotatedCommand\\Events\\CustomEventAwareInterface;\nuse Consolidation\\AnnotatedCommand\\Events\\CustomEventAwareTrait;\nuse Consolidation\\AnnotatedCommand\\Hooks\\HookManager;\nuse Consolidation\\OutputFormatters\\StructuredData\\RowsOfFields;\nuse Drush\\Attributes as CLI;\nuse Drush\\Style\\DrushStyle;\nuse Symfony\\Component\\Console\\Input\\InputInterface;\nuse Symfony\\Component\\Console\\Output\\OutputInterface;\n\n/**\n * Run these commands using the --include option - e.g. `drush --include=/path/to/drush/examples art sandwich`\n *\n * See [Drush Test Traits](https://github.com/drush-ops/drush/blob/12.x/docs/contribute/unish.md#about-the-test-suites) for info on testing Drush commands.\n */\n\nclass ArtCommands extends DrushCommands implements CustomEventAwareInterface\n{\n use CustomEventAwareTrait;\n\n /** @var string[] */\n protected ?array $arts;\n\n /**\n * Show a fabulous picture.\n */\n #[CLI\\Command(name: 'artwork:show', aliases: ['arts'])]\n #[CLI\\Argument(name: 'art', description: 'The name of the art to display')]\n #[CLI\\Usage(name: 'drush art sandwich', description: 'Show a marvelous picture of a sandwich with pickles.')]\n public function art($art = '')\n {\n $data = $this->getArt();\n $name = $data[$art]['name'];\n $description = $data[$art]['description'];\n $path = $data[$art]['path'];\n $msg = dt(\n 'Okay. Here is {art}: {description}',\n ['art' => $name, 'description' => $description]\n );\n $this->output()->writeln(\"\\n\" . $msg . \"\\n\");\n $this->printFile($path);\n }\n\n /**\n * Show a table of information about available art.\n */\n #[CLI\\Command(name: 'artwork:list', aliases: ['artls'])]\n #[CLI\\FieldLabels(labels: ['name' => 'Name', 'description' => 'Description', 'path' => 'Path'])]\n #[CLI\\DefaultTableFields(fields: ['name', 'description'])]\n #[CLI\\FilterDefaultField(field: 'name')]\n public function listArt($options = ['format' => 'table']): RowsOfFields\n {\n $data = $this->getArt();\n return new RowsOfFields($data);\n }\n\n /**\n * Commandfiles may also add topics. These will appear in\n * the list of topics when `drush topic` is executed.\n * To view the topic below, run `drush --include=/full/path/to/examples topic`\n */\n\n /**\n * Ruminations on the true meaning and philosophy of artwork.\n */\n #[CLI\\Command(name: 'artwork:explain')]\n #[CLI\\Topics(isTopic: true, path: __DIR__ . '/art-topic.md')]\n #[CLI\\Help(hidden: true)]\n public function ruminate(): void\n {\n self::printFile($this->commandData);\n }\n\n /**\n * Return the available built-in art. Any Drush commandfile may provide\n * more art by implementing a 'drush-art' on-event hook. This on-event\n * hook is defined in the 'findArt' method below.\n */\n #[CLI\\Hook(type: HookManager::ON_EVENT, target: 'drush-art')]\n public function builtInArt()\n {\n return [\n 'drush' => [\n 'name' => 'Drush',\n 'description' => 'The Drush logo.',\n 'path' => __DIR__ . '/art/drush-nocolor.txt',\n ],\n 'sandwich' => [\n 'name' => 'Sandwich',\n 'description' => 'A tasty meal with bread often consumed at lunchtime.',\n 'path' => __DIR__ . '/art/sandwich-nocolor.txt',\n ],\n ];\n }\n\n #[CLI\\Hook(type: HookManager::INTERACT, target: 'artwork:show')]\n public function interact(InputInterface $input, OutputInterface $output, AnnotationData $annotationData)\n {\n $io = new DrushStyle($input, $output);\n\n // If the user did not specify any artwork, then prompt for one.\n $art = $input->getArgument('art');\n if (empty($art)) {\n $data = $this->getArt();\n $selections = $this->convertArtListToKeyValue($data);\n $selection = $io->choice('Select art to display', $selections);\n $input->setArgument('art', $selection);\n }\n }\n\n #[CLI\\Hook(type: HookManager::ARGUMENT_VALIDATOR, target: 'artwork:show')]\n public function artValidate(CommandData $commandData)\n {\n $art = $commandData->input()->getArgument('art');\n $data = $this->getArt();\n if (!isset($data[$art])) {\n throw new \\Exception(dt('I do not have any art called \"{name}\".', ['name' => $art]));\n }\n }\n\n /**\n * Get a list of available artwork. Cache result for future fast access.\n */\n protected function getArt(): array\n {\n if (!isset($this->arts)) {\n $this->arts = $this->findArt();\n }\n return $this->arts;\n }\n\n /**\n * Use custom defined on-event hook 'drush-art' to find available artwork.\n */\n protected function findArt()\n {\n $arts = [];\n $handlers = $this->getCustomEventHandlers('drush-art');\n foreach ($handlers as $handler) {\n $handlerResult = $handler();\n $arts = array_merge($arts, $handlerResult);\n }\n return $arts;\n }\n\n /**\n * Given a list of artwork, convert to a 'key' => 'Name: Description' array.\n */\n protected function convertArtListToKeyValue(array $data): array\n {\n $result = [];\n foreach ($data as $key => $item) {\n $result[$key] = $item['name'] . ': ' . $item['description'];\n }\n return $result;\n }\n}\n
"},{"location":"examples/PolicyCommands.php/","title":"PolicyCommands.php","text":"<?php\n\nnamespace Drush\\Commands;\n\nuse Consolidation\\AnnotatedCommand\\CommandData;\nuse Consolidation\\AnnotatedCommand\\Hooks\\HookManager;\nuse Drush\\Attributes as CLI;\nuse Drush\\Commands\\core\\RsyncCommands;\nuse Drush\\Commands\\core\\UpdateDBCommands;\nuse Drush\\Commands\\DrushCommands;\nuse Drush\\Commands\\sql\\SqlSyncCommands;\nuse Symfony\\Component\\Console\\Input\\InputOption;\n\n/**\n * Load this commandfile using the --include option - e.g. `drush --include=/path/to/drush/examples`\n *\n * See [Drush Test Traits](https://github.com/drush-ops/drush/blob/12.x/docs/contribute/unish.md#about-the-test-suites) for info on testing Drush commands.\n */\n\nclass PolicyCommands extends DrushCommands\n{\n /**\n * Prevent catastrophic braino. Note that this file has to be local to the\n * machine that initiates the sql:sync command.\n *\n * @throws \\Exception\n */\n #[CLI\\Hook(type: HookManager::ARGUMENT_VALIDATOR, target: SqlSyncCommands::SYNC)]\n public function sqlSyncValidate(CommandData $commandData)\n {\n if ($commandData->input()->getArgument('target') == '@prod') {\n throw new \\Exception(dt('Per !file, you may never overwrite the production database.', ['!file' => __FILE__]));\n }\n }\n\n /**\n * Limit rsync operations to production site.\n */\n #[CLI\\Hook(type: HookManager::ARGUMENT_VALIDATOR, target: RsyncCommands::RSYNC)]\n public function rsyncValidate(CommandData $commandData)\n {\n if (preg_match(\"/^@prod/\", $commandData->input()->getArgument('target'))) {\n throw new \\Exception(dt('Per !file, you may never rsync to the production site.', ['!file' => __FILE__]));\n }\n }\n\n /**\n * Unauthorized may not execute updates.\n */\n #[CLI\\Hook(type: HookManager::ARGUMENT_VALIDATOR, target: UpdateDBCommands::UPDATEDB)]\n public function validateUpdateDb(CommandData $commandData)\n {\n if (!$commandData->input()->getOption('secret') == 'mysecret') {\n throw new \\Exception(dt('UpdateDb command requires a secret token per site policy.'));\n }\n }\n\n #[CLI\\Hook(type: HookManager::OPTION_HOOK, target: UpdateDBCommands::UPDATEDB)]\n #[CLI\\Option(name: 'secret', description: 'A required token else user may not run updatedb command.')]\n public function optionsetUpdateDb($options = ['secret' => self::REQ])\n {\n }\n}\n
"},{"location":"examples/SiteAliasAlterCommands.php/","title":"SiteAliasAlterCommands.php","text":"<?php\n\nnamespace Drush\\Commands;\n\nuse Consolidation\\AnnotatedCommand\\AnnotationData;\nuse Consolidation\\AnnotatedCommand\\Hooks\\HookManager;\nuse Consolidation\\SiteAlias\\SiteAliasManagerAwareInterface;\nuse Consolidation\\SiteAlias\\SiteAliasManagerAwareTrait;\nuse Drush\\Attributes as CLI;\nuse Symfony\\Component\\Console\\Input\\InputInterface;\n\n/**\n * Load this example by using the --include option - e.g. `drush --include=/path/to/drush/examples`\n */\nclass SiteAliasAlterCommands extends DrushCommands implements SiteAliasManagerAwareInterface\n{\n use SiteAliasManagerAwareTrait;\n\n /**\n * A few example alterations to site aliases.\n */\n #[CLI\\Hook(type: HookManager::PRE_INITIALIZE, target: '*')]\n public function alter(InputInterface $input, AnnotationData $annotationData)\n {\n $self = $this->siteAliasManager()->getSelf();\n if ($self->isRemote()) {\n // Always pass along ssh keys.\n if (!$self->has('ssh.options')) {\n // Don't edit the alias - edit the general config service instead.\n $this->getConfig()->set('ssh.options', '-o ForwardAgent=yes');\n }\n\n // Change the SSH user.\n $input->setOption('remote-user', 'mw2');\n\n // Test to see if specific environment really exists in wildcard\n // aliases, but only if the target is a specific host.\n $host = $self->get('host');\n if (preg_match('#\\.myserver.com$#', $host)) {\n $ip = gethostbyname($host);\n // If the return value of gethostbyname equals its input parameter,\n // that indicates failure.\n if ($host == $ip) {\n $aliasName = $self->name();\n throw new \\Exception(\"The alias $aliasName refers to an environment that does not exist.\");\n }\n }\n }\n }\n}\n
"},{"location":"examples/SyncViaHttpCommands.php/","title":"SyncViaHttpCommands.php","text":"<?php\n\nnamespace Drush\\Commands;\n\nuse Consolidation\\AnnotatedCommand\\CommandData;\nuse Consolidation\\AnnotatedCommand\\Hooks\\HookManager;\nuse Drush\\Attributes as CLI;\nuse Drush\\Commands\\DrushCommands;\nuse Drush\\Commands\\sql\\SqlSyncCommands;\nuse Drush\\Drush;\nuse Drush\\Exec\\ExecTrait;\nuse Symfony\\Component\\Filesystem\\Filesystem;\n\n/**\n * Load this commandfile using the --include option - e.g. `drush --include=/path/to/drush/examples`\n */\n\nclass SyncViaHttpCommands extends DrushCommands\n{\n /**\n * When a hook extends a command with additional options, it must\n * implement declare those option(s) in a @hook option like this one. Doing so will add\n * the option to the help text for the modified command, and will also\n * allow the new option to be specified on the command line. Without\n * this, Drush will fail with an error when a user attempts to use\n * an unknown option.\n */\n #[CLI\\Hook(type: HookManager::OPTION_HOOK, target: SqlSyncCommands::SYNC)]\n #[CLI\\Option(name: 'http-sync', description: 'Copy the database via http instead of rsync. Value is the url that the existing database dump can be found at.')]\n #[CLI\\Option(name: 'http-sync-user', description: 'Username for the protected directory containing the sql dump.')]\n #[CLI\\Option(name: 'http-sync-password', description: 'Password for the same directory.')]\n public function optionsetSqlSync()\n {\n }\n\n /**\n * During the pre hook, determine if the http-sync option has been\n * specified. If it has been, then disable the normal ssh + rsync\n * dump-and-transfer that sql-sync usually does, and transfer the\n * database dump via an http download.\n */\n #[CLI\\Hook(type: HookManager::PRE_COMMAND_HOOK, target: SqlSyncCommands::SYNC)]\n public function preSqlSync(CommandData $commandData)\n {\n $sql_dump_download_url = $commandData->input()->getOption('http-sync');\n if (!empty($sql_dump_download_url)) {\n $user = $commandData->input()->getOption('http-sync-user');\n $password = $commandData->input()->getOption('http-sync-password');\n $source_dump_file = $this->downloadFile($sql_dump_download_url, $user, $password);\n $commandData->input()->setOption('target-dump', $source_dump_file);\n $commandData->input()->setOption('no-dump', true);\n $commandData->input()->setOption('no-sync', true);\n }\n }\n\n /**\n * Downloads a file.\n *\n * Optionally uses user authentication, using either wget or curl, as available.\n */\n protected function downloadFile($url, $user = false, $password = false, $destination = false, $overwrite = true)\n {\n static $use_wget;\n if ($use_wget === null) {\n $use_wget = ExecTrait::programExists('wget');\n }\n\n $destination_tmp = drush_tempnam('download_file');\n if ($use_wget) {\n $args = ['wget', '-q', '--timeout=30'];\n if ($user && $password) {\n $args = array_merge($args, [\"--user=$user\", \"--password=$password\", '-O', $destination_tmp, $url]);\n } else {\n $args = array_merge($args, ['-O', $destination_tmp, $url]);\n }\n } else {\n $args = ['curl', '-s', '-L', '--connect-timeout 30'];\n if ($user && $password) {\n $args = array_merge($args, ['--user', \"$user:$password\", '-o', $destination_tmp, $url]);\n } else {\n $args = array_merge($args, ['-o', $destination_tmp, $url]);\n }\n }\n $process = Drush::process($args);\n $process->mustRun();\n\n if (!Drush::simulate()) {\n if (!drush_file_not_empty($destination_tmp) && $file = @file_get_contents($url)) {\n @file_put_contents($destination_tmp, $file);\n }\n if (!drush_file_not_empty($destination_tmp)) {\n // Download failed.\n throw new \\Exception(dt(\"The URL !url could not be downloaded.\", ['!url' => $url]));\n }\n }\n if ($destination) {\n $fs = new Filesystem();\n $fs->rename($destination_tmp, $destination, $overwrite);\n return $destination;\n }\n return $destination_tmp;\n }\n}\n
"},{"location":"examples/XkcdCommands.php/","title":"XkcdCommands.php","text":"<?php\n\nnamespace Drush\\Commands;\n\nuse Drush\\Attributes as CLI;\nuse Drush\\Exec\\ExecTrait;\n\n/**\n * Run these commands using the --include option - e.g. `drush --include=/path/to/drush/examples xkcd`\n *\n * For an example of a Drush extension with tests for Drush:\n * - https://github.com/drush-ops/example-drush-extension\n */\n\nclass XkcdCommands extends DrushCommands\n{\n use ExecTrait;\n\n /**\n * Retrieve and display xkcd cartoons.\n */\n #[CLI\\Command(name: 'xkcd:fetch', aliases: ['xkcd'])]\n #[CLI\\Option(name: 'search', description: 'Optional argument to retrieve the cartoons matching an index number, keyword search or \"random\". If omitted the latest cartoon will be retrieved.')]\n #[CLI\\Option(name: 'image-viewer', description: 'Command to use to view images (e.g. xv, firefox). Defaults to \"display\" (from ImageMagick).')]\n #[CLI\\Option(name: 'google-custom-search-api-key', description: 'Google Custom Search API Key, available from https://code.google.com/apis/console/. Default key limited to 100 queries/day globally.')]\n #[CLI\\Usage(name: 'drush xkcd', description: 'Retrieve and display the latest cartoon.')]\n #[CLI\\Usage(name: 'drush xkcd sandwich', description: 'Retrieve and display cartoons about sandwiches.')]\n #[CLI\\Usage(name: 'drush xkcd 123 --image-viewer=eog', description: 'Retrieve and display cartoon #123 in eog.')]\n #[CLI\\Usage(name: 'drush xkcd random --image-viewer=firefox', description: 'Retrieve and display a random cartoon in Firefox.')]\n public function fetch($search = null, $options = ['image-viewer' => 'open', 'google-custom-search-api-key' => 'AIzaSyDpE01VDNNT73s6CEeJRdSg5jukoG244ek'])\n {\n $this->doFetch($search, $options);\n }\n\n /**\n * @param $search\n * @param array $options\n * @throws \\Exception\n */\n protected function doFetch($search, array $options): void\n {\n if (empty($search)) {\n $this->startBrowser('http://xkcd.com');\n } elseif (is_numeric($search)) {\n $this->startBrowser('http://xkcd.com/' . $search);\n } elseif ($search == 'random') {\n $xkcd_response = @json_decode(file_get_contents('http://xkcd.com/info.0.json'));\n if (!empty($xkcd_response->num)) {\n $this->startBrowser('http://xkcd.com/' . rand(1, $xkcd_response->num));\n }\n } else {\n // This uses an API key with a limited number of searches per.\n $search_response = @json_decode(file_get_contents('https://www.googleapis.com/customsearch/v1?key=' . $options['google-custom-search-api-key'] . '&cx=012652707207066138651:zudjtuwe28q&q=' . $search));\n if (!empty($search_response->items)) {\n foreach ($search_response->items as $item) {\n $this->startBrowser($item->link);\n }\n } else {\n throw new \\Exception(dt('The search failed or produced no results.'));\n }\n }\n }\n}\n
"},{"location":"examples/example.drush.yml/","title":"drush.yml","text":"#\n# A minimalist Drush config file.\n# See https://www.drush.org/latest/using-drush-configuration/ for lots more documentation.\n#\n\n# Preflight configuration.\ndrush:\ninclude:\n- '${env.HOME}/.drush/commands'\n- /usr/share/drush/commands\npaths:\nconfig:\n# Load additional config files. Is silently skipped if not found. Filename must be drush.yml\n- ${env.HOME}/.drush/config/drush.yml\nalias-path:\n- '${env.HOME}/.drush/sites'\n- /etc/drush/sites\n\n# Global options.\noptions:\n# Specify the base_url that should be used when generating links.\n# uri: 'http://example.com/subdir'\n\n# Command-specific options.\ncommand:\nsql:\ndump:\noptions:\n# Uncomment to omit cache and similar tables (including during a sql:sync).\n# structure-tables-key: common\n\n# Non-options.\nssh:\n# Specify options to pass to ssh. The default is to prohibit\n# password authentication, and is included here, so you may add additional\n# parameters without losing the default configuration.\noptions: '-o PasswordAuthentication=no'\n# This string is valid for Bash shell. Override in case you need something different. See https://github.com/drush-ops/drush/issues/3816.\npipefail: 'set -o pipefail; '\n
"},{"location":"examples/example.prompt.sh/","title":"prompt.sh","text":"# -*- mode: shell-script; mode: flyspell-prog; ispell-local-dictionary: \"american\" -*-\n#\n# Example PS1 prompt.\n#\n# Note: This file does a lot, and is designed for Bash. If you want to show the\n# currently set alias in your prompt, use the first 2 values below as an example.\n\n# This section can be used for the POWERLEVEL9K theme for Oh My Zsh.\n#FILE=\"${TMPDIR:-/tmp/}/drush-env-${USER}/drush-drupal-site-$$\"\n#POWERLEVEL9K_CUSTOM_DRUSH=\"[ -r $FILE ] && cat $FILE\"\n#POWERLEVEL9K_CUSTOM_DRUSH_BACKGROUND=\"green\"\n#POWERLEVEL9K_LEFT_PROMPT_ELEMENTS=(context dir vcs custom_drush)\n\n#\n# Note that your Bash session must already have the __git_ps1 function available.\n# Typically this is provided by git-prompt.sh, see instructions for downloading\n# and including this file here:\n# https://github.com/git/git/blob/10.x/contrib/completion/git-prompt.sh\n#\n# Features:\n#\n# Displays Git repository and Drush alias status in your prompt.\n\n__drush_ps1() {\nf=\"${TMPDIR:-/tmp/}/drush-env-${USER}/drush-drupal-site-$$\"\nif [ -f $f ]\nthen\n__DRUPAL_SITE=$(cat \"$f\")\nelse\n__DRUPAL_SITE=\"$DRUPAL_SITE\"\nfi\n\n# Set DRUSH_PS1_SHOWCOLORHINTS to a non-empty value and define a\n# __drush_ps1_colorize_alias() function for color hints in your Drush PS1\n# prompt. See example.prompt.sh for an example implementation.\nif [ -n \"${__DRUPAL_SITE-}\" ] && [ -n \"${DRUSH_PS1_SHOWCOLORHINTS-}\" ]; then\n__drush_ps1_colorize_alias\n fi\n\n[[ -n \"$__DRUPAL_SITE\" ]] && printf \"${1:- (%s)}\" \"$__DRUPAL_SITE\"\n}\n\nif [ -n \"$(type -t __git_ps1)\" ] && [ \"$(type -t __git_ps1)\" = function ] && [ \"$(type -t __drush_ps1)\" ] && [ \"$(type -t __drush_ps1)\" = function ]; then\n\n# This line enables color hints in your Drush prompt. Modify the below\n# __drush_ps1_colorize_alias() to customize your color theme.\nDRUSH_PS1_SHOWCOLORHINTS=true\n\n# Git offers various prompt customization options as well as seen in\n# https://github.com/git/git/blob/10.x/contrib/completion/git-prompt.sh.\n# Adjust the following lines to enable the corresponding features:\n#\nGIT_PS1_SHOWDIRTYSTATE=true\nGIT_PS1_SHOWUPSTREAM=auto\n # GIT_PS1_SHOWSTASHSTATE=true\n# GIT_PS1_SHOWUNTRACKEDFILES=true\nGIT_PS1_SHOWCOLORHINTS=true\n\n# The following line sets your bash prompt according to this example:\n#\n# username@hostname ~/working-directory (git-branch)[@drush-alias] $\n#\n# See http://ss64.com/bash/syntax-prompt.html for customization options.\nexport PROMPT_COMMAND='__git_ps1 \"\\u@\\h \\w\" \"$(__drush_ps1 \"[%s]\") \\\\\\$ \"'\n\n# PROMPT_COMMAND is used in the example above rather than PS1 because neither\n# Git nor Drush color hints are compatible with PS1. If you don't want color\n# hints, however, and prefer to use PS1, you can still do so by commenting out\n# the PROMPT_COMMAND line above and uncommenting the PS1 line below:\n#\n# export PS1='\\u@\\h \\w$(__git_ps1 \" (%s)\")$(__drush_ps1 \"[%s]\")\\$ '\n\n__drush_ps1_colorize_alias() {\nif [[ -n ${ZSH_VERSION-} ]]; then\nlocal COLOR_BLUE='%F{blue}'\nlocal COLOR_CYAN='%F{cyan}'\nlocal COLOR_GREEN='%F{green}'\nlocal COLOR_MAGENTA='%F{magenta}'\nlocal COLOR_RED='%F{red}'\nlocal COLOR_WHITE='%F{white}'\nlocal COLOR_YELLOW='%F{yellow}'\nlocal COLOR_NONE='%f'\nelse\n# Using \\[ and \\] around colors is necessary to prevent issues with\n# command line editing/browsing/completion.\nlocal COLOR_BLUE='\\[\\e[94m\\]'\nlocal COLOR_CYAN='\\[\\e[36m\\]'\nlocal COLOR_GREEN='\\[\\e[32m\\]'\nlocal COLOR_MAGENTA='\\[\\e[35m\\]'\nlocal COLOR_RED='\\[\\e[91m\\]'\nlocal COLOR_WHITE='\\[\\e[37m\\]'\nlocal COLOR_YELLOW='\\[\\e[93m\\]'\nlocal COLOR_NONE='\\[\\e[0m\\]'\nfi\n\n# Customize your color theme below.\ncase \"$__DRUPAL_SITE\" in\n*.live|*.prod) local ENV_COLOR=\"$COLOR_RED\" ;;\n*.stage|*.test) local ENV_COLOR=\"$COLOR_YELLOW\" ;;\n*.local) local ENV_COLOR=\"$COLOR_GREEN\" ;;\n*) local ENV_COLOR=\"$COLOR_BLUE\" ;;\nesac\n\n__DRUPAL_SITE=\"${ENV_COLOR}${__DRUPAL_SITE}${COLOR_NONE}\"\n}\n\nfi\n
"},{"location":"examples/example.site.yml/","title":"site.yml","text":"#\n# A minimalist Drush site alias file.\n# See https://www.drush.org/latest/site-aliases/ for lots more documentation.\n#\n# File: self.site.yml\nlive:\nhost: www.domain.com\nuser: www-admin\nroot: /other/path/to/drupal\nuri: http://www.example.com\nssh:\noptions: '-p 100'\npaths:\ndrush-script: '/path/to/drush'\nenv-vars:\nPATH: /bin:/usr/bin:/home/www-admin/.composer/vendor/bin\nDRUPAL_ENV: live\ncommand:\nsite:\ninstall:\noptions:\nadmin-password: 'secret-secret'\nstage:\nhost: stage.domain.com\nuser: www-admin\nroot: /other/path/to/drupal\nuri: http://stage.example.com\n
"},{"location":"examples/git-bisect.example.sh/","title":"git-bisect.sh","text":"#!/usr/bin/env sh\n\n#\n# Git bisect is a helpful way to discover which commit an error\n# occurred in. This example file gives simple instructions for\n# using git bisect with Drush to quickly find erroneous commits\n# in Drush commands or Drupal modules, presuming that you can\n# trigger the error condition via Drush (e.g. using `drush php-eval`).\n#\n# Follow these simple steps:\n#\n# $ git bisect start\n# $ git bisect bad # Tell git that the current commit does not work\n# $ git bisect good bcadd5a # Tell drush that the commithash 12345 worked fine\n# $ git bisect run mytestscript.sh\n#\n# 'git bisect run' will continue to call 'git bisect good' and 'git bisect bad',\n# based on whether the script's exit code was 0 or 1, respectively.\n#\n# Replace 'mytestscript.sh' in the example above with a custom script that you\n# write yourself. Use the example script at the end of this document as a\n# guide. Replace the example command with one that calls the Drush command\n# that you would like to test, and replace the 'grep' string with a value\n# that appears when the error exists in the commit, but does not appear when\n# commit is okay.\n#\n# If you are using Drush to test Drupal or an external Drush module, use:\n#\n# $ git bisect run drush mycommand --strict=2\n#\n# This presumes that there is one or more '[warning]' or '[error]'\n# messages emitted when there is a problem, and no warnings or errors\n# when the commit is okay. Omit '--strict=2' to ignore warnings, and\n# signal failure only when 'error' messages are emitted.\n#\n# If you need to test for an error condition explicitly, to find errors\n# that do not return any warning or error log messages on their own, you\n# can use the Drush php-eval command to force an error when `myfunction()`\n# returns FALSE. Replace 'myfunction()' with the name of an appropriate\n# function in your module that can be used to detect the error condition\n# you are looking for.\n#\n# $ git bisect run drush ev 'if(!myfunction()) { return drush_set_error(\"ERR\"); }'\n#\ndrush mycommand --myoption 2>&1 | grep -q 'string that indicates there was a problem'\nif [ $? == 0 ] ; then\nexit 1\nelse\nexit 0\nfi\n
"},{"location":"examples/helloworld.script/","title":"Helloworld.script","text":"<?php\n\n//\n// This example demonstrates how to write a drush\n// script. These scripts are run with the php:script command.\n//\nuse Drush\\Drush;\n\n$this->output()->writeln(\"Hello world!\");\n$this->output()->writeln(\"The extra options/arguments to this command were:\");\n$this->output()->writeln(print_r($extra, true));\n\n//\n// We can check which site was bootstrapped via\n// the '@self' alias, which is defined only if\n// there is a bootstrapped site.\n//\n$self = Drush::aliasManager()->getSelf();;\nif (!$self->hasRoot()) {\n $this->output()->writeln('No bootstrapped site.');\n}\nelse {\n $this->output()->writeln('The following site is bootstrapped:');\n $this->output()->writeln(print_r($self->legacyRecord(), true));\n}\n
"},{"location":"generators/all/","title":"All generators","text":"Tip
Press the / key to Search for a command. Or use your browser's Find in Page feature.
Generates a composer.json file
"},{"location":"generators/composer/#examples","title":"Examples","text":"drush generate composer
. Generates a composer.json fileGenerates a controller
"},{"location":"generators/controller/#examples","title":"Examples","text":"drush generate controller
. Generates a controllerGenerates a Drush site alias file.
"},{"location":"generators/drush_alias-file/#examples","title":"Examples","text":"drush generate drush:alias-file
. Generates a Drush site alias file.Generates a Drush command file.
"},{"location":"generators/drush_command-file/#examples","title":"Examples","text":"drush generate drush:command-file
. Generates a Drush command file.Generates Drush generator
"},{"location":"generators/drush_generator/#examples","title":"Examples","text":"drush generate drush:generator
. Generates Drush generatorGenerates Symfony console command
"},{"location":"generators/drush_symfony-command/#examples","title":"Examples","text":"drush generate drush:symfony-command
. Generates Symfony console command11.0+
Generate a bundle class for a content entity.
"},{"location":"generators/entity_bundle-class/#examples","title":"Examples","text":"drush generate entity:bundle-class
. Generate a bundle class for a content entity.Generates configuration entity
"},{"location":"generators/entity_configuration/#examples","title":"Examples","text":"drush generate entity:configuration
. Generates configuration entityGenerates content entity
"},{"location":"generators/entity_content/#examples","title":"Examples","text":"drush generate entity:content
. Generates content entityGenerates a field
"},{"location":"generators/field/#examples","title":"Examples","text":"drush generate field
. Generates a fieldGenerates a configuration form
"},{"location":"generators/form_config/#examples","title":"Examples","text":"drush generate form:config
. Generates a configuration formGenerates a confirmation form
"},{"location":"generators/form_confirm/#examples","title":"Examples","text":"drush generate form:confirm
. Generates a confirmation formGenerates simple form
"},{"location":"generators/form_simple/#examples","title":"Examples","text":"drush generate form:simple
. Generates simple formGenerates a hook
"},{"location":"generators/hook/#examples","title":"Examples","text":"drush generate hook
. Generates a hookGenerates an install file
"},{"location":"generators/install-file/#examples","title":"Examples","text":"drush generate install-file
. Generates an install fileGenerates Drupal JavaScript file
"},{"location":"generators/javascript/#examples","title":"Examples","text":"drush generate javascript
. Generates Drupal JavaScript fileGenerates a layout
"},{"location":"generators/layout/#examples","title":"Examples","text":"drush generate layout
. Generates a layoutGenerates an Apache site configuration file
"},{"location":"generators/misc_apache-virtual-host/#examples","title":"Examples","text":"drush generate misc:apache-virtual-host
. Generates an Apache site configuration fileGenerates an Nginx site configuration file
"},{"location":"generators/misc_nginx-virtual-host/#examples","title":"Examples","text":"drush generate misc:nginx-virtual-host
. Generates an Nginx site configuration fileGenerates Drupal module
"},{"location":"generators/module/#examples","title":"Examples","text":"drush generate module
. Generates Drupal moduleGenerates PhpStorm metadata
"},{"location":"generators/phpstorm-meta/#examples","title":"Examples","text":"drush generate phpstorm-meta
. Generates PhpStorm metadataGenerates action plugin
"},{"location":"generators/plugin_action/#examples","title":"Examples","text":"drush generate plugin:action
. Generates action pluginGenerates block plugin
"},{"location":"generators/plugin_block/#examples","title":"Examples","text":"drush generate plugin:block
. Generates block pluginGenerates CKEditor plugin
"},{"location":"generators/plugin_ckeditor/#examples","title":"Examples","text":"drush generate plugin:ckeditor
. Generates CKEditor pluginGenerates condition plugin
"},{"location":"generators/plugin_condition/#examples","title":"Examples","text":"drush generate plugin:condition
. Generates condition pluginGenerates constraint plugin
"},{"location":"generators/plugin_constraint/#examples","title":"Examples","text":"drush generate plugin:constraint
. Generates constraint pluginGenerates entity reference selection plugin
"},{"location":"generators/plugin_entity-reference-selection/#examples","title":"Examples","text":"drush generate plugin:entity-reference-selection
. Generates entity reference selection pluginGenerates field formatter plugin
"},{"location":"generators/plugin_field_formatter/#examples","title":"Examples","text":"drush generate plugin:field:formatter
. Generates field formatter pluginGenerates field type plugin
"},{"location":"generators/plugin_field_type/#examples","title":"Examples","text":"drush generate plugin:field:type
. Generates field type pluginGenerates field widget plugin
"},{"location":"generators/plugin_field_widget/#examples","title":"Examples","text":"drush generate plugin:field:widget
. Generates field widget pluginGenerates filter plugin
"},{"location":"generators/plugin_filter/#examples","title":"Examples","text":"drush generate plugin:filter
. Generates filter pluginGenerates plugin manager
"},{"location":"generators/plugin_manager/#examples","title":"Examples","text":"drush generate plugin:manager
. Generates plugin managerGenerates menu-link plugin
"},{"location":"generators/plugin_menu-link/#examples","title":"Examples","text":"drush generate plugin:menu-link
. Generates menu-link pluginGenerates migrate destination plugin
"},{"location":"generators/plugin_migrate_destination/#examples","title":"Examples","text":"drush generate plugin:migrate:destination
. Generates migrate destination pluginGenerates migrate process plugin
"},{"location":"generators/plugin_migrate_process/#examples","title":"Examples","text":"drush generate plugin:migrate:process
. Generates migrate process pluginGenerates migrate source plugin
"},{"location":"generators/plugin_migrate_source/#examples","title":"Examples","text":"drush generate plugin:migrate:source
. Generates migrate source pluginGenerates queue worker plugin
"},{"location":"generators/plugin_queue-worker/#examples","title":"Examples","text":"drush generate plugin:queue-worker
. Generates queue worker pluginGenerates rest resource plugin
"},{"location":"generators/plugin_rest-resource/#examples","title":"Examples","text":"drush generate plugin:rest-resource
. Generates rest resource pluginGenerates views default argument plugin
"},{"location":"generators/plugin_views_argument-default/#examples","title":"Examples","text":"drush generate plugin:views:argument-default
. Generates views default argument pluginGenerates views field plugin
"},{"location":"generators/plugin_views_field/#examples","title":"Examples","text":"drush generate plugin:views:field
. Generates views field pluginGenerates views style plugin
"},{"location":"generators/plugin_views_style/#examples","title":"Examples","text":"drush generate plugin:views:style
. Generates views style pluginGenerates README file
"},{"location":"generators/readme/#examples","title":"Examples","text":"drush generate readme
. Generates README fileGenerates Drupal render element
"},{"location":"generators/render-element/#examples","title":"Examples","text":"drush generate render-element
. Generates Drupal render elementGenerates a service provider
"},{"location":"generators/service-provider/#examples","title":"Examples","text":"drush generate service-provider
. Generates a service providerGenerates an access checker service
"},{"location":"generators/service_access-checker/#examples","title":"Examples","text":"drush generate service:access-checker
. Generates an access checker serviceGenerates a breadcrumb builder service
"},{"location":"generators/service_breadcrumb-builder/#examples","title":"Examples","text":"drush generate service:breadcrumb-builder
. Generates a breadcrumb builder serviceGenerates a cache context service
"},{"location":"generators/service_cache-context/#examples","title":"Examples","text":"drush generate service:cache-context
. Generates a cache context serviceGenerates a custom Drupal service
"},{"location":"generators/service_custom/#examples","title":"Examples","text":"drush generate service:custom
. Generates a custom Drupal serviceGenerates an event subscriber
"},{"location":"generators/service_event-subscriber/#examples","title":"Examples","text":"drush generate service:event-subscriber
. Generates an event subscriberGenerates a logger service
"},{"location":"generators/service_logger/#examples","title":"Examples","text":"drush generate service:logger
. Generates a logger serviceGenerates a middleware
"},{"location":"generators/service_middleware/#examples","title":"Examples","text":"drush generate service:middleware
. Generates a middlewareGenerates a param converter service
"},{"location":"generators/service_param-converter/#examples","title":"Examples","text":"drush generate service:param-converter
. Generates a param converter serviceGenerates a path processor service
"},{"location":"generators/service_path-processor/#examples","title":"Examples","text":"drush generate service:path-processor
. Generates a path processor serviceGenerates a request policy service
"},{"location":"generators/service_request-policy/#examples","title":"Examples","text":"drush generate service:request-policy
. Generates a request policy serviceGenerates a response policy service
"},{"location":"generators/service_response-policy/#examples","title":"Examples","text":"drush generate service:response-policy
. Generates a response policy serviceGenerates a route subscriber
"},{"location":"generators/service_route-subscriber/#examples","title":"Examples","text":"drush generate service:route-subscriber
. Generates a route subscriberGenerates a theme negotiator
"},{"location":"generators/service_theme-negotiator/#examples","title":"Examples","text":"drush generate service:theme-negotiator
. Generates a theme negotiatorGenerates Twig extension service
"},{"location":"generators/service_twig-extension/#examples","title":"Examples","text":"drush generate service:twig-extension
. Generates Twig extension serviceGenerates a uninstall validator service
"},{"location":"generators/service_uninstall-validator/#examples","title":"Examples","text":"drush generate service:uninstall-validator
. Generates a uninstall validator serviceGenerates Drupal SDC theme component
"},{"location":"generators/single-directory-component/#examples","title":"Examples","text":"drush generate single-directory-component
. Generates Drupal SDC theme componentGenerates a browser based test
"},{"location":"generators/test_browser/#examples","title":"Examples","text":"drush generate test:browser
. Generates a browser based testGenerates a kernel based test
"},{"location":"generators/test_kernel/#examples","title":"Examples","text":"drush generate test:kernel
. Generates a kernel based testGenerates a nightwatch test
"},{"location":"generators/test_nightwatch/#examples","title":"Examples","text":"drush generate test:nightwatch
. Generates a nightwatch testGenerates a unit test
"},{"location":"generators/test_unit/#examples","title":"Examples","text":"drush generate test:unit
. Generates a unit testGenerates a test that supports JavaScript
"},{"location":"generators/test_webdriver/#examples","title":"Examples","text":"drush generate test:webdriver
. Generates a test that supports JavaScriptGenerates Drupal theme
"},{"location":"generators/theme/#examples","title":"Examples","text":"drush generate theme
. Generates Drupal themeGenerates Drupal theme-settings.php file
"},{"location":"generators/theme_settings/#examples","title":"Examples","text":"drush generate theme:settings
. Generates Drupal theme-settings.php fileGenerates a breakpoints yml file
"},{"location":"generators/yml_breakpoints/#examples","title":"Examples","text":"drush generate yml:breakpoints
. Generates a breakpoints yml fileGenerates a links.action yml file
"},{"location":"generators/yml_links_action/#examples","title":"Examples","text":"drush generate yml:links:action
. Generates a links.action yml fileGenerates links.contextual yml file
"},{"location":"generators/yml_links_contextual/#examples","title":"Examples","text":"drush generate yml:links:contextual
. Generates links.contextual yml fileGenerates a links.menu yml file
"},{"location":"generators/yml_links_menu/#examples","title":"Examples","text":"drush generate yml:links:menu
. Generates a links.menu yml fileGenerates a links.task yml file
"},{"location":"generators/yml_links_task/#examples","title":"Examples","text":"drush generate yml:links:task
. Generates a links.task yml fileGenerates a migration yml file
"},{"location":"generators/yml_migration/#examples","title":"Examples","text":"drush generate yml:migration
. Generates a migration yml fileGenerates module libraries yml file
"},{"location":"generators/yml_module-libraries/#examples","title":"Examples","text":"drush generate yml:module-libraries
. Generates module libraries yml fileGenerates a permissions yml file
"},{"location":"generators/yml_permissions/#examples","title":"Examples","text":"drush generate yml:permissions
. Generates a permissions yml fileGenerates a routing yml file
"},{"location":"generators/yml_routing/#examples","title":"Examples","text":"drush generate yml:routing
. Generates a routing yml fileGenerates a services yml file
"},{"location":"generators/yml_services/#examples","title":"Examples","text":"drush generate yml:services
. Generates a services yml fileGenerates theme libraries yml file
"},{"location":"generators/yml_theme-libraries/#examples","title":"Examples","text":"drush generate yml:theme-libraries
. Generates theme libraries yml filedrush:
@@ -5485,7 +5485,7 @@ Misc&par
Last update:
- March 15, 2023
+ May 31, 2024