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);
if ($this->flock($handle, $command, $timeout, $no_exclusive)) {
$output->writeln('OK');
}
} 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);
}
}