LockWaitCommand.php 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. <?php
  2. namespace WorkflowBundle\Command;
  3. use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand;
  4. use Symfony\Component\Console\Input\InputInterface;
  5. use Symfony\Component\Console\Input\InputOption;
  6. use Symfony\Component\Console\Output\OutputInterface;
  7. use WorkflowBundle\Services\TaskLoggerService;
  8. class LockWaitCommand extends ContainerAwareCommand
  9. {
  10. protected function configure()
  11. {
  12. $this
  13. ->setName('lock:wait')
  14. ->setDescription('Lock wait command')
  15. ->setHelp('Lock wait command. Wait for lock a file. The lock can be either exclusive or shared')
  16. ->addArgument('filename', InputOption::VALUE_REQUIRED, 'Filename')
  17. ->addOption('command', 'c', InputOption::VALUE_REQUIRED, 'Command to execute')
  18. ->addOption('dir', null, InputOption::VALUE_REQUIRED, 'Directory path file', '/tmp')
  19. ->addOption('timeout', null, InputOption::VALUE_REQUIRED, 'Timeout execution (ms)', 600)
  20. ->addOption('no-exclusive', 'no-e', InputOption::VALUE_NONE, 'No exclusive lock')
  21. ;
  22. }
  23. /**
  24. * @param InputInterface $input
  25. * @param OutputInterface $output
  26. */
  27. protected function execute(InputInterface $input, OutputInterface $output)
  28. {
  29. $filename = $input->getArgument('filename');
  30. $command = $input->getOption('command');
  31. $dir = $input->getOption('dir');
  32. $timeout = $input->getOption('timeout');
  33. $no_exclusive = $input->getOption('no-exclusive');
  34. if ($filename && $command) {
  35. $handle = $this->fopen($filename, $dir);
  36. if ($this->flock($handle, $command, $timeout, $no_exclusive)) {
  37. $output->writeln('<info>OK</info>');
  38. }
  39. } else {
  40. $output->writeln('<error>Enter a valid filename and command</error>');
  41. }
  42. }
  43. /**
  44. * @param string $filename
  45. * @param string $dir
  46. *
  47. * @return resource
  48. */
  49. protected function fopen($filename, $dir)
  50. {
  51. // limpio el filename completo
  52. $invalid_chars = array(" ", '"', "'", "&", "\\", "?", "#", "$", "//");
  53. $delimiter = DIRECTORY_SEPARATOR;
  54. $dir_pieces = explode($delimiter, str_replace($invalid_chars, '', $dir));
  55. $filename_pieces = explode($delimiter, str_replace($invalid_chars, '', $filename));
  56. $last_filename_piece = array_pop($filename_pieces);
  57. $dir = $delimiter . implode($delimiter, array_filter(array_merge($dir_pieces, $filename_pieces)));
  58. $filename = $dir . $delimiter . $last_filename_piece;
  59. if (!file_exists($dir)) {
  60. mkdir($dir, 0777, true);
  61. }
  62. return fopen($filename, "w+");
  63. }
  64. /**
  65. * @param resource $handle
  66. * @param string $command
  67. * @param int $timeout
  68. * @param boolean $no_exclusive
  69. *
  70. * @return boolean
  71. */
  72. protected function flock($handle, $command, $timeout = 600, $no_exclusive = false)
  73. {
  74. pcntl_signal(SIGALRM, function() {
  75. exit(1);
  76. });
  77. pcntl_alarm($timeout);
  78. $operation = LOCK_EX;
  79. if ($no_exclusive) {
  80. $operation = LOCK_SH;
  81. }
  82. if (flock($handle, $operation)) {
  83. $exit_code = $this->runProcess($command)['exit_code'];
  84. } else {
  85. echo 'No se pudo obtener el lock' . PHP_EOL;
  86. $exit_code = 1;
  87. }
  88. pcntl_alarm(0);
  89. pcntl_signal_dispatch();
  90. pcntl_signal(SIGALRM, SIG_DFL);
  91. flock($handle, LOCK_UN);
  92. fclose($handle);
  93. exit($exit_code);
  94. }
  95. /**
  96. * @param string $filename
  97. *
  98. * @return array
  99. */
  100. protected function runProcess($filename)
  101. {
  102. /* @var $taskloggerService TaskLoggerService */
  103. $taskloggerService = $this->getContainer()->get('flowdat_tasklogger_service');
  104. return $taskloggerService->runProcess($filename);
  105. }
  106. }