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.
Post support requests to Drupal Answers. Tag question with drush.
Report bugs and request features in the GitHub Drush Issue Queue.
Use pull requests (PRs) to contribute to Drush. Guidelines.
"},{"location":"#faq","title":"FAQ","text":""},{"location":"#what-does-drush-stand-for","title":"What does Drush stand for?","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.
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.
PHP8 AttributeAnnotation
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
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.
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.
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.
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.
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.
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.
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.
Drush 12 expects commandfiles to use a create() method to inject Drupal and Drush dependencies. Prior versions used a drush.services.yml file which is now deprecated and will be removed in Drush 13.
Drush 12 expects all commandfiles in the <module-name>/Drush/<Commands|Generators> directory. The Drush subdirectory is a new requirement.
Creating a new Drush command is easy. Follow the steps below.
Run drush generate drush:command-file.
Drush will prompt for the machine name of the module that should \"own\" the file. The module selected must already exist and be enabled. Use drush generate module to create a new module.
Drush will then report that it created a commandfile. Edit as needed.
Use the classes for the core Drush commands at /src/Commands as inspiration and documentation.
See the dependency injection docs for interfaces you can implement to gain access to Drush config, Drupal site aliases, etc. Also note the create() method for injecting Drupal or Drush dependencies.
Write PHPUnit tests based on Drush Test Traits.
"},{"location":"commands/#attributes-or-annotations","title":"Attributes or Annotations","text":"
The following are both valid ways to declare a command:
PHP8 AttributesAnnotations
use 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
A commandfile that will only be used on PHP8+ should use PHP Attributes instead of Annotations.
See Attributes provided by Drush core. Custom code can add additional attributes.
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:
The generator class namespace, relative to base namespace, should be Drupal\\<module-name>\\Drush\\CommandInfoAlterers and the class file should be located under the src/Drush/CommandInfoAlterers directory.
The filename must have a name like FooCommandInfoAlterer.php. The prefix Foo can be whatever string you want. The file must end in CommandInfoAlterer.php.
The class must implement the \\Consolidation\\AnnotatedCommand\\CommandInfoAltererInterface.
Implement the alteration logic in the alterCommandInfo() method.
Along with the alter code, it's strongly recommended to log a debug message explaining what exactly was altered. This makes things easier on others who may need to debug the interaction of the alter code with other modules. Also it's a good practice to inject the the logger in the class constructor.
For an example, see WootCommandInfoAlterer provided by the testing 'woot' module.
Such commands are auto-discovered by their class PSR4 namespace and class/file name suffix. Drush will auto-discover commands if:
The commands class is PSR4 auto-loadable.
The commands class namespace, relative to base namespace, is Drush\\Commands. For instance, if a Drush command provider third party library maps this PSR4 autoload entry:
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.
The class and file name ends with *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.
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
The filename must be have a name like Commands/ExampleCommands.php
The prefix Example can be whatever string you want.
The file must end in Commands.php
The directory above Commands must be one of:
A Folder listed in the 'include' option. Include may be provided via config or via CLI.
../drush, /drush or /sites/all/drush. These paths are relative to Drupal root.
"},{"location":"config-exporting/","title":"Exporting and Importing Configuration","text":"
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 supports excluding development modules from enabling on higher environments.
See Config Split module for more advanced needs.
"},{"location":"cron/","title":"Running Drupal cron tasks from Drush","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.
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).
"},{"location":"cron/#setting-the-path","title":"Setting the PATH","text":"
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).
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.
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.
"},{"location":"dependency-injection/#types-of-injection","title":"Types of Injection","text":"
There are two ways that a class can receive its dependencies. One is called \u201cconstructor injection\u201d, and the other is called \u201csetter injection\u201d.
Example of constructor injection:
public function __construct(DependencyType $service)\n {\n $this->service = $service;\n }\n
Example of setter injection:
public function setService(DependencyType $service)\n {\n $this->service = $service;\n }\n
The code that is responsible for providing the dependencies a class needs is usually an object called the dependency injection container."},{"location":"dependency-injection/#create-method","title":"create() method","text":"
11.6+
Tip
Drush 11 and prior required dependency injection via a drush.services.yml file. This approach is deprecated in Drush 12 and will be removed in Drush 13.
Drush command files can inject services by adding a create() method to the commandfile. See creating commands for instructions on how to use the Drupal Code Generator to create a simple command file starter. A create() method and a 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(ContainerInterface $container, DrushContainer $drush): 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. Drush's approach mimics Drupal's blocks, forms, and controllers.
Note that if you do not need to pull any services from the Drush container, then you may omit the second parameter to the create() method.
12.0+ Drush commands that need to be instantiated prior to bootstrap may do so by utilizing the createEarly() static factory. This method looks and functions exacty like the create() static factory, except it is only passed the Drush container. The Drupal container is not available to command handlers that use createEarly().
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.
Inflection is deprecated in Drush 12; use create() or createEarly() instead. Some classes are no longer available for inflection in Drush 12, and more (or potentially all) may be removed in Drush 13.
Drush will also inject dependencies that it provides using a technique called inflection. Inflection is a kind of dependency injection that works by way of a set of provided inflection interfaces, one for each available service. Each of these interfaces will define one or more setter methods (usually only one); these will automatically be called by Drush when the commandfile object is instantiated. The command only needs to implement this method and save the provided object in a class field. There is usually a corresponding trait that may be included via a use statement to fulfill this requirement.
For example:
<?php\nnamespace Drupal\\my_module\\Commands;\n\nuse Drush\\Commands\\DrushCommands;\nuse Consolidation\\OutputFormatters\\StructuredData\\ListDataFromKeys;\nuse Consolidation\\SiteAlias\\SiteAliasManagerAwareInterface;\nuse Consolidation\\SiteAlias\\SiteAliasManagerAwareTrait;\n\nclass MyModuleCommands extends DrushCommands implements SiteAliasManagerAwareInterface\n{\n use SiteAliasManagerAwareTrait;\n\n /**\n * Prints the current alias name and info.\n */\n #[CLI\\Command(name: 'mymodule:myAlias')]\n public function myAlias(): ListDataFromKeys \n {\n $selfAlias = $this->siteAliasManager()->getSelf();\n $this->logger()->success(\u2018The current alias is {name}\u2019, [\u2018name\u2019 => $selfAlias]);\n return new ListDataFromKeys($aliasRecord->export());\n }\n}\n
All Drush command files extend DrushCommands. DrushCommands implements ConfigAwareInterface, IOAwareInterface, LoggerAwareInterface, which gives access to $this->getConfig(), $this->logger() and other ways to do input and output. See the IO documentation for more information.
Any additional services that are desired must be injected by implementing the appropriate inflection interface.
Additional Interfaces:
SiteAliasManagerAwareInterface: The site alias manager allows alias records to be obtained.
CustomEventAwareInterface: Allows command files to define and fire custom events that other command files can hook.
Note that although the autoloader and Drush dependency injection container is available and may be injected into your command file if needed, this should be avoided. Favor using services that can be injected from Drupal or Drush. Some of the objects in the container are not part of the Drush public API, and may not maintain compatibility in minor and patch releases.
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:
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.).
Drush 11 and prior required generators to define a drush.services.yml file. This is no longer used with Drush 12+ generators. See create() method 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.
Drupal modules may supply their own Generators, just like they can supply Commands.
See Woot module, which Drush uses for testing. Specifically,
Write a class similar to ExampleGenerator. Implement your custom logic in the generate() method. Typically this class is placed under the src/Drush/Generators directory.
Add a .twig file to the same directory. This template specifies what gets output from the generator.
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:
The generator class should be PSR4 auto-loadable.
The generator class namespace, relative to base namespace, should be Drush\\Generators. For instance, if a Drush generator provider third party library maps this PSR4 autoload entry:
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.
The filename must have a name like FooGenerator.php. The prefix 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.
Documentation about available hooks.
To see how core commands implement a hook, you can search the Drush source code.
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.
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. It is required that Drupal sites be built using Composer, with Drush listed as a dependency. See recommended-project (Drush must be added). If your Composer project doesn't yet depend on Drush, run composer require drush/drush to add it.
Execution. Change your working directory to your project root, and call Drush via vendor/bin/drush. To make this easier, append ./vendor/bin to the end of your $PATH; this allows you to call Drush via drush once your working directory is set. If you only have only one Drupal codebase on your system, you may put /path/to/vendor/bin/drush in your $PATH; if you do this, then it is not necessary to set your working directory before calling Drush.
Completion. Optional. Append to .bashrc or equivalent for ZSH or Fish shell. Run drush completion --help for more details.
Multiple Codebases. Optional. If using the bash shell, consider installing the fd project, a small set of scripts that make it easier to switch between different project directories quickly, with type completion.
Note
See Usage for details on using Drush.
To use a non-default PHP, edit ~/.bashrc so that the desired PHP is in front of your $PATH. If that is not desirable, you can change your PATH for just one request: PATH=/path/to/php:$PATH drush status ...`
To use a custom php.ini for Drush requests, see this comment.
See our guide on porting commandfiles from Drush 8 to later versions. Also note that alias and config files use a new .yml format in Drush 10+.
"},{"location":"install/#drupal-compatibility","title":"Drupal Compatibility","text":"Drush Version PHP Version End Of Life Drupal versions 7 8 9 10 Drush 12 8.1+ TBD \u2705 Drush 11 7.4+ Nov 2023 \u2705 \u2713 Drush 10 7.1+ (not 8) Jan 2022 \u2713 \u2713 Drush 9 5.6+ May 2020 \u2713 Drush 8 5.4.5+ Jan 2025 \u2705 \u2713\ufe0f Drush 7 5.3.0+ Jul 2017 \u2713 Drush 6 5.3.0+ Dec 2015 \u2713 Drush 5 5.2.0+ May 2015 \u2713 Legend \u2705 Supported and recommended \u2713 Compatible but no longer supported"},{"location":"io/","title":"Input / Output","text":"
The Input object holds information about the request such option and argument values. You may need to this information when coding a hook implementation. You don't need this object in your command callback method since these values are passed as parameters.
The Output object is rarely needed. Instead, return an object that gets formatted via the Output Formatter system. If you want to send additional output, use the io system (see below).
If you need to ask the user a question, or print non-object content, use the io() system.
A command callback gets access via $this->io().
The main methods for gathering user input are $this->io()->choice() and $this->io()->confirm().
You may use any of the methods described in the Symfony Style docs.
"},{"location":"migrate/","title":"Defining and running migrations","text":"
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.
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.
Output formats may be used to select the data type used to print the output. For example, many commands allow the user to select between a human-readable table, or various machine-parsable formats such as yaml and json.
Output fields may be used to select and order the data columns.
Output filters may be used to limit which data rows are printed based on logical expressions.
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
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.
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:
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:
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:
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.
"},{"location":"output-formats-filters/#comparison-of-filters-with-grep","title":"Comparison of Filters with Grep","text":"
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 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.
An informative example is the browse command
A commandfile gets access to the SAM by implementing the SiteAliasManagerAwareInterface and useing the SiteAliasManagerAwareTrait trait. Then you gain access via $this->siteAliasManager().
If an alias was used for the current request, it is available via $this->siteAliasManager()->getself().
The SAM generally deals in SiteAlias objects. That is how any given site alias is represented. See its methods for determining things like whether the alias points to a local host or remote host.
Site alias docs.
Dynamically alter site aliases.
The SAM is also available for as a standalone Composer project. More information available in the README there.
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:
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: The fully-qualified domain name of the remote system hosting the Drupal instance. The 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: The username to log in as when using ssh or docker. If each user has to use own username, you can create an environment variable which holds the value, and reference via ${env.PROJECT_SSH_USER} (for example). Or you may omit the user item and specify a user in the ~/.ssh/config file.
root: The Drupal root; must not be specified as a relative path.
uri: The value of --uri should always be the same as when the site is being accessed from a web browser (e.g. http://example.com)
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:
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:
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.
"},{"location":"site-aliases/#additional-site-alias-options","title":"Additional Site Alias Options","text":"
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: When specified, Drush executes via docker-compose exec rather than ssh.
service: the name of the container to run on.
exec:
options: Options for the exec subcommand.
os: The operating system of the remote server. Valid values are Windows and Linux. Set this value for all remote aliases where the remote's OS differs from the local. This is especially relevant for the sql:sync command.
ssh: Contains settings used to control how ssh commands are generated when running remote commands.
options: Contains additional commandline options for the ssh command itself, e.g. -p 100
tty: Usually, Drush will decide whether or not to create a tty (via the 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.
paths: An array of aliases for common rsync targets. Relative aliases are always taken from the Drupal root.
files: Path to files directory. This will be looked up if not specified.
drush-script: Path to the remote Drush command.
command: These options will only be set if the alias is used with the specified command. In the advanced example below, the option --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
env-vars: An array of key / value pairs that will be set as environment variables.
"},{"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:
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.
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-and-other-transports","title":"Docker Compose and other transports","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/#example-of-rsync-with-exclude-paths","title":"Example of rsync with exclude-paths","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.
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.
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
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:
Drupal site folder (e.g. sites/{example.com}/drush.yml).
sites/all/drush, WEBROOT/drush, or PROJECTROOT/drush.
In any location, as specified by the --config option.
User's .drush folder (i.e. ~/.drush/drush.yml).
System-wide configuration folder (e.g. /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.
"},{"location":"using-drush-configuration/#config-examples","title":"Config examples","text":""},{"location":"using-drush-configuration/#specify-config-files-to-load","title":"Specify config files to load","text":"
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
The value may be path to a file, or to a directory containing drush.yml file(s).
View discovered config paths: drush status --fields=drush-conf --format=yaml
"},{"location":"using-drush-configuration/#specify-folders-to-search-for-drush-command-files","title":"Specify folders to search for Drush command files.","text":"
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.
"},{"location":"using-drush-configuration/#specify-the-folders-to-search-for-drush-alias-files-siteyml","title":"Specify the folders to search for Drush alias files (*.site.yml).","text":"
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.
- 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.
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
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
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
If you are authoring a commandfile and wish to access the user's configuration, see Command Authoring.
Setting boolean options broke with Symfony 3. This will be fixed in a future release.
Version-specific configuration. Limit the version of Drush that will load a configuration file by placing the Drush major version number in the filename, e.g. drush10.yml.
The Drush configuration system has been factored out of Drush and shared with the world at https://github.com/consolidation/config. Feel free to use it for your projects. Lots more usage information is there.
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.
--destination=DESTINATION. The full path and filename in which the archive should be stored. If omitted, it will be saved to the drush-backups directory.
--overwrite. Overwrite destination file if exists.
--description=DESCRIPTION. Describe the archive contents.
--tags=TAGS. Add tags to the archive manifest. Delimit several by commas.
--generator=GENERATOR. The generator name to store in the MANIFEST.yml file. The default is \"Drush archive-dump\".
--generatorversion=GENERATORVERSION. The generator version number to store in the MANIFEST file. The default is Drush version.
--exclude-code-paths=EXCLUDE-CODE-PATHS. Comma-separated list of paths (or regular expressions matching paths) to exclude from the code archive.
--skip-tables-key=SKIP-TABLES-KEY. A key in the $skip_tables array. @see Site aliases
--structure-tables-key=STRUCTURE-TABLES-KEY. A key in the $structure_tables array. @see Site aliases
--tables-key=TABLES-KEY. A key in the $tables array.
--skip-tables-list=SKIP-TABLES-LIST. A comma-separated list of tables to exclude completely.
--structure-tables-list=STRUCTURE-TABLES-LIST. A comma-separated list of tables to include for structure, but not data.
--tables-list=TABLES-LIST. A comma-separated list of tables to transfer.
--database[=DATABASE]. The DB connection key if using multiple connections in settings.php. [default: default]
--db-url=DB-URL. A Drupal 6 style database URL. For example mysql://root:pass@localhost:port/dbname
--target[=TARGET]. The name of a target within the specified database connection. [default: default]
--show-passwords. Show password on the CLI. Useful for debugging.
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 directory
drush 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.
[path]. The full path to a single archive file (*.tar.gz) or a directory with components to import. * May contain the following components generated by archive:dump command: * 1) code (\"code\" directory); * 2) database dump file (\"database/database.sql\" file); * 3) Drupal files (\"files\" directory).
[site]. Destination site alias. Defaults to @self.
--destination-path[=DESTINATION-PATH]. The base path to restore the code/files into.
--overwrite. Overwrite files if exists when un-compressing an archive.
--site-subdir[=SITE-SUBDIR]. Site subdirectory to put settings.local.php into. [default: default]
--setup-database-connection[=SETUP-DATABASE-CONNECTION]. Sets up the database connection in settings.local.php file if either --db-url option or set of specific --db- options are provided. [default: 1*]
--code. Import code.
--code-source-path[=CODE-SOURCE-PATH]. Import code from specified directory. Has higher priority over \"path\" argument.
--files. Import Drupal files.
--files-source-path[=FILES-SOURCE-PATH]. Import Drupal files from specified directory. Has higher priority over \"path\" argument.
--files-destination-relative-path[=FILES-DESTINATION-RELATIVE-PATH]. Import Drupal files into specified directory relative to Composer root.
--db. Import database.
--db-source-path[=DB-SOURCE-PATH]. Import database from specified dump file. Has higher priority over \"path\" argument.
--format[=FORMAT]. Format the result data. Available formats: csv,json,list,null,php,print-r,string,table,tsv,var_dump,var_export,xml,yaml [default: json]
--fields=FIELDS. Available fields: Cache ID (cid), Data (data), Created (created), Expire (expire), Tags (tags), Checksum (checksum), Valid (valid)
--field=FIELD. Select just one field, and force format to string.
The *%command.name% command dumps the shell completion script required to use shell autocompletion (currently, bash, fish, zsh completion are supported).
Dump 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
--source=SOURCE. An arbitrary directory that holds the configuration files.
--partial. Allows for partial config imports from the source directory. Only updates and new configs will be processed with this flag (missing configs will not be deleted). No config transformation happens.
--safe. Validate that there are no git uncommitted changes before proceeding
--runner[=RUNNER]. Where to run the rsync command; defaults to the local site. Can also be source or destination.
--format[=FORMAT]. Format the result data. Available formats: csv,json,list,null,php,print-r,string,table,tsv,var_dump,var_export,xml,yaml [default: null]
--fields=FIELDS. Available fields: Path (path)
--field=FIELD. Select just one field, and force format to string.
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.
--input-format[=INPUT-FORMAT]. Format to parse the object. Recognized values: string, yaml. Since JSON is a subset of YAML, $value may be in JSON format. [default: string]
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.
--state[=STATE]. A comma-separated list of states to filter results. [default: Only in DB,Only in sync dir,Different]
--prefix=PREFIX. The config prefix. For example, system. No prefix will return all names in the system.
--format=FORMAT. Format the result data. Available formats: csv,json,list,null,php,print-r,sections,string,table,tsv,var_dump,var_export,xml,yaml [default: table]
--fields=FIELDS. Available fields: Name (name), State (state)
--field=FIELD. Select just one field, and force format to string.
--filter[=FILTER]. Filter output based on provided expression
--format[=FORMAT]. Format the result data. Available formats: csv,json,list,null,php,print-r,sections,string,table,tsv,var_dump,var_export,xml,yaml [default: table]
--severity[=SEVERITY]. Only show status report messages with a severity greater than or equal to the specified value. [default: -1]
--ignore[=IGNORE]. Comma-separated list of requirements to remove from output. Run with --format=yaml to see key values to use.
--fields=FIELDS. Available fields: Title (title), Severity (severity), SID (sid), Description (description), Summary (value)
--field=FIELD. Select just one field, and force format to string.
--filter[=FILTER]. Filter output based on provided expression
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 @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 --.
--project=PROJECT. A comma delimited list of projects. Their paths will be added to path-aliases section.
--format[=FORMAT]. Format the result data. Available formats: csv,json,list,null,php,print-r,string,table,tsv,var_dump,var_export,xml,yaml [default: table]
--fields=FIELDS. Available fields: Drupal version (drupal-version), Site URI (uri), DB driver (db-driver), DB hostname (db-hostname), DB port (db-port), DB username (db-username), DB password (db-password), DB name (db-name), Database (db-status), Drupal bootstrap (bootstrap), Default theme (theme), Admin theme (admin-theme), PHP binary (php-bin), PHP config (php-conf), PHP OS (php-os), PHP version (php-version), Drush script (drush-script), Drush version (drush-version), Drush temp (drush-temp), Drush configs (drush-conf), Drush aliases (drush-alias-files), Alias search paths (alias-searchpaths), Install profile (install-profile), Drupal root (root), Drupal Settings (drupal-settings-file), Site path (site-path), Site path (site), Themes path (themes), Modules path (modules), Files, Public (files), Files, Private (private), Files, Temp (temp), Drupal config (config-sync), Files, Public (files-path), Files, Temp (temp-path), Other paths (%paths)
--field=FIELD. Select just one field, and force format to string.
--format=FORMAT. Format the result data. Available formats: csv,json,list,null,php,print-r,sections,string,table,tsv,var_dump,var_export,xml,yaml [default: table]
--fields=FIELDS. Available fields: Module (module), Hook (hook), Description (description)
--field=FIELD. Select just one field, and force format to string.
--filter[=FILTER]. Filter output based on provided expression
--format[=FORMAT]. Format the result data. Available formats: csv,json,list,null,php,print-r,sections,string,table,tsv,var_dump,var_export,xml,yaml [default: table]
--show-machine-names. Show machine names instead of labels in option lists.
--fields=FIELDS. Available fields: Label (label), Description (description), Field name (field_name), Field type (field_type), Required (required), Translatable (translatable), Cardinality (cardinality), Default value (default_value), Default value callback (default_value_callback), Allowed values (allowed_values), Allowed values function (allowed_values_function), Selection handler (handler), Target bundles (target_bundles)
--field=FIELD. Select just one field, and force format to string.
--filter[=FILTER]. Filter output based on provided expression
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.
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.
--format[=FORMAT]. Format the result data. Available formats: csv,json,list,null,php,print-r,tsv,var_dump,var_export,xml,yaml [default: yaml]
--field-type=FIELD-TYPE. Applicable field type.
--fields=FIELDS. Available fields: ID (id), Label (label), Default Settings (default_settings), Field types (field_types), Settings (settings), Class (class), Provider (provider) [default: id label default_settings field_types]
--field=FIELD. Select just one field, and force format to string.
--filter[=FILTER]. Filter output based on provided expression
--format[=FORMAT]. Format the result data. Available formats: csv,json,list,null,php,print-r,sections,string,table,tsv,var_dump,var_export,xml,yaml [default: table]
--show-machine-names. Show machine names instead of labels in option lists.
--fields=FIELDS. Available fields: Label (label), Description (description), Field name (field_name), Field type (field_type), Required (required), Translatable (translatable), Cardinality (cardinality), Default value (default_value), Default value callback (default_value_callback), Allowed values (allowed_values), Allowed values function (allowed_values_function), Selection handler (handler), Target bundles (target_bundles)
--field=FIELD. Select just one field, and force format to string.
--filter[=FILTER]. Filter output based on provided expression
--format[=FORMAT]. Format the result data. Available formats: csv,json,list,null,php,print-r,tsv,var_dump,var_export,xml,yaml [default: yaml]
--field-type=FIELD-TYPE. Applicable field type.
--fields=FIELDS. Available fields: ID (id), Label (label), Default Settings (default_settings), Field types (field_types), Settings (settings), Class (class), Provider (provider) [default: id label default_settings field_types]
--field=FIELD. Select just one field, and force format to string.
--filter[=FILTER]. Filter output based on provided expression
--format[=FORMAT]. Format the result data. Available formats: csv,json,list,null,php,print-r,string,tsv,var_dump,var_export,xml,yaml [default: helpcli]
--format[=FORMAT]. Format the result data. Available formats: csv,json,list,null,php,print-r,tsv,var_dump,var_export,xml,yaml [default: json]
--fields=FIELDS. Limit output to only the listed elements. Name top-level elements by key, e.g. \"--fields=name,date\", or use dot notation to select a nested element, e.g. \"--fields=a.b.c as example\".
--field=FIELD. Select just one field, and force format to string.
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.
--type=TYPE. String types to include, defaults to not-customized. Recognized values: not-customized, customized
--override=OVERRIDE. Whether and how imported strings will override existing translations. Defaults to the Import behavior configured in the admin interface. Recognized values: none, customized, not-customized, all
--type[=TYPE]. String types to include, defaults to all types. Recognized values: not-customized, customized, not-translated [default: not-customized]
--override=OVERRIDE. Whether and how imported strings will override existing translations. Defaults to the Import behavior configured in the admin interface. Recognized values: none, customized, not-customized, all
--autocreate-language. Create the language in addition to import.
--format[=FORMAT]. Format the result data. Available formats: csv,json,list,null,php,print-r,sections,string,table,tsv,var_dump,var_export,xml,yaml [default: table]
--fields=FIELDS. Available fields: Field name (machine_name), Description (description) [default: machine_name description]
--field=FIELD. Select just one field, and force format to string.
--tag=TAG. A comma-separated list of migration tags to import
--limit=LIMIT. Limit on the number of items to process in each migration
--feedback=FEEDBACK. Frequency of progress messages, in items processed
--idlist=IDLIST. Comma-separated list of IDs to import. As an ID may have more than one column, concatenate the columns with the colon ':' separator
--update. In addition to processing unprocessed items from the source, update previously-imported items with the current data
--force. Force an operation to run, even if all dependencies are not satisfied
--execute-dependencies. Execute all dependent migrations first
--timestamp. Show progress ending timestamp in progress messages
--total. Show total processed item number in progress messages
--progress[=PROGRESS]. Show progress bar [default: 1]
--delete. Delete destination records missed from the source. Not compatible with --limit and --idlist options, and high_water_property source configuration key.
migrate:messages article. Show all messages for the article migration
migrate: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\"].
--idlist=IDLIST. Comma-separated list of IDs to import. As an ID may have more than one column, concatenate the columns with the colon ':' separator
--format[=FORMAT]. Format the result data. Available formats: csv,json,list,null,php,print-r,sections,string,table,tsv,var_dump,var_export,xml,yaml [default: table]
--tag=TAG. A comma-separated list of migration tags to list. If only --tag is provided, all tagged migrations will be listed, grouped by tags.
--format[=FORMAT]. Format the result data. Available formats: csv,json,list,null,php,print-r,sections,string,table,tsv,var_dump,var_export,xml,yaml [default: table]
--fields=FIELDS. Available fields: Migration ID (id), Status (status), Total (total), Imported (imported), Needing update (needing_update), Unprocessed (unprocessed), Last Imported (last_imported) [default: id status total imported unprocessed last_imported]
--field=FIELD. Select just one field, and force format to string.
--filter[=FILTER]. Filter output based on provided expression
Build a Markdown document for each Drush command/generator that is available on a site.
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.
$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 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.
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.
--format[=FORMAT]. Format the result data. Available formats: csv,json,list,null,php,print-r,sections,string,table,tsv,var_dump,var_export,xml,yaml [default: table]
--type[=TYPE]. Only show extensions having a given type. Choices: module, theme. [default: module,theme]
--status[=STATUS]. Only show extensions having a given status. Choices: enabled or disabled. [default: enabled,disabled]
--package=PACKAGE. Only show extensions having a given project packages (e.g. Development).
--core. Only show extensions that are in Drupal core.
--no-core. Only show extensions that are not provided by Drupal core.
--fields=FIELDS. Available fields: Package (package), Project (project), Name (display_name), Name (name), Type (type), Path (path), Status (status), Version (version)
--field=FIELD. Select just one field, and force format to string.
--filter[=FILTER]. Filter output based on provided expression
Check Drupal Composer packages for pending security updates.
This uses the Drupal security advisories package to determine if updates are available. An exit code of 3 indicates that the check completed, and insecure packages were found.
--format=FORMAT. Format the result data. Available formats: csv,json,list,null,php,print-r,sections,string,table,tsv,var_dump,var_export,xml,yaml [default: table]
--fields=FIELDS. Available fields: Name (name), Installed Version (version)
--field=FIELD. Select just one field, and force format to string.
--filter[=FILTER]. Filter output based on provided expression
--format[=FORMAT]. Format the result data. Available formats: csv,json,list,null,php,print-r,sections,string,table,tsv,var_dump,var_export,xml,yaml [default: table]
--fields=FIELDS. Available fields: Queue (queue), Items (items), Class (class)
--field=FIELD. Select just one field, and force format to string.
--filter[=FILTER]. Filter output based on provided expression
Display a list of all roles defined on the system.
If a role name is provided as an argument, then all of the permissions of that role will be listed. If a permission name is provided as an option, then all of the roles that have been granted that permission will be listed.
--format[=FORMAT]. Format the result data. Available formats: csv,json,list,null,php,print-r,sections,string,table,tsv,var_dump,var_export,xml,yaml [default: yaml]
--fields=FIELDS. Available fields: ID (rid), Role Label (label), Permissions (perms)
--field=FIELD. Select just one field, and force format to string.
--filter[=FILTER]. Filter output based on provided expression
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.
--format[=FORMAT]. Format the result data. Available formats: csv,json,list,null,php,print-r,tsv,var_dump,var_export,xml,yaml [default: yaml]
--fields=FIELDS. Limit output to only the listed elements. Name top-level elements by key, e.g. \"--fields=name,date\", or use dot notation to select a nested element, e.g. \"--fields=a.b.c as example\".
--field=FIELD. Select just one field, and force format to string.
--filter[=FILTER]. Filter output based on provided expression
drush si demo_umami --locale=da. (Re)install using the Umami install profile. Set default language to Danish.
drush si --db-url=mysql://root:pass@localhost:port/dbname. Install using the specified DB params.
drush si --db-url=sqlite://sites/example.com/files/.ht.sqlite. Install using SQLite
drush 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.
[profile].... An install profile name. Defaults to standard unless an install profile is marked as a distribution. Additional info for the install profile may also be provided with additional arguments. The key is in the form [form name].[parameter name]
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.
--result-file=RESULT-FILE. Save to a file. The file should be relative to Drupal root. If --result-file is provided with the value 'auto', a date-based filename will be created under ~/drush-backups directory.
--create-db. Omit DROP TABLE statements. Used by Postgres and Oracle only.
--data-only. Dump data without statements to create any of the schema.
--ordered-dump. Order by primary key and add line breaks for efficient diffs. Slows down the dump. Mysql only.
--gzip. Compress the dump using the gzip program which must be in your $PATH.
--extra=EXTRA. Add custom arguments/options when connecting to database (used internally to list tables).
--extra-dump=EXTRA-DUMP. Add custom arguments/options to the dumping of the database (e.g. mysqldump command).
--format[=FORMAT]. Format the result data. Available formats: csv,json,list,null,php,print-r,string,table,tsv,var_dump,var_export,xml,yaml [default: null]
--database[=DATABASE]. The DB connection key if using multiple connections in settings.php. [default: default]
--db-url=DB-URL. A Drupal 6 style database URL. For example mysql://root:pass@localhost:port/dbname
--target[=TARGET]. The name of a target within the specified database connection. [default: default]
--show-passwords. Show password on the CLI. Useful for debugging.
--skip-tables-key=SKIP-TABLES-KEY. A key in the $skip_tables array. @see Site aliases
--structure-tables-key=STRUCTURE-TABLES-KEY. A key in the $structure_tables array. @see Site aliases
--tables-key=TABLES-KEY. A key in the $tables array.
--skip-tables-list=SKIP-TABLES-LIST. A comma-separated list of tables to exclude completely.
--structure-tables-list=STRUCTURE-TABLES-LIST. A comma-separated list of tables to include for structure, but not data.
--tables-list=TABLES-LIST. A comma-separated list of tables to transfer.
--fields=FIELDS. Available fields: Path (path)
--field=FIELD. Select just one field, and force format to string.
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.
Sanitize the database by removing or obfuscating user data.
Commandfiles may add custom operations by implementing:
- `#[CLI\\Hook(type: HookManager::ON_EVENT, target: 'sql-sanitize-confirms')]`. Display summary to user before confirmation.\n- `#[CLI\\Hook(type: HookManager::POST_COMMAND_HOOK, target: 'sql: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
--allowlist-fields[=ALLOWLIST-FIELDS]. A comma delimited list of fields exempt from sanitization.
--sanitize-email[=SANITIZE-EMAIL]. The pattern for test email addresses in the sanitization operation, or no to keep email addresses unchanged. May contain replacement patterns %uid, %mail or %name. [default: user+%uid@localhost.localdomain]
--sanitize-password[=SANITIZE-PASSWORD]. By default, passwords are randomized. Specify no to disable that. Specify any other value to set all passwords to that value.
--format[=FORMAT]. Format the result data. Available formats: csv,json,list,null,php,print-r,string,table,tsv,var_dump,var_export,xml,yaml [default: string]
--fields=FIELDS. Limit output to only the listed elements. Name top-level elements by key, e.g. \"--fields=name,date\", or use dot notation to select a nested element, e.g. \"--fields=a.b.c as example\".
--field=FIELD. Select just one field, and force format to string.
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 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.
--format=FORMAT. Format the result data. Available formats: csv,json,list,null,php,print-r,sections,string,table,tsv,var_dump,var_export,xml,yaml [default: table]
--fields=FIELDS. Available fields: Template (template), Compiled (compiled)
--field=FIELD. Select just one field, and force format to string.
--format[=FORMAT]. Format the result data. Available formats: csv,json,list,null,php,print-r,sections,string,table,tsv,var_dump,var_export,xml,yaml [default: table]
--fields=FIELDS. Available fields: Module (module), Update ID (update_id), Description (description), Type (type)
--field=FIELD. Select just one field, and force format to string.
--filter[=FILTER]. Filter output based on provided expression
Block or delete user account(s) with the specified name(s).
Existing content may be deleted or reassigned to the Anonymous user. See options.
By default only nodes are deleted or reassigned. Custom entity types need own code to support cancellation. See https://www.drupal.org/project/drupal/issues/3043725 for updates.
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 letmein
--format[=FORMAT]. Format the result data. Available formats: csv,json,list,null,php,print-r,sections,string,table,tsv,var_dump,var_export,xml,yaml [default: table]
--password=PASSWORD. The password for the new account
--mail=MAIL. The email address for the new account
--fields=FIELDS. Available fields: User ID (uid), User name (name), Password (pass), User mail (mail), User theme (theme), Signature (signature), Signature format (signature_format), User created (user_created), Created (created), User last access (user_access), Last access (access), User last login (user_login), Last login (login), User status (user_status), Status (status), Time zone (timezone), User picture (picture), Initial user mail (init), User roles (roles), Group Audience (group_audience), Language code (langcode), Uuid (uuid)
--field=FIELD. Select just one field, and force format to string.
--filter[=FILTER]. Filter output based on provided expression
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.
--format[=FORMAT]. Format the result data. Available formats: csv,json,list,null,php,print-r,sections,string,table,tsv,var_dump,var_export,xml,yaml [default: table]
--uid=UID. A comma delimited list of user ids to lookup (an alternative to names).
--mail=MAIL. A comma delimited list of emails to lookup (an alternative to names).
--fields=FIELDS. Available fields: User ID (uid), User name (name), Password (pass), User mail (mail), User theme (theme), Signature (signature), Signature format (signature_format), User created (user_created), Created (created), User last access (user_access), Last access (access), User last login (user_login), Last login (login), User status (user_status), Status (status), Time zone (timezone), User picture (picture), Initial user mail (init), User roles (roles), Group Audience (group_audience), Language code (langcode), Uuid (uuid)
--field=FIELD. Select just one field, and force format to string.
--filter[=FILTER]. Filter output based on provided expression
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\".
--format[=FORMAT]. Format the result data. Available formats: csv,json,list,null,php,print-r,string,table,tsv,var_dump,var_export,xml,yaml [default: table]
--fields=FIELDS. Available fields: Drush version (drush-version)
--field=FIELD. Select just one field, and force format to string.
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.
--tags=TAGS. A comma-separated list of views tags by which to filter the results.
--status=STATUS. Filter views by status. Choices: enabled, disabled.
--format[=FORMAT]. Format the result data. Available formats: csv,json,list,null,php,print-r,sections,string,table,tsv,var_dump,var_export,xml,yaml [default: table]
--fields=FIELDS. Available fields: Machine name (machine-name), Name (label), Description (description), Status (status), Tag (tag)
--field=FIELD. Select just one field, and force format to string.
--filter[=FILTER]. Filter output based on provided expression
--format[=FORMAT]. Format the result data. Available formats: csv,json,list,null,php,print-r,sections,string,table,tsv,var_dump,var_export,xml,yaml [default: table]
--count[=COUNT]. The number of messages to show. [default: 10]
--extended. Return extended information about each message.
--severity. Restrict to messages of a given severity level (numeric or string).
--type. Restrict to messages of a given type.
--fields=FIELDS. Available fields: ID (wid), Type (type), Message (message), Severity (severity), Location (location), Hostname (hostname), Date (date), Username (username)
--field=FIELD. Select just one field, and force format to string.
--filter[=FILTER]. Filter output based on provided expression
--format[=FORMAT]. Format the result data. Available formats: csv,json,list,null,php,print-r,string,table,tsv,var_dump,var_export,xml,yaml [default: yaml]
--fields=FIELDS. Limit output to only the listed elements. Name top-level elements by key, e.g. \"--fields=name,date\", or use dot notation to select a nested element, e.g. \"--fields=a.b.c as example\".
--field=FIELD. Select just one field, and force format to string.
--format[=FORMAT]. Format the result data. Available formats: csv,json,list,null,php,print-r,sections,string,table,tsv,var_dump,var_export,xml,yaml [default: table]
--count[=COUNT]. The number of messages to show. [default: 10]
--severity=SEVERITY. Restrict to messages of a given severity level (numeric or string).
--severity-min=SEVERITY-MIN. Restrict to messages of a given severity level and higher.
--type=TYPE. Restrict to messages of a given type.
--extended. Return extended information about each message.
--fields=FIELDS. Available fields: ID (wid), Type (type), Message (message), Severity (severity), Location (location), Hostname (hostname), Date (date), Username (username), Uid (uid)
--field=FIELD. Select just one field, and force format to string.
--filter[=FILTER]. Filter output based on provided expression
Drush is built by people like you! Please join us.
"},{"location":"contribute/CONTRIBUTING/#git-and-pull-requests","title":"Git and Pull requests","text":"
Contributions are submitted, reviewed, and accepted using GitHub pull requests.
The latest changes are in the 12.x branch. PR's should initially target this branch.
See the test-specific README.md for instructions on running the test suite. Test before you push. Get familiar with Unish, our test suite. Optionally run tests in the provided Docker containers.
We maintain branches named 12.x, 11.x, etc. These are release branches. From these branches, we make new tags for patch and minor versions.
Do write comments. You don't have to comment every line, but if you come up with something that's a bit complex/weird, just leave a comment. Bear in mind that you will probably leave the project at some point and that other people will read your code. Undocumented huge amounts of code are nearly worthless!
We use PSR-12.
Keep it compatible. Do not introduce changes to the public API, or configurations too casually. Don't make incompatible changes without good reasons!
Run 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.
The docs are on our web site. You may also read these from within Drush, with the drush topic command.
Documentation should be kept up-to-date. This means, whenever you add a new API method, add a new hook or change the database model, pack the relevant changes to the docs in the same pull request.
"},{"location":"contribute/unish/#about-the-test-suites","title":"About the Test Suites","text":"
Unit tests operate on functions that take values and return results without creating side effects. No database connection is required to run these tests, and no Drupal site is set up.
Integration tests set up a test dependency injection container and operate by calling the Symfony Application APIs directly. A Drupal site called the System Under Test is set up and used for the tests. The SUT is set up and installed only once, and then is re-used for all tests. Integration tests therefore cannot make destructive changes to the SUT database. Also, Drupal is bootstrapped only once (always using the standard Drupal kernel, never the install or update kernel). This means that all commands run at @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.
Functional tests operate by execing 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.
"},{"location":"contribute/unish/#drush-test-traits","title":"Drush Test Traits","text":"
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.
An extension that ships inside a contributed module - DevelCommandsTest for an example. More examples are SchedulerDrushTest and Views Bulk Operations. Remember to add drush/drush to your module's composer.json (require-dev section).
A standalone Drush extension or one that ships outside of a module - example drush extension
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
<?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
<?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('destination') == '@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('destination'))) {\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
<?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
<?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
<?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
#\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
# -*- 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
#\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
#!/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
<?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
"}]}
\ No newline at end of file
+{"config":{"lang":["en"],"separator":"[\\s\\-]+","pipeline":["stopWordFilter"]},"docs":[{"location":"","title":"Home","text":"
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.
Post support requests to Drupal Answers. Tag question with drush.
Report bugs and request features in the GitHub Drush Issue Queue.
Use pull requests (PRs) to contribute to Drush. Guidelines.
"},{"location":"#faq","title":"FAQ","text":""},{"location":"#what-does-drush-stand-for","title":"What does Drush stand for?","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.
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.
PHP8 AttributeAnnotation
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
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.
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.
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.
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.
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.
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.
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.
Drush 12 expects commandfiles to use a create() method to inject Drupal and Drush dependencies. Prior versions used a drush.services.yml file which is now deprecated and will be removed in Drush 13.
Drush 12 expects all commandfiles in the <module-name>/Drush/<Commands|Generators> directory. The Drush subdirectory is a new requirement.
Creating a new Drush command is easy. Follow the steps below.
Run drush generate drush:command-file.
Drush will prompt for the machine name of the module that should \"own\" the file. The module selected must already exist and be enabled. Use drush generate module to create a new module.
Drush will then report that it created a commandfile. Edit as needed.
Use the classes for the core Drush commands at /src/Commands as inspiration and documentation.
See the dependency injection docs for interfaces you can implement to gain access to Drush config, Drupal site aliases, etc. Also note the create() method for injecting Drupal or Drush dependencies.
Write PHPUnit tests based on Drush Test Traits.
"},{"location":"commands/#attributes-or-annotations","title":"Attributes or Annotations","text":"
The following are both valid ways to declare a command:
PHP8 AttributesAnnotations
use 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
A commandfile that will only be used on PHP8+ should use PHP Attributes instead of Annotations.
See Attributes provided by Drush core. Custom code can add additional attributes.
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:
The generator class namespace, relative to base namespace, should be Drupal\\<module-name>\\Drush\\CommandInfoAlterers and the class file should be located under the src/Drush/CommandInfoAlterers directory.
The filename must have a name like FooCommandInfoAlterer.php. The prefix Foo can be whatever string you want. The file must end in CommandInfoAlterer.php.
The class must implement the \\Consolidation\\AnnotatedCommand\\CommandInfoAltererInterface.
Implement the alteration logic in the alterCommandInfo() method.
Along with the alter code, it's strongly recommended to log a debug message explaining what exactly was altered. This makes things easier on others who may need to debug the interaction of the alter code with other modules. Also it's a good practice to inject the the logger in the class constructor.
For an example, see WootCommandInfoAlterer provided by the testing 'woot' module.
Such commands are auto-discovered by their class PSR4 namespace and class/file name suffix. Drush will auto-discover commands if:
The commands class is PSR4 auto-loadable.
The commands class namespace, relative to base namespace, is Drush\\Commands. For instance, if a Drush command provider third party library maps this PSR4 autoload entry:
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.
The class and file name ends with *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.
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
The filename must be have a name like Commands/ExampleCommands.php
The prefix Example can be whatever string you want.
The file must end in Commands.php
The directory above Commands must be one of:
A Folder listed in the 'include' option. Include may be provided via config or via CLI.
../drush, /drush or /sites/all/drush. These paths are relative to Drupal root.
"},{"location":"config-exporting/","title":"Exporting and Importing Configuration","text":"
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 supports excluding development modules from enabling on higher environments.
See Config Split module for more advanced needs.
"},{"location":"cron/","title":"Running Drupal cron tasks from Drush","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.
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).
"},{"location":"cron/#setting-the-path","title":"Setting the PATH","text":"
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).
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.
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.
"},{"location":"dependency-injection/#types-of-injection","title":"Types of Injection","text":"
There are two ways that a class can receive its dependencies. One is called \u201cconstructor injection\u201d, and the other is called \u201csetter injection\u201d.
Example of constructor injection:
public function __construct(DependencyType $service)\n {\n $this->service = $service;\n }\n
Example of setter injection:
public function setService(DependencyType $service)\n {\n $this->service = $service;\n }\n
The code that is responsible for providing the dependencies a class needs is usually an object called the dependency injection container."},{"location":"dependency-injection/#create-method","title":"create() method","text":"
11.6+
Tip
Drush 11 and prior required dependency injection via a drush.services.yml file. This approach is deprecated in Drush 12 and will be removed in Drush 13.
Drush command files can inject services by adding a create() method to the commandfile. See creating commands for instructions on how to use the Drupal Code Generator to create a simple command file starter. A create() method and a 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(ContainerInterface $container, DrushContainer $drush): 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. Drush's approach mimics Drupal's blocks, forms, and controllers.
Note that if you do not need to pull any services from the Drush container, then you may omit the second parameter to the create() method.
12.0+ Drush commands that need to be instantiated prior to bootstrap may do so by utilizing the createEarly() static factory. This method looks and functions exacty like the create() static factory, except it is only passed the Drush container. The Drupal container is not available to command handlers that use createEarly().
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.
Inflection is deprecated in Drush 12; use create() or createEarly() instead. Some classes are no longer available for inflection in Drush 12, and more (or potentially all) may be removed in Drush 13.
Drush will also inject dependencies that it provides using a technique called inflection. Inflection is a kind of dependency injection that works by way of a set of provided inflection interfaces, one for each available service. Each of these interfaces will define one or more setter methods (usually only one); these will automatically be called by Drush when the commandfile object is instantiated. The command only needs to implement this method and save the provided object in a class field. There is usually a corresponding trait that may be included via a use statement to fulfill this requirement.
For example:
<?php\nnamespace Drupal\\my_module\\Commands;\n\nuse Drush\\Commands\\DrushCommands;\nuse Consolidation\\OutputFormatters\\StructuredData\\ListDataFromKeys;\nuse Consolidation\\SiteAlias\\SiteAliasManagerAwareInterface;\nuse Consolidation\\SiteAlias\\SiteAliasManagerAwareTrait;\n\nclass MyModuleCommands extends DrushCommands implements SiteAliasManagerAwareInterface\n{\n use SiteAliasManagerAwareTrait;\n\n /**\n * Prints the current alias name and info.\n */\n #[CLI\\Command(name: 'mymodule:myAlias')]\n public function myAlias(): ListDataFromKeys \n {\n $selfAlias = $this->siteAliasManager()->getSelf();\n $this->logger()->success(\u2018The current alias is {name}\u2019, [\u2018name\u2019 => $selfAlias]);\n return new ListDataFromKeys($aliasRecord->export());\n }\n}\n
All Drush command files extend DrushCommands. DrushCommands implements ConfigAwareInterface, IOAwareInterface, LoggerAwareInterface, which gives access to $this->getConfig(), $this->logger() and other ways to do input and output. See the IO documentation for more information.
Any additional services that are desired must be injected by implementing the appropriate inflection interface.
Additional Interfaces:
SiteAliasManagerAwareInterface: The site alias manager allows alias records to be obtained.
CustomEventAwareInterface: Allows command files to define and fire custom events that other command files can hook.
Note that although the autoloader and Drush dependency injection container is available and may be injected into your command file if needed, this should be avoided. Favor using services that can be injected from Drupal or Drush. Some of the objects in the container are not part of the Drush public API, and may not maintain compatibility in minor and patch releases.
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:
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.).
Drush 11 and prior required generators to define a drush.services.yml file. This is no longer used with Drush 12+ generators. See create() method 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.
Drupal modules may supply their own Generators, just like they can supply Commands.
See Woot module, which Drush uses for testing. Specifically,
Write a class similar to ExampleGenerator. Implement your custom logic in the generate() method. Typically this class is placed under the src/Drush/Generators directory.
Add a .twig file to the same directory. This template specifies what gets output from the generator.
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:
The generator class should be PSR4 auto-loadable.
The generator class namespace, relative to base namespace, should be Drush\\Generators. For instance, if a Drush generator provider third party library maps this PSR4 autoload entry:
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.
The filename must have a name like FooGenerator.php. The prefix 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.
Documentation about available hooks.
To see how core commands implement a hook, you can search the Drush source code.
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.
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. It is required that Drupal sites be built using Composer, with Drush listed as a dependency. See recommended-project (Drush must be added). If your Composer project doesn't yet depend on Drush, run composer require drush/drush to add it.
Execution. Change your working directory to your project root, and call Drush via vendor/bin/drush. To make this easier, append ./vendor/bin to the end of your $PATH; this allows you to call Drush via drush once your working directory is set. If you only have only one Drupal codebase on your system, you may put /path/to/vendor/bin/drush in your $PATH; if you do this, then it is not necessary to set your working directory before calling Drush.
Completion. Optional. Append to .bashrc or equivalent for ZSH or Fish shell. Run drush completion --help for more details.
Multiple Codebases. Optional. If using the bash shell, consider installing the fd project, a small set of scripts that make it easier to switch between different project directories quickly, with type completion.
Note
See Usage for details on using Drush.
To use a non-default PHP, edit ~/.bashrc so that the desired PHP is in front of your $PATH. If that is not desirable, you can change your PATH for just one request: PATH=/path/to/php:$PATH drush status ...`
To use a custom php.ini for Drush requests, see this comment.
See our guide on porting commandfiles from Drush 8 to later versions. Also note that alias and config files use a new .yml format in Drush 10+.
"},{"location":"install/#drupal-compatibility","title":"Drupal Compatibility","text":"Drush Version PHP Version End Of Life Drupal versions 7 8 9 10 Drush 12 8.1+ TBD \u2705 Drush 11 7.4+ Nov 2023 \u2705 \u2713 Drush 10 7.1+ (not 8) Jan 2022 \u2713 \u2713 Drush 9 5.6+ May 2020 \u2713 Drush 8 5.4.5+ Jan 2025 \u2705 \u2713\ufe0f Drush 7 5.3.0+ Jul 2017 \u2713 Drush 6 5.3.0+ Dec 2015 \u2713 Drush 5 5.2.0+ May 2015 \u2713 Legend \u2705 Supported and recommended \u2713 Compatible but no longer supported"},{"location":"io/","title":"Input / Output","text":"
The Input object holds information about the request such option and argument values. You may need to this information when coding a hook implementation. You don't need this object in your command callback method since these values are passed as parameters.
The Output object is rarely needed. Instead, return an object that gets formatted via the Output Formatter system. If you want to send additional output, use the io system (see below).
If you need to ask the user a question, or print non-object content, use the io() system.
A command callback gets access via $this->io().
The main methods for gathering user input are $this->io()->choice() and $this->io()->confirm().
You may use any of the methods described in the Symfony Style docs.
"},{"location":"migrate/","title":"Defining and running migrations","text":"
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.
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.
Output formats may be used to select the data type used to print the output. For example, many commands allow the user to select between a human-readable table, or various machine-parsable formats such as yaml and json.
Output fields may be used to select and order the data columns.
Output filters may be used to limit which data rows are printed based on logical expressions.
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
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.
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:
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:
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:
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.
"},{"location":"output-formats-filters/#comparison-of-filters-with-grep","title":"Comparison of Filters with Grep","text":"
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 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.
An informative example is the browse command
A commandfile gets access to the SAM by implementing the SiteAliasManagerAwareInterface and useing the SiteAliasManagerAwareTrait trait. Then you gain access via $this->siteAliasManager().
If an alias was used for the current request, it is available via $this->siteAliasManager()->getself().
The SAM generally deals in SiteAlias objects. That is how any given site alias is represented. See its methods for determining things like whether the alias points to a local host or remote host.
Site alias docs.
Dynamically alter site aliases.
The SAM is also available for as a standalone Composer project. More information available in the README there.
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:
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: The fully-qualified domain name of the remote system hosting the Drupal instance. The 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: The username to log in as when using ssh or docker. If each user has to use own username, you can create an environment variable which holds the value, and reference via ${env.PROJECT_SSH_USER} (for example). Or you may omit the user item and specify a user in the ~/.ssh/config file.
root: The Drupal root; must not be specified as a relative path.
uri: The value of --uri should always be the same as when the site is being accessed from a web browser (e.g. http://example.com)
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:
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:
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.
"},{"location":"site-aliases/#additional-site-alias-options","title":"Additional Site Alias Options","text":"
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: When specified, Drush executes via docker-compose exec rather than ssh.
service: the name of the container to run on.
exec:
options: Options for the exec subcommand.
os: The operating system of the remote server. Valid values are Windows and Linux. Set this value for all remote aliases where the remote's OS differs from the local. This is especially relevant for the sql:sync command.
ssh: Contains settings used to control how ssh commands are generated when running remote commands.
options: Contains additional commandline options for the ssh command itself, e.g. -p 100
tty: Usually, Drush will decide whether or not to create a tty (via the 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.
paths: An array of aliases for common rsync targets. Relative aliases are always taken from the Drupal root.
files: Path to files directory. This will be looked up if not specified.
drush-script: Path to the remote Drush command.
command: These options will only be set if the alias is used with the specified command. In the advanced example below, the option --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
env-vars: An array of key / value pairs that will be set as environment variables.
"},{"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:
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.
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-and-other-transports","title":"Docker Compose and other transports","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/#example-of-rsync-with-exclude-paths","title":"Example of rsync with exclude-paths","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.
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.
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
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:
Drupal site folder (e.g. sites/{example.com}/drush.yml).
sites/all/drush, WEBROOT/drush, or PROJECTROOT/drush.
In any location, as specified by the --config option.
User's .drush folder (i.e. ~/.drush/drush.yml).
System-wide configuration folder (e.g. /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.
"},{"location":"using-drush-configuration/#config-examples","title":"Config examples","text":""},{"location":"using-drush-configuration/#specify-config-files-to-load","title":"Specify config files to load","text":"
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
The value may be path to a file, or to a directory containing drush.yml file(s).
View discovered config paths: drush status --fields=drush-conf --format=yaml
"},{"location":"using-drush-configuration/#specify-folders-to-search-for-drush-command-files","title":"Specify folders to search for Drush command files.","text":"
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.
"},{"location":"using-drush-configuration/#specify-the-folders-to-search-for-drush-alias-files-siteyml","title":"Specify the folders to search for Drush alias files (*.site.yml).","text":"
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.
- 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.
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
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
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
If you are authoring a commandfile and wish to access the user's configuration, see Command Authoring.
Setting boolean options broke with Symfony 3. This will be fixed in a future release.
Version-specific configuration. Limit the version of Drush that will load a configuration file by placing the Drush major version number in the filename, e.g. drush10.yml.
The Drush configuration system has been factored out of Drush and shared with the world at https://github.com/consolidation/config. Feel free to use it for your projects. Lots more usage information is there.
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.
--destination=DESTINATION. The full path and filename in which the archive should be stored. If omitted, it will be saved to the drush-backups directory.
--overwrite. Overwrite destination file if exists.
--description=DESCRIPTION. Describe the archive contents.
--tags=TAGS. Add tags to the archive manifest. Delimit several by commas.
--generator=GENERATOR. The generator name to store in the MANIFEST.yml file. The default is \"Drush archive-dump\".
--generatorversion=GENERATORVERSION. The generator version number to store in the MANIFEST file. The default is Drush version.
--exclude-code-paths=EXCLUDE-CODE-PATHS. Comma-separated list of paths (or regular expressions matching paths) to exclude from the code archive.
--skip-tables-key=SKIP-TABLES-KEY. A key in the $skip_tables array. @see Site aliases
--structure-tables-key=STRUCTURE-TABLES-KEY. A key in the $structure_tables array. @see Site aliases
--tables-key=TABLES-KEY. A key in the $tables array.
--skip-tables-list=SKIP-TABLES-LIST. A comma-separated list of tables to exclude completely.
--structure-tables-list=STRUCTURE-TABLES-LIST. A comma-separated list of tables to include for structure, but not data.
--tables-list=TABLES-LIST. A comma-separated list of tables to transfer.
--database[=DATABASE]. The DB connection key if using multiple connections in settings.php. [default: default]
--db-url=DB-URL. A Drupal 6 style database URL. For example mysql://root:pass@localhost:port/dbname
--target[=TARGET]. The name of a target within the specified database connection. [default: default]
--show-passwords. Show password on the CLI. Useful for debugging.
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 directory
drush 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.
[path]. The full path to a single archive file (*.tar.gz) or a directory with components to import. * May contain the following components generated by archive:dump command: * 1) code (\"code\" directory); * 2) database dump file (\"database/database.sql\" file); * 3) Drupal files (\"files\" directory).
[site]. Destination site alias. Defaults to @self.
--destination-path[=DESTINATION-PATH]. The base path to restore the code/files into.
--overwrite. Overwrite files if exists when un-compressing an archive.
--site-subdir[=SITE-SUBDIR]. Site subdirectory to put settings.local.php into. [default: default]
--setup-database-connection[=SETUP-DATABASE-CONNECTION]. Sets up the database connection in settings.local.php file if either --db-url option or set of specific --db- options are provided. [default: 1*]
--code. Import code.
--code-source-path[=CODE-SOURCE-PATH]. Import code from specified directory. Has higher priority over \"path\" argument.
--files. Import Drupal files.
--files-source-path[=FILES-SOURCE-PATH]. Import Drupal files from specified directory. Has higher priority over \"path\" argument.
--files-destination-relative-path[=FILES-DESTINATION-RELATIVE-PATH]. Import Drupal files into specified directory relative to Composer root.
--db. Import database.
--db-source-path[=DB-SOURCE-PATH]. Import database from specified dump file. Has higher priority over \"path\" argument.
--format[=FORMAT]. Format the result data. Available formats: csv,json,list,null,php,print-r,string,table,tsv,var_dump,var_export,xml,yaml [default: json]
--fields=FIELDS. Available fields: Cache ID (cid), Data (data), Created (created), Expire (expire), Tags (tags), Checksum (checksum), Valid (valid)
--field=FIELD. Select just one field, and force format to string.
The *%command.name% command dumps the shell completion script required to use shell autocompletion (currently, bash, fish, zsh completion are supported).
Dump 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
--source=SOURCE. An arbitrary directory that holds the configuration files.
--partial. Allows for partial config imports from the source directory. Only updates and new configs will be processed with this flag (missing configs will not be deleted). No config transformation happens.
--safe. Validate that there are no git uncommitted changes before proceeding
--runner[=RUNNER]. Where to run the rsync command; defaults to the local site. Can also be source or destination.
--format[=FORMAT]. Format the result data. Available formats: csv,json,list,null,php,print-r,string,table,tsv,var_dump,var_export,xml,yaml [default: null]
--fields=FIELDS. Available fields: Path (path)
--field=FIELD. Select just one field, and force format to string.
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.
--input-format[=INPUT-FORMAT]. Format to parse the object. Recognized values: string, yaml. Since JSON is a subset of YAML, $value may be in JSON format. [default: string]
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.
--state[=STATE]. A comma-separated list of states to filter results. [default: Only in DB,Only in sync dir,Different]
--prefix=PREFIX. The config prefix. For example, system. No prefix will return all names in the system.
--format=FORMAT. Format the result data. Available formats: csv,json,list,null,php,print-r,sections,string,table,tsv,var_dump,var_export,xml,yaml [default: table]
--fields=FIELDS. Available fields: Name (name), State (state)
--field=FIELD. Select just one field, and force format to string.
--filter[=FILTER]. Filter output based on provided expression
--format[=FORMAT]. Format the result data. Available formats: csv,json,list,null,php,print-r,sections,string,table,tsv,var_dump,var_export,xml,yaml [default: table]
--severity[=SEVERITY]. Only show status report messages with a severity greater than or equal to the specified value. [default: -1]
--ignore[=IGNORE]. Comma-separated list of requirements to remove from output. Run with --format=yaml to see key values to use.
--fields=FIELDS. Available fields: Title (title), Severity (severity), SID (sid), Description (description), Summary (value)
--field=FIELD. Select just one field, and force format to string.
--filter[=FILTER]. Filter output based on provided expression
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 @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 --.
--project=PROJECT. A comma delimited list of projects. Their paths will be added to path-aliases section.
--format[=FORMAT]. Format the result data. Available formats: csv,json,list,null,php,print-r,string,table,tsv,var_dump,var_export,xml,yaml [default: table]
--fields=FIELDS. Available fields: Drupal version (drupal-version), Site URI (uri), DB driver (db-driver), DB hostname (db-hostname), DB port (db-port), DB username (db-username), DB password (db-password), DB name (db-name), Database (db-status), Drupal bootstrap (bootstrap), Default theme (theme), Admin theme (admin-theme), PHP binary (php-bin), PHP config (php-conf), PHP OS (php-os), PHP version (php-version), Drush script (drush-script), Drush version (drush-version), Drush temp (drush-temp), Drush configs (drush-conf), Drush aliases (drush-alias-files), Alias search paths (alias-searchpaths), Install profile (install-profile), Drupal root (root), Drupal Settings (drupal-settings-file), Site path (site-path), Site path (site), Themes path (themes), Modules path (modules), Files, Public (files), Files, Private (private), Files, Temp (temp), Drupal config (config-sync), Files, Public (files-path), Files, Temp (temp-path), Other paths (%paths)
--field=FIELD. Select just one field, and force format to string.
--format=FORMAT. Format the result data. Available formats: csv,json,list,null,php,print-r,sections,string,table,tsv,var_dump,var_export,xml,yaml [default: table]
--fields=FIELDS. Available fields: Module (module), Hook (hook), Description (description)
--field=FIELD. Select just one field, and force format to string.
--filter[=FILTER]. Filter output based on provided expression
--format[=FORMAT]. Format the result data. Available formats: csv,json,list,null,php,print-r,sections,string,table,tsv,var_dump,var_export,xml,yaml [default: table]
--show-machine-names. Show machine names instead of labels in option lists.
--fields=FIELDS. Available fields: Label (label), Description (description), Field name (field_name), Field type (field_type), Required (required), Translatable (translatable), Cardinality (cardinality), Default value (default_value), Default value callback (default_value_callback), Allowed values (allowed_values), Allowed values function (allowed_values_function), Selection handler (handler), Target bundles (target_bundles)
--field=FIELD. Select just one field, and force format to string.
--filter[=FILTER]. Filter output based on provided expression
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.
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.
--format[=FORMAT]. Format the result data. Available formats: csv,json,list,null,php,print-r,tsv,var_dump,var_export,xml,yaml [default: yaml]
--field-type=FIELD-TYPE. Applicable field type.
--fields=FIELDS. Available fields: ID (id), Label (label), Default Settings (default_settings), Field types (field_types), Settings (settings), Class (class), Provider (provider) [default: id label default_settings field_types]
--field=FIELD. Select just one field, and force format to string.
--filter[=FILTER]. Filter output based on provided expression
--format[=FORMAT]. Format the result data. Available formats: csv,json,list,null,php,print-r,sections,string,table,tsv,var_dump,var_export,xml,yaml [default: table]
--show-machine-names. Show machine names instead of labels in option lists.
--fields=FIELDS. Available fields: Label (label), Description (description), Field name (field_name), Field type (field_type), Required (required), Translatable (translatable), Cardinality (cardinality), Default value (default_value), Default value callback (default_value_callback), Allowed values (allowed_values), Allowed values function (allowed_values_function), Selection handler (handler), Target bundles (target_bundles)
--field=FIELD. Select just one field, and force format to string.
--filter[=FILTER]. Filter output based on provided expression
--format[=FORMAT]. Format the result data. Available formats: csv,json,list,null,php,print-r,tsv,var_dump,var_export,xml,yaml [default: yaml]
--field-type=FIELD-TYPE. Applicable field type.
--fields=FIELDS. Available fields: ID (id), Label (label), Default Settings (default_settings), Field types (field_types), Settings (settings), Class (class), Provider (provider) [default: id label default_settings field_types]
--field=FIELD. Select just one field, and force format to string.
--filter[=FILTER]. Filter output based on provided expression
--format[=FORMAT]. Format the result data. Available formats: csv,json,list,null,php,print-r,string,tsv,var_dump,var_export,xml,yaml [default: helpcli]
--format[=FORMAT]. Format the result data. Available formats: csv,json,list,null,php,print-r,tsv,var_dump,var_export,xml,yaml [default: json]
--fields=FIELDS. Limit output to only the listed elements. Name top-level elements by key, e.g. \"--fields=name,date\", or use dot notation to select a nested element, e.g. \"--fields=a.b.c as example\".
--field=FIELD. Select just one field, and force format to string.
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.
--type=TYPE. String types to include, defaults to not-customized. Recognized values: not-customized, customized
--override=OVERRIDE. Whether and how imported strings will override existing translations. Defaults to the Import behavior configured in the admin interface. Recognized values: none, customized, not-customized, all
--type[=TYPE]. String types to include, defaults to all types. Recognized values: not-customized, customized, not-translated [default: not-customized]
--override=OVERRIDE. Whether and how imported strings will override existing translations. Defaults to the Import behavior configured in the admin interface. Recognized values: none, customized, not-customized, all
--autocreate-language. Create the language in addition to import.
--format[=FORMAT]. Format the result data. Available formats: csv,json,list,null,php,print-r,sections,string,table,tsv,var_dump,var_export,xml,yaml [default: table]
--fields=FIELDS. Available fields: Field name (machine_name), Description (description) [default: machine_name description]
--field=FIELD. Select just one field, and force format to string.
--tag=TAG. A comma-separated list of migration tags to import
--limit=LIMIT. Limit on the number of items to process in each migration
--feedback=FEEDBACK. Frequency of progress messages, in items processed
--idlist=IDLIST. Comma-separated list of IDs to import. As an ID may have more than one column, concatenate the columns with the colon ':' separator
--update. In addition to processing unprocessed items from the source, update previously-imported items with the current data
--force. Force an operation to run, even if all dependencies are not satisfied
--execute-dependencies. Execute all dependent migrations first
--timestamp. Show progress ending timestamp in progress messages
--total. Show total processed item number in progress messages
--progress[=PROGRESS]. Show progress bar [default: 1]
--delete. Delete destination records missed from the source. Not compatible with --limit and --idlist options, and high_water_property source configuration key.
migrate:messages article. Show all messages for the article migration
migrate: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\"].
--idlist=IDLIST. Comma-separated list of IDs to import. As an ID may have more than one column, concatenate the columns with the colon ':' separator
--format[=FORMAT]. Format the result data. Available formats: csv,json,list,null,php,print-r,sections,string,table,tsv,var_dump,var_export,xml,yaml [default: table]
--tag=TAG. A comma-separated list of migration tags to list. If only --tag is provided, all tagged migrations will be listed, grouped by tags.
--format[=FORMAT]. Format the result data. Available formats: csv,json,list,null,php,print-r,sections,string,table,tsv,var_dump,var_export,xml,yaml [default: table]
--fields=FIELDS. Available fields: Migration ID (id), Status (status), Total (total), Imported (imported), Needing update (needing_update), Unprocessed (unprocessed), Last Imported (last_imported) [default: id status total imported unprocessed last_imported]
--field=FIELD. Select just one field, and force format to string.
--filter[=FILTER]. Filter output based on provided expression
Build a Markdown document for each Drush command/generator that is available on a site.
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.
$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 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.
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.
--format[=FORMAT]. Format the result data. Available formats: csv,json,list,null,php,print-r,sections,string,table,tsv,var_dump,var_export,xml,yaml [default: table]
--type[=TYPE]. Only show extensions having a given type. Choices: module, theme. [default: module,theme]
--status[=STATUS]. Only show extensions having a given status. Choices: enabled or disabled. [default: enabled,disabled]
--package=PACKAGE. Only show extensions having a given project packages (e.g. Development).
--core. Only show extensions that are in Drupal core.
--no-core. Only show extensions that are not provided by Drupal core.
--fields=FIELDS. Available fields: Package (package), Project (project), Name (display_name), Name (name), Type (type), Path (path), Status (status), Version (version)
--field=FIELD. Select just one field, and force format to string.
--filter[=FILTER]. Filter output based on provided expression
Check Drupal Composer packages for pending security updates.
This uses the Drupal security advisories package to determine if updates are available. An exit code of 3 indicates that the check completed, and insecure packages were found.
--format=FORMAT. Format the result data. Available formats: csv,json,list,null,php,print-r,sections,string,table,tsv,var_dump,var_export,xml,yaml [default: table]
--fields=FIELDS. Available fields: Name (name), Installed Version (version)
--field=FIELD. Select just one field, and force format to string.
--filter[=FILTER]. Filter output based on provided expression
--format[=FORMAT]. Format the result data. Available formats: csv,json,list,null,php,print-r,sections,string,table,tsv,var_dump,var_export,xml,yaml [default: table]
--fields=FIELDS. Available fields: Queue (queue), Items (items), Class (class)
--field=FIELD. Select just one field, and force format to string.
--filter[=FILTER]. Filter output based on provided expression
Display a list of all roles defined on the system.
If a role name is provided as an argument, then all of the permissions of that role will be listed. If a permission name is provided as an option, then all of the roles that have been granted that permission will be listed.
--format[=FORMAT]. Format the result data. Available formats: csv,json,list,null,php,print-r,sections,string,table,tsv,var_dump,var_export,xml,yaml [default: yaml]
--fields=FIELDS. Available fields: ID (rid), Role Label (label), Permissions (perms)
--field=FIELD. Select just one field, and force format to string.
--filter[=FILTER]. Filter output based on provided expression
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.
--format[=FORMAT]. Format the result data. Available formats: csv,json,list,null,php,print-r,tsv,var_dump,var_export,xml,yaml [default: yaml]
--fields=FIELDS. Limit output to only the listed elements. Name top-level elements by key, e.g. \"--fields=name,date\", or use dot notation to select a nested element, e.g. \"--fields=a.b.c as example\".
--field=FIELD. Select just one field, and force format to string.
--filter[=FILTER]. Filter output based on provided expression
drush si demo_umami --locale=da. (Re)install using the Umami install profile. Set default language to Danish.
drush si --db-url=mysql://root:pass@localhost:port/dbname. Install using the specified DB params.
drush si --db-url=sqlite://sites/example.com/files/.ht.sqlite. Install using SQLite
drush 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.
[profile].... An install profile name. Defaults to standard unless an install profile is marked as a distribution. Additional info for the install profile may also be provided with additional arguments. The key is in the form [form name].[parameter name]
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.
--result-file=RESULT-FILE. Save to a file. The file should be relative to Drupal root. If --result-file is provided with the value 'auto', a date-based filename will be created under ~/drush-backups directory.
--create-db. Omit DROP TABLE statements. Used by Postgres and Oracle only.
--data-only. Dump data without statements to create any of the schema.
--ordered-dump. Order by primary key and add line breaks for efficient diffs. Slows down the dump. Mysql only.
--gzip. Compress the dump using the gzip program which must be in your $PATH.
--extra=EXTRA. Add custom arguments/options when connecting to database (used internally to list tables).
--extra-dump=EXTRA-DUMP. Add custom arguments/options to the dumping of the database (e.g. mysqldump command).
--format[=FORMAT]. Format the result data. Available formats: csv,json,list,null,php,print-r,string,table,tsv,var_dump,var_export,xml,yaml [default: null]
--database[=DATABASE]. The DB connection key if using multiple connections in settings.php. [default: default]
--db-url=DB-URL. A Drupal 6 style database URL. For example mysql://root:pass@localhost:port/dbname
--target[=TARGET]. The name of a target within the specified database connection. [default: default]
--show-passwords. Show password on the CLI. Useful for debugging.
--skip-tables-key=SKIP-TABLES-KEY. A key in the $skip_tables array. @see Site aliases
--structure-tables-key=STRUCTURE-TABLES-KEY. A key in the $structure_tables array. @see Site aliases
--tables-key=TABLES-KEY. A key in the $tables array.
--skip-tables-list=SKIP-TABLES-LIST. A comma-separated list of tables to exclude completely.
--structure-tables-list=STRUCTURE-TABLES-LIST. A comma-separated list of tables to include for structure, but not data.
--tables-list=TABLES-LIST. A comma-separated list of tables to transfer.
--fields=FIELDS. Available fields: Path (path)
--field=FIELD. Select just one field, and force format to string.
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.
Sanitize the database by removing or obfuscating user data.
Commandfiles may add custom operations by implementing:
- `#[CLI\\Hook(type: HookManager::ON_EVENT, target: 'sql-sanitize-confirms')]`. Display summary to user before confirmation.\n- `#[CLI\\Hook(type: HookManager::POST_COMMAND_HOOK, target: 'sql: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
--allowlist-fields[=ALLOWLIST-FIELDS]. A comma delimited list of fields exempt from sanitization.
--sanitize-email[=SANITIZE-EMAIL]. The pattern for test email addresses in the sanitization operation, or no to keep email addresses unchanged. May contain replacement patterns %uid, %mail or %name. [default: user+%uid@localhost.localdomain]
--sanitize-password[=SANITIZE-PASSWORD]. By default, passwords are randomized. Specify no to disable that. Specify any other value to set all passwords to that value.
--format[=FORMAT]. Format the result data. Available formats: csv,json,list,null,php,print-r,string,table,tsv,var_dump,var_export,xml,yaml [default: string]
--fields=FIELDS. Limit output to only the listed elements. Name top-level elements by key, e.g. \"--fields=name,date\", or use dot notation to select a nested element, e.g. \"--fields=a.b.c as example\".
--field=FIELD. Select just one field, and force format to string.
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 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.
--format=FORMAT. Format the result data. Available formats: csv,json,list,null,php,print-r,sections,string,table,tsv,var_dump,var_export,xml,yaml [default: table]
--fields=FIELDS. Available fields: Template (template), Compiled (compiled)
--field=FIELD. Select just one field, and force format to string.
--format[=FORMAT]. Format the result data. Available formats: csv,json,list,null,php,print-r,sections,string,table,tsv,var_dump,var_export,xml,yaml [default: table]
--fields=FIELDS. Available fields: Module (module), Update ID (update_id), Description (description), Type (type)
--field=FIELD. Select just one field, and force format to string.
--filter[=FILTER]. Filter output based on provided expression
Block or delete user account(s) with the specified name(s).
Existing content may be deleted or reassigned to the Anonymous user. See options.
By default only nodes are deleted or reassigned. Custom entity types need own code to support cancellation. See https://www.drupal.org/project/drupal/issues/3043725 for updates.
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 letmein
--format[=FORMAT]. Format the result data. Available formats: csv,json,list,null,php,print-r,sections,string,table,tsv,var_dump,var_export,xml,yaml [default: table]
--password=PASSWORD. The password for the new account
--mail=MAIL. The email address for the new account
--fields=FIELDS. Available fields: User ID (uid), User name (name), Password (pass), User mail (mail), User theme (theme), Signature (signature), Signature format (signature_format), User created (user_created), Created (created), User last access (user_access), Last access (access), User last login (user_login), Last login (login), User status (user_status), Status (status), Time zone (timezone), User picture (picture), Initial user mail (init), User roles (roles), Group Audience (group_audience), Language code (langcode), Uuid (uuid)
--field=FIELD. Select just one field, and force format to string.
--filter[=FILTER]. Filter output based on provided expression
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.
--format[=FORMAT]. Format the result data. Available formats: csv,json,list,null,php,print-r,sections,string,table,tsv,var_dump,var_export,xml,yaml [default: table]
--uid=UID. A comma delimited list of user ids to lookup (an alternative to names).
--mail=MAIL. A comma delimited list of emails to lookup (an alternative to names).
--fields=FIELDS. Available fields: User ID (uid), User name (name), Password (pass), User mail (mail), User theme (theme), Signature (signature), Signature format (signature_format), User created (user_created), Created (created), User last access (user_access), Last access (access), User last login (user_login), Last login (login), User status (user_status), Status (status), Time zone (timezone), User picture (picture), Initial user mail (init), User roles (roles), Group Audience (group_audience), Language code (langcode), Uuid (uuid)
--field=FIELD. Select just one field, and force format to string.
--filter[=FILTER]. Filter output based on provided expression
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\".
--format[=FORMAT]. Format the result data. Available formats: csv,json,list,null,php,print-r,string,table,tsv,var_dump,var_export,xml,yaml [default: table]
--fields=FIELDS. Available fields: Drush version (drush-version)
--field=FIELD. Select just one field, and force format to string.
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.
--tags=TAGS. A comma-separated list of views tags by which to filter the results.
--status=STATUS. Filter views by status. Choices: enabled, disabled.
--format[=FORMAT]. Format the result data. Available formats: csv,json,list,null,php,print-r,sections,string,table,tsv,var_dump,var_export,xml,yaml [default: table]
--fields=FIELDS. Available fields: Machine name (machine-name), Name (label), Description (description), Status (status), Tag (tag)
--field=FIELD. Select just one field, and force format to string.
--filter[=FILTER]. Filter output based on provided expression
--format[=FORMAT]. Format the result data. Available formats: csv,json,list,null,php,print-r,sections,string,table,tsv,var_dump,var_export,xml,yaml [default: table]
--count[=COUNT]. The number of messages to show. [default: 10]
--extended. Return extended information about each message.
--severity. Restrict to messages of a given severity level (numeric or string).
--type. Restrict to messages of a given type.
--fields=FIELDS. Available fields: ID (wid), Type (type), Message (message), Severity (severity), Location (location), Hostname (hostname), Date (date), Username (username)
--field=FIELD. Select just one field, and force format to string.
--filter[=FILTER]. Filter output based on provided expression
--format[=FORMAT]. Format the result data. Available formats: csv,json,list,null,php,print-r,string,table,tsv,var_dump,var_export,xml,yaml [default: yaml]
--fields=FIELDS. Limit output to only the listed elements. Name top-level elements by key, e.g. \"--fields=name,date\", or use dot notation to select a nested element, e.g. \"--fields=a.b.c as example\".
--field=FIELD. Select just one field, and force format to string.
--format[=FORMAT]. Format the result data. Available formats: csv,json,list,null,php,print-r,sections,string,table,tsv,var_dump,var_export,xml,yaml [default: table]
--count[=COUNT]. The number of messages to show. [default: 10]
--severity=SEVERITY. Restrict to messages of a given severity level (numeric or string).
--severity-min=SEVERITY-MIN. Restrict to messages of a given severity level and higher.
--type=TYPE. Restrict to messages of a given type.
--extended. Return extended information about each message.
--fields=FIELDS. Available fields: ID (wid), Type (type), Message (message), Severity (severity), Location (location), Hostname (hostname), Date (date), Username (username), Uid (uid)
--field=FIELD. Select just one field, and force format to string.
--filter[=FILTER]. Filter output based on provided expression
Drush is built by people like you! Please join us.
"},{"location":"contribute/CONTRIBUTING/#git-and-pull-requests","title":"Git and Pull requests","text":"
Contributions are submitted, reviewed, and accepted using GitHub pull requests.
The latest changes are in the 12.x branch. PR's should initially target this branch.
See the test-specific README.md for instructions on running the test suite. Test before you push. Get familiar with Unish, our test suite. Optionally run tests in the provided Docker containers.
We maintain branches named 12.x, 11.x, etc. These are release branches. From these branches, we make new tags for patch and minor versions.
Do write comments. You don't have to comment every line, but if you come up with something that's a bit complex/weird, just leave a comment. Bear in mind that you will probably leave the project at some point and that other people will read your code. Undocumented huge amounts of code are nearly worthless!
We use PSR-12.
Keep it compatible. Do not introduce changes to the public API, or configurations too casually. Don't make incompatible changes without good reasons!
Run 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.
The docs are on our web site. You may also read these from within Drush, with the drush topic command.
Documentation should be kept up-to-date. This means, whenever you add a new API method, add a new hook or change the database model, pack the relevant changes to the docs in the same pull request.
"},{"location":"contribute/unish/#about-the-test-suites","title":"About the Test Suites","text":"
Unit tests operate on functions that take values and return results without creating side effects. No database connection is required to run these tests, and no Drupal site is set up.
Integration tests set up a test dependency injection container and operate by calling the Symfony Application APIs directly. A Drupal site called the System Under Test is set up and used for the tests. The SUT is set up and installed only once, and then is re-used for all tests. Integration tests therefore cannot make destructive changes to the SUT database. Also, Drupal is bootstrapped only once (always using the standard Drupal kernel, never the install or update kernel). This means that all commands run at @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.
Functional tests operate by execing 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.
"},{"location":"contribute/unish/#drush-test-traits","title":"Drush Test Traits","text":"
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.
An extension that ships inside a contributed module - DevelCommandsTest for an example. More examples are SchedulerDrushTest and Views Bulk Operations. Remember to add drush/drush to your module's composer.json (require-dev section).
A standalone Drush extension or one that ships outside of a module - example drush extension
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
<?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
<?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('destination') == '@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('destination'))) {\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
<?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
<?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
<?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
#\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
# -*- 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
#\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
#!/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
<?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
"}]}
\ No newline at end of file
diff --git a/12.x/site-alias-manager/index.html b/12.x/site-alias-manager/index.html
index 8f00fde028..06ef9d14f1 100644
--- a/12.x/site-alias-manager/index.html
+++ b/12.x/site-alias-manager/index.html
@@ -3887,6 +3887,20 @@
+