2016-10-06 8 views
1

symfonyを使ってWebインターフェースを実装しています。コントローラからsudoを使ってsymfonyコンソールコマンドを呼び出す

がより良い私のコードのロジックを分離するために、私は次のようにいくつかのコンソールコマンドを作成しました:

app/console system:do-restricted --option 

そして私はこのようなコントローラからコマンドを呼び出す:

$status = $console->run(new ArrayInput([ 
    'command' => 'system:do-restricted', 
    '--option' => true 
]), $output = new BufferedOutput()); 

がありますコンソールコマンドのsudoを許可する方法はありますか?

私は唯一の方法は、シェル形および使用プロセスに上記のコマンドを再変換することであり、その場合に、OutputBaffer(+ ANSI色)に命令するInputArrayとstdoutを変換する簡単な方法があると思いますか?

+0

Webサーバーがsudoを持っています特権?そうでない場合は、おそらくいいえ。 – jcroll

+0

もちろんコントローラはsudoコマンドを起動できません。 – jcroll

答えて

0

最後に、私はsymfonyのConsole\Applicationの代わりに使用されるように、このクラスを実装しました:

<?php 

namespace Acme\Model; 

use Symfony\Component\Process\Process; 
use Symfony\Component\Console\Input\ArrayInput; 
use Psr\Log\LoggerAwareInterface; 
use Psr\Log\LoggerAwareTrait; 
use Symfony\Component\Console\Output\OutputInterface; 

final class Console implements LoggerAwareInterface 
{ 
    use LoggerAwareTrait; 

    private $consoleCommand; 

    public function __construct($consoleCommand = 'sudo app/console') 
    { 
     $this->consoleCommand = $consoleCommand; 
    } 

    /** 
    * Create a process for console command. 
    * 
    * @param string $command 
    * @param array[] $argv Same syntax as symfony ArrayInput 
    * 
    * @see Symfony\Component\Console\Input\ArrayInput 
    */ 
    public function process($command, array $argv = []) 
    { 
     $console = escapeshellcmd($this->consoleCommand); 

     $command = escapeshellarg($command); 

     $options = []; 

     $arguments = []; 

     foreach ($argv as $name => $value) { 
      if ('--' === substr($name, 0, 2)) { 
       if (false === $value) { 
        continue; 
       } 
       $option = $name; 
       if (is_string($value)) { 
        $option .= '='.$value; 
       } 
       $options[] = escapeshellarg($option); 
      } else { 
       $arguments[] = escapeshellarg($value); 
      } 
     } 

     $process = new Process(
      $console.' ' 
      .$command.' ' 
      .implode(' ', $options).' ' 
      .implode(' ', $arguments) 
     ); 

     if ($this->logger) { 
      $this->logger->info(sprintf('Created process for command: %s', $process->getCommandLine())); 
     } 

     return $process; 
    } 

    /** 
    * Run a console command. 
    * 
    * @param string    $command One of the 'app/console' commands 
    * @param array[]    $argv Assoc array '--opt' => true/false, '--opt' => 'value' or 'arg_name' => 'arg_value' 
    * @param OutputInterface|null $output Output object 
    * 
    * @see Symfony\Component\Console\Input\ArrayInput 
    */ 
    public function run($command, array $argv = [], OutputInterface $output = null) 
    { 
     if ($output->isDecorated()) { 
      $argv['--ansi'] = true; 
     } 
     $process = $this->process($command, $argv); 

     $callable = null; 
     if (null !== $output) { 
      $callable = function ($type, $line) use ($output) { 
       $output->writeln($line); 
      }; 
     } 

     $exitCode = $process->run($callable); 

     if ($this->logger) { 
      $this->logger->info(sprintf('Command returned: %d', $exitCode), ['output' => $output]); 
     } 

     return $exitCode; 
    } 
} 

そして私はこのようにそれを呼び出す:

$status = $this->console->run(
    'balancer:cluster:copy-config', 
    ['--option' => true, '--opt-val' => 'value', 'arg1' => 'value1'], 
    $output = new BufferedOutput() 
); 
関連する問題