|
25 | 25 | * @author timm2k <[email protected]> |
26 | 26 | * @author Timo Förster <[email protected]> |
27 | 27 | * @author Valdnet <[email protected]> |
| 28 | + * @author MichaIng <[email protected]> |
28 | 29 | * |
29 | 30 | * @license AGPL-3.0 |
30 | 31 | * |
@@ -238,7 +239,7 @@ protected function getCurlVersion() { |
238 | 239 | } |
239 | 240 |
|
240 | 241 | /** |
241 | | - * Check if the used SSL lib is outdated. Older OpenSSL and NSS versions do |
| 242 | + * Check if the used SSL lib is outdated. Older OpenSSL and NSS versions do |
242 | 243 | * have multiple bugs which likely lead to problems in combination with |
243 | 244 | * functionality required by ownCloud such as SNI. |
244 | 245 | * |
@@ -450,31 +451,61 @@ public function getFailedIntegrityCheckFiles(): DataDisplayResponse { |
450 | 451 | } |
451 | 452 |
|
452 | 453 | /** |
453 | | - * Checks whether a PHP opcache is properly set up |
454 | | - * @return bool |
| 454 | + * Checks whether a PHP OPcache is properly set up |
| 455 | + * @return string[] The list of OPcache setup recommendations |
455 | 456 | */ |
456 | | - protected function isOpcacheProperlySetup() { |
457 | | - if (!$this->iniGetWrapper->getBool('opcache.enable')) { |
458 | | - return false; |
| 457 | + protected function getOpcacheSetupRecommendations(): array { |
| 458 | + // If the module is not loaded, return directly to skip inapplicable checks |
| 459 | + if (!extension_loaded('Zend OPcache')) { |
| 460 | + return ['The PHP OPcache module is not loaded. <a target="_blank" rel="noreferrer noopener" class="external" href="' . $this->urlGenerator->linkToDocs('admin-php-opcache') . '">For better performance it is recommended</a> to load it into your PHP installation.']; |
459 | 461 | } |
460 | 462 |
|
461 | | - if (!$this->iniGetWrapper->getBool('opcache.save_comments')) { |
462 | | - return false; |
463 | | - } |
| 463 | + $recommendations = []; |
464 | 464 |
|
465 | | - if ($this->iniGetWrapper->getNumeric('opcache.max_accelerated_files') < 10000) { |
466 | | - return false; |
| 465 | + // Check whether Nextcloud is allowed to use the OPcache API |
| 466 | + $isPermitted = true; |
| 467 | + $permittedPath = $this->iniGetWrapper->getString('opcache.restrict_api'); |
| 468 | + if (isset($permittedPath) && $permittedPath !== '' && !str_starts_with(\OC::$SERVERROOT, $permittedPath)) { |
| 469 | + $isPermitted = false; |
467 | 470 | } |
468 | 471 |
|
469 | | - if ($this->iniGetWrapper->getNumeric('opcache.memory_consumption') < 128) { |
470 | | - return false; |
471 | | - } |
| 472 | + if (!$this->iniGetWrapper->getBool('opcache.enable')) { |
| 473 | + $recommendations[] = 'OPcache is disabled. For better performance, it is recommended to apply <code>opcache.enable=1</code> to your PHP configuration.'; |
472 | 474 |
|
473 | | - if ($this->iniGetWrapper->getNumeric('opcache.interned_strings_buffer') < 8) { |
474 | | - return false; |
| 475 | + // Check for saved comments only when OPcache is currently disabled. If it was enabled, opcache.save_comments=0 would break Nextcloud in the first place. |
| 476 | + if (!$this->iniGetWrapper->getBool('opcache.save_comments')) { |
| 477 | + $recommendations[] = 'OPcache is configured to remove code comments. With OPcache enabled, <code>opcache.save_comments=1</code> must be set for Nextcloud to function.'; |
| 478 | + } |
| 479 | + |
| 480 | + if (!$isPermitted) { |
| 481 | + $recommendations[] = 'Nextcloud is not allowed to use the OPcache API. With OPcache enabled, it is highly recommended to include all Nextcloud directories with <code>opcache.restrict_api</code> or unset this setting to disable OPcache API restrictions, to prevent errors during Nextcloud core or app upgrades.'; |
| 482 | + } |
| 483 | + } elseif (!$isPermitted) { |
| 484 | + $recommendations[] = 'Nextcloud is not allowed to use the OPcache API. It is highly recommended to include all Nextcloud directories with <code>opcache.restrict_api</code> or unset this setting to disable OPcache API restrictions, to prevent errors during Nextcloud core or app upgrades.'; |
| 485 | + } else { |
| 486 | + // Check whether opcache_get_status has been explicitly disabled an in case skip usage based checks |
| 487 | + $disabledFunctions = $this->iniGetWrapper->getString('disable_functions'); |
| 488 | + if (isset($disabledFunctions) && str_contains($disabledFunctions, 'opcache_get_status')) { |
| 489 | + return []; |
| 490 | + } |
| 491 | + |
| 492 | + $status = opcache_get_status(false); |
| 493 | + |
| 494 | + // Recommend to raise value, if more than 90% of max value is reached |
| 495 | + if ($status['opcache_statistics']['num_cached_keys'] / $status['opcache_statistics']['max_cached_keys'] > 0.9) { |
| 496 | + $recommendations[] = 'The maximum number of OPcache keys is nearly exceeded. To assure that all scripts can be hold in cache, it is recommended to apply <code>opcache.max_accelerated_files</code> to your PHP configuration with a value higher than <code>' . ($this->iniGetWrapper->getNumeric('opcache.max_accelerated_files') ?: 'currently') . '</code>.'; |
| 497 | + } |
| 498 | + |
| 499 | + if ($status['memory_usage']['used_memory'] / $status['memory_usage']['free_memory'] > 9) { |
| 500 | + $recommendations[] = 'The OPcache buffer is nearly full. To assure that all scripts can be hold in cache, it is recommended to apply <code>opcache.memory_consumption</code> to your PHP configuration with a value higher than <code>' . ($this->iniGetWrapper->getNumeric('opcache.memory_consumption') ?: 'currently') . '</code>.'; |
| 501 | + } |
| 502 | + |
| 503 | + if ($status['interned_strings_usage']['used_memory'] / $status['interned_strings_usage']['free_memory'] > 9) { |
| 504 | + $recommendations[] = 'The OPcache interned strings buffer is nearly full. To assure that repeating strings can be effectively cached, it is recommended to apply <code>opcache.interned_strings_buffer</code> to your PHP configuration with a value higher than <code>' . ($this->iniGetWrapper->getNumeric('opcache.interned_strings_buffer') ?: 'currently') . '</code>.'; |
| 505 | + } |
475 | 506 | } |
476 | 507 |
|
477 | | - return true; |
| 508 | + return $recommendations; |
478 | 509 | } |
479 | 510 |
|
480 | 511 | /** |
@@ -574,10 +605,6 @@ protected function getCronErrors() { |
574 | 605 | return []; |
575 | 606 | } |
576 | 607 |
|
577 | | - protected function hasOpcacheLoaded(): bool { |
578 | | - return extension_loaded('Zend OPcache'); |
579 | | - } |
580 | | - |
581 | 608 | private function isTemporaryDirectoryWritable(): bool { |
582 | 609 | try { |
583 | 610 | if (!empty($this->tempManager->getTempBaseDir())) { |
@@ -791,9 +818,7 @@ public function check() { |
791 | 818 | 'isCorrectMemcachedPHPModuleInstalled' => $this->isCorrectMemcachedPHPModuleInstalled(), |
792 | 819 | 'hasPassedCodeIntegrityCheck' => $this->checker->hasPassedCheck(), |
793 | 820 | 'codeIntegrityCheckerDocumentation' => $this->urlGenerator->linkToDocs('admin-code-integrity'), |
794 | | - 'isOpcacheProperlySetup' => $this->isOpcacheProperlySetup(), |
795 | | - 'hasOpcacheLoaded' => $this->hasOpcacheLoaded(), |
796 | | - 'phpOpcacheDocumentation' => $this->urlGenerator->linkToDocs('admin-php-opcache'), |
| 821 | + 'OpcacheSetupRecommendations' => $this->getOpcacheSetupRecommendations(), |
797 | 822 | 'isSettimelimitAvailable' => $this->isSettimelimitAvailable(), |
798 | 823 | 'hasFreeTypeSupport' => $this->hasFreeTypeSupport(), |
799 | 824 | 'missingPrimaryKeys' => $this->hasMissingPrimaryKeys(), |
|
0 commit comments