merged branch canni/command_in_process (PR #2894)
Commits
-------
e9b4c58
[Console] Enable process isolantion in Shell
Discussion
----------
[Console] Enable process isolantion in Shell
Bug fix: no
BC break: no
Feature addition: yes
Symfony2 test pass: yes
Fixes the following tickets: #2848 #2847
Todo: Write unit tests
See tickets for reference, need help with unit testing, because I don't know how to test this :)
---------------------------------------------------------------------------
by canni at 2011-12-16T09:36:32Z
I've tested this with different scenarios like "inception" (invoking shell from shell - will not work) ;) and others, everything seems to work great.
As I have no idea on how to pack this with unit testing some help needed, also as I don't have any windows in home ;) need someone to test it on MS os.
And we should decide, do we want process isolation by default? (This will not break the BC, break only the "expected behavior" - colorful output and "interactivity")
---------------------------------------------------------------------------
by canni at 2011-12-18T15:14:26Z
I've rebased this branch to match current `HEAD` and I've added usage of new process builder, for better portability an shell arg escaping.
---------------------------------------------------------------------------
by fabpot at 2012-02-02T08:28:32Z
@canni: Can you squash your commits before I merge this PR? Thanks.
---------------------------------------------------------------------------
by canni at 2012-02-02T09:07:16Z
@fabpot @stof done.
This commit is contained in:
commit
687703db94
@ -128,6 +128,7 @@ To get the diff between two versions, go to https://github.com/symfony/symfony/c
|
||||
* added support for STDERR in the console output class (errors are now sent to STDERR)
|
||||
* made the defaults (helper set, commands, input definition) in Application more easily customizable
|
||||
* added support for the shell even if readline is not available
|
||||
* added support for process isolation in Symfony shell via `--process-isolation` switch
|
||||
|
||||
### ClassLoader
|
||||
|
||||
|
@ -39,6 +39,7 @@ class Application extends BaseApplication
|
||||
parent::__construct('Symfony', Kernel::VERSION.' - '.$kernel->getName().'/'.$kernel->getEnvironment().($kernel->isDebug() ? '/debug' : ''));
|
||||
|
||||
$this->getDefinition()->addOption(new InputOption('--shell', '-s', InputOption::VALUE_NONE, 'Launch the shell.'));
|
||||
$this->getDefinition()->addOption(new InputOption('--process-isolation', null, InputOption::VALUE_NONE, 'Launch commands from shell as a separate processes.'));
|
||||
$this->getDefinition()->addOption(new InputOption('--env', '-e', InputOption::VALUE_REQUIRED, 'The Environment name.', $kernel->getEnvironment()));
|
||||
$this->getDefinition()->addOption(new InputOption('--no-debug', null, InputOption::VALUE_NONE, 'Switches off debug mode.'));
|
||||
}
|
||||
@ -67,6 +68,7 @@ class Application extends BaseApplication
|
||||
|
||||
if (true === $input->hasParameterOption(array('--shell', '-s'))) {
|
||||
$shell = new Shell($this);
|
||||
$shell->setProcessIsolation($input->hasParameterOption(array('--process-isolation')));
|
||||
$shell->run();
|
||||
|
||||
return 0;
|
||||
|
@ -14,6 +14,8 @@ namespace Symfony\Component\Console;
|
||||
use Symfony\Component\Console\Application;
|
||||
use Symfony\Component\Console\Input\StringInput;
|
||||
use Symfony\Component\Console\Output\ConsoleOutput;
|
||||
use Symfony\Component\Process\ProcessBuilder;
|
||||
use Symfony\Component\Process\PhpExecutableFinder;
|
||||
|
||||
/**
|
||||
* A Shell wraps an Application to add shell capabilities to it.
|
||||
@ -31,6 +33,7 @@ class Shell
|
||||
private $output;
|
||||
private $hasReadline;
|
||||
private $prompt;
|
||||
private $processIsolation;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
@ -39,8 +42,6 @@ class Shell
|
||||
* a \RuntimeException exception is thrown.
|
||||
*
|
||||
* @param Application $application An application instance
|
||||
*
|
||||
* @throws \RuntimeException When Readline extension is not enabled
|
||||
*/
|
||||
public function __construct(Application $application)
|
||||
{
|
||||
@ -49,6 +50,7 @@ class Shell
|
||||
$this->history = getenv('HOME').'/.history_'.$application->getName();
|
||||
$this->output = new ConsoleOutput();
|
||||
$this->prompt = $application->getName().' > ';
|
||||
$this->processIsolation = false;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -65,6 +67,20 @@ class Shell
|
||||
}
|
||||
|
||||
$this->output->writeln($this->getHeader());
|
||||
$php = null;
|
||||
if ($this->processIsolation) {
|
||||
$finder = new PhpExecutableFinder();
|
||||
$php = $finder->find();
|
||||
$this->output->writeln(<<<EOF
|
||||
<info>Running with process isolation, you should consider this:</info>
|
||||
* each command is executed as separate process,
|
||||
* commands don't support interactivity, all params must be passed explicitly,
|
||||
* commands output is not colorized.
|
||||
|
||||
EOF
|
||||
);
|
||||
}
|
||||
|
||||
while (true) {
|
||||
$command = $this->readline();
|
||||
|
||||
@ -79,7 +95,28 @@ class Shell
|
||||
readline_write_history($this->history);
|
||||
}
|
||||
|
||||
if (0 !== $ret = $this->application->run(new StringInput($command), $this->output)) {
|
||||
if ($this->processIsolation) {
|
||||
$pb = new ProcessBuilder();
|
||||
|
||||
$process = $pb
|
||||
->add($php)
|
||||
->add($_SERVER['argv'][0])
|
||||
->add($command)
|
||||
->inheritEnvironmentVariables(true)
|
||||
->getProcess()
|
||||
;
|
||||
|
||||
$output = $this->output;
|
||||
$process->run(function($type, $data) use ($output) {
|
||||
$output->writeln($data);
|
||||
});
|
||||
|
||||
$ret = $process->getExitCode();
|
||||
} else {
|
||||
$ret = $this->application->run(new StringInput($command), $this->output);
|
||||
}
|
||||
|
||||
if (0 !== $ret) {
|
||||
$this->output->writeln(sprintf('<error>The command terminated with an error status (%s)</error>', $ret));
|
||||
}
|
||||
}
|
||||
@ -156,4 +193,14 @@ EOF;
|
||||
|
||||
return $line;
|
||||
}
|
||||
|
||||
public function getProcessIsolation()
|
||||
{
|
||||
return $this->processIsolation;
|
||||
}
|
||||
|
||||
public function setProcessIsolation($processIsolation)
|
||||
{
|
||||
$this->processIsolation = (Boolean) $processIsolation;
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user