setName('lock:wait') ->setDescription('Lock wait command') ->setHelp('Lock wait command. Wait for lock a file. The lock can be either exclusive or shared') ->addArgument('filename', InputOption::VALUE_REQUIRED, 'Filename') ->addOption('command', 'c', InputOption::VALUE_REQUIRED, 'Command to execute') ->addOption('dir', null, InputOption::VALUE_REQUIRED, 'Directory path file', '/tmp') ->addOption('timeout', null, InputOption::VALUE_REQUIRED, 'Timeout execution (ms)', 600) ->addOption('no-exclusive', 'no-e', InputOption::VALUE_NONE, 'No exclusive lock') ; } /** * @param InputInterface $input * @param OutputInterface $output */ protected function execute(InputInterface $input, OutputInterface $output) { $filename = $input->getArgument('filename'); $command = $input->getOption('command'); $dir = $input->getOption('dir'); $timeout = $input->getOption('timeout'); $no_exclusive = $input->getOption('no-exclusive'); if ($filename && $command) { $handle = $this->fopen($filename, $dir); $this->flock($handle, $command, $timeout, $no_exclusive); } else { $output->writeln('Enter a valid filename and command'); } } /** * @param string $filename * @param string $dir * * @return resource */ protected function fopen($filename, $dir) { // limpio el filename completo $invalid_chars = array(" ", '"', "'", "&", "\\", "?", "#", "$", "//"); $delimiter = DIRECTORY_SEPARATOR; $dir_pieces = explode($delimiter, str_replace($invalid_chars, '', $dir)); $filename_pieces = explode($delimiter, str_replace($invalid_chars, '', $filename)); $last_filename_piece = array_pop($filename_pieces); $dir = $delimiter . implode($delimiter, array_filter(array_merge($dir_pieces, $filename_pieces))); $filename = $dir . $delimiter . $last_filename_piece; if (!file_exists($dir)) { mkdir($dir, 0777, true); } return fopen($filename, "w+"); } /** * @param resource $handle * @param string $command * @param int $timeout * @param boolean $no_exclusive * * @return boolean */ protected function flock($handle, $command, $timeout = 600, $no_exclusive = false) { pcntl_signal(SIGALRM, function() { exit(1); }); pcntl_alarm($timeout); $operation = LOCK_EX; if ($no_exclusive) { $operation = LOCK_SH; } if (flock($handle, $operation)) { $exit_code = $this->runProcess($command)['exit_code']; } else { echo 'No se pudo obtener el lock' . PHP_EOL; $exit_code = 1; } pcntl_alarm(0); pcntl_signal_dispatch(); pcntl_signal(SIGALRM, SIG_DFL); flock($handle, LOCK_UN); fclose($handle); exit($exit_code); } /** * @param string $filename * * @return array */ protected function runProcess($filename) { /* @var $taskloggerService TaskLoggerService */ $taskloggerService = $this->getContainer()->get('flowdat_tasklogger_service'); return $taskloggerService->runProcess($filename); } }