I'm creating an admin page for my module that will allow an admin to trigger scripts from within the module configurations.
So far, I've created these routes:
my_module.scripts.home:
path: "/admin/config/development/my_module/scripts"
defaults:
_title: "Scripts"
_controller: '\Drupal\my_module\Controller\ScriptsController::home'
requirements:
_permission: "administer site configuration"
my_module.scripts.run:
path: "/admin/config/development/my_module/scripts/run/{script}"
defaults:
_title: "Run Script"
'\Drupal\ytp_integrations\Controller\ScriptsController::runScript'
name: "none"
requirements:
_permission: "administer site configuration"
And then my Scripts Controller looks like so:
<?php
namespace Drupal\my_module\Controller;
use Drupal\Core\Controller\ControllerBase;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\Yaml\Yaml;
use Drupal\Core\Url;
/**
* Defines Configurations Controller class.
*
* This class controller i
*/
class ScriptsController extends ControllerBase {
/**
* Home
*/
function home() {
$build['table'] = [
'#type' => 'table',
'#header' => [
'Title',
'Description',
'Path',
'Status',
],
];
// Retrieve all scripts
$scripts_config_file = file_get_contents(drupal_get_path('module', 'my_module') . '/my_module.scripts.yml');
$script_config = Yaml::parse($scripts_config_file);
// Create Table Rows and add to table
$rows = [];
foreach($script_config as $key => $script) {
$rows[] = [
'title' => $script['title'],
'description' => $script['description'],
'path' => $script['path'],
'operations' => [
'data' => [
'#type' => 'link',
'#title' => 'Run',
'#url' => Url::fromRoute('my_module.scripts.run', ['script' => $key])
],
],
];
}
$build['table']['#rows'] = $rows;
return [
'#type' => '#markup',
'#markup' => render($build),
];
}
/**
* Run Script
*
*
*/
function runScript($script) {
// Retrieve the script
$module_path = drupal_get_path('module', 'my_module');
$script_config = Yaml::parse(file_get_contents("$module_path/my_module.scripts.yml"));
$script_data = $script_config[$script];
$script_path = $module_path . '/' . $script_data['path'];
$execute = exec("drush scr $script_path > /dev/null &");
\Drupal::logger('ytp')->notice('<pre><code>' . print_r($execute, TRUE) . '</code></pre>');
return new RedirectResponse(Url::fromRoute('ytp_integrations.scripts.home')->toString());
}
}
Structurally, this seems to all work, but when I print out the execute variable after running the drush
command via exec, I get nothing and the code in my script isn't executed. I changed the command to pwd and it printed out the path like expected, but exec doesn't seem to know what drush is...
I would use drush_invoke_process
, but I would like my drush command to be executed in the background. I'm expecting to get a pid
back so that I am able to determine which scripts should have their run
button disabled if the pid is running in the background.
Any reason why exec
doesn't know what drush is or how I could kick off my drush script in the background running via Drush?
exec
in your shell so it probably just doesn't have drush in the PATH - tryvendor/bin/drush
instead – Clive♦ Feb 22 at 23:38> /dev/null &
and run any drush command like$execute = exec("vendor/bin/drush status");
, I'm now getting the error ` thrown in /Users/meproject_root/vendor/webmozart/path-util/src/Path.php on line 257`. Any idea what that is? – BlondeSwan Feb 22 at 23:53exec
, write a file in a shared location on the disk containing the name of 1 or more scripts. Add a cron job to check the file in the shared location and run the appropriate drush scripts. This will run as your normal user, making drush more likely to work, and is still non-blocking. Plus it gives you an opportunity to implement a rudimentary cancel feature if you need it – Clive♦ Feb 23 at 20:29