2016-10-06 163 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的控制檯命令?

我想的唯一方法是重新轉換上述命令到外殼形式和使用過程中,在這種情況下,有一種簡單的方法來轉換InputArray命令和stdout到OutputBaffer(+ ANSI顏色)?

+0

請問您的Web服務器有須藤特權?如果不是,可能不是。 – 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() 
);