PluginProbe
OPcache Reset / 2.4.0
OPcache Reset v2.4.0
trunk 1.0.0 2.0.0 2.0.1 2.1.0 2.1.1 2.1.2 2.1.3 2.1.5 2.1.6 2.1.7 2.1.8 2.1.9 2.2.0 2.3.0 2.4.0 2.4.1 2.4.2 2.4.3
opcache-reset / opcache-reset.php

opcache-reset.php in OPcache Reset 2.4.0, at opcache-reset.php

134 lines 4.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Plugin Name: OPcache Reset
4 * Plugin URI: http://wordpress.org/plugins/opcache-reset/
5 * Description: Automatic reset of OPcache
6 * Version: 2.4.0
7 * Requires at least: 5.0
8 * Requires PHP: 7.4
9 * Author: Danila Vershinin
10 * Author URI: https://www.getpagespeed.com/
11 * License: GPL2
12 * License URI: https://www.gnu.org/licenses/gpl-2.0.html
13 */
14
15 // Handle direct FastCGI OPcache reset request.
16 // This param can ONLY be set via direct FastCGI connection to PHP-FPM.
17 // nginx/Apache never forward arbitrary custom CGI params - only HTTP_* headers.
18 // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotValidated -- Checking existence only.
19 if ( isset( $_SERVER['GPS_OPCACHE_RESET_INTERNAL'] ) && '1' === $_SERVER['GPS_OPCACHE_RESET_INTERNAL'] ) {
20 if ( function_exists( 'opcache_reset' ) ) {
21 opcache_reset();
22 echo 'OK';
23 } else {
24 echo 'NO_OPCACHE';
25 }
26 exit;
27 }
28
29 // Make sure we don't expose any info if called directly
30 if ( ! function_exists( 'add_action' ) ) {
31 echo 'Hi there! I\'m just a plugin, not much I can do when called directly.';
32 exit;
33 }
34
35 if ( is_admin() ) {
36 if ( ! ( defined( 'DOING_AJAX' ) && DOING_AJAX ) ) {
37 // We are in admin mode: notices and such are handled here
38 require_once __DIR__ . '/opcache-admin.php';
39 }
40 }
41
42 // Load WP-CLI commands.
43 if ( defined( 'WP_CLI' ) && WP_CLI ) {
44 require_once __DIR__ . '/opcache-cli.php';
45 }
46
47 /**
48 * Reset OPCache using different approach depending on the caller context (e.g. cron vs. web)
49 */
50 function gps_opcache_reset() {
51
52 if ( ! function_exists( 'opcache_reset' ) ) {
53 // Bail if extension is not loaded
54 return;
55 }
56
57 if ( empty( ini_get( 'opcache.enable' ) ) ) {
58 // Do not try doing anything if OPcache is loaded but disabled
59 return;
60 }
61
62 if ( ! empty( ini_get( 'opcache.restrict_api' ) ) && strpos( __FILE__, ini_get( 'opcache.restrict_api' ) ) !== 0 ) {
63 return;
64 }
65
66 // https://www.getpagespeed.com/server-setup/php/zend-opcache
67 // Follow the principles of reliable file cache clearing from this article
68 $file_cache_dir = ini_get( 'opcache.file_cache' );
69 // Check if file cache is enabled and delete it if enabled
70 if ( $file_cache_dir && is_writable( $file_cache_dir ) ) {
71 // check if we can create subdirectory in the parent directory.
72 // Normally, it's ~/.cache so we can
73 $cache_dir = dirname( $file_cache_dir );
74 if ( ! is_writable( $cache_dir ) ) {
75 $file_cache_dir = null;
76 }
77 }
78
79 if ( $file_cache_dir && file_exists( $file_cache_dir ) ) {
80 // move it out of the way to avoid race conditions
81 shell_exec( "mv {$file_cache_dir} {$file_cache_dir}.rm" );
82 }
83
84 // We are in PHP-FPM context and not file cache only
85 if ( php_sapi_name() !== 'cli' && ! ini_get( 'opcache.file_cache_only' ) ) {
86 opcache_reset();
87 }
88
89 if ( $file_cache_dir ) {
90 if ( file_exists( "{$file_cache_dir}.rm" ) ) {
91 shell_exec( "rm -rf {$file_cache_dir}.rm" );
92 }
93 // make sure OPcache directory is re-created
94 shell_exec( "mkdir -p {$file_cache_dir}" );
95 }
96
97 // Irrespective of the context, we should attempt to clear the memory-based OPCache, because this script may be called from CLI
98 // and can't be aware of whether PHP-FPM is running with file_cache_only => On
99 // Since the script may be called via cron or PHP-FPM with clear_env settings, the PATH may not be set properly, so we need to set it
100 $username = getenv( 'USER' );
101 $path = "/home/{$username}/.local/bin:/usr/bin:/bin";
102 $system_path = getenv( 'PATH' );
103 if ( $system_path ) {
104 $path .= ':' . $system_path;
105 }
106
107 // Try cachetool binary first.
108 $cachetool = trim( shell_exec( "PATH={$path} which cachetool 2>/dev/null" ) );
109 if ( $cachetool ) {
110 $cmd = 'php -d opcache.enable_cli=0 -d opcache.file_cache_only=0 -d opcache.file_cache=/tmp $(which cachetool) opcache:reset';
111 shell_exec( "PATH={$path} {$cmd} 2>&1" );
112 return;
113 }
114
115 // Fallback: direct FastCGI if cachetool.yml exists.
116 require_once __DIR__ . '/opcache-fastcgi.php';
117 $config_path = gps_find_cachetool_config();
118 if ( $config_path ) {
119 $socket = gps_parse_cachetool_yml( $config_path );
120 if ( $socket ) {
121 gps_fastcgi_opcache_reset( $socket );
122 }
123 }
124 }
125
126
127 // Reset OPcache after plugin/theme/core updates (files are modified on disk).
128 // Note: Activation/deactivation/theme-switch don't need cache clear since files aren't modified.
129 add_action( 'upgrader_process_complete', 'gps_opcache_reset', PHP_INT_MAX - 1, 2 );
130
131 // Reset OPcache after a plugin is deleted/uninstalled (files are removed from disk).
132 // Important when opcache.validate_timestamps=0 to prevent serving cached deleted files.
133 add_action( 'deleted_plugin', 'gps_opcache_reset', PHP_INT_MAX - 1, 2 );
134