# CacheTool: managing APCu and OPcache on a live PHP-FPM pool

> CacheTool is a PHP command line tool and library that reaches the APCu, OPcache and file status caches of a running PHP-FPM pool over FastCGI, so bytecode can be cleared from a shell or a cron job without a reload. The sharp edge is the file status cache, which is per-process, so clearing it reaches only one worker.

**gordalina/cachetool** — CLI App and library to manage apc & opcache.

- Repository: https://github.com/gordalina/cachetool
- Website: https://gordalina.github.io/cachetool
- Stars: 1,827 · Forks: 156
- Language: PHP
- License: MIT
- Published: 2026-10-20 · Updated: 2026-10-20 · Language: en
- Canonical page: https://hysenlabs.com/projects/gordalina-cachetool

## Asking a running FPM pool to clear its own cache

CacheTool is a command line tool and a library for working with APCu, OPcache and the file status cache of a PHP installation, and the mechanism is unusual for a command line utility: it does not touch the cache directly. It connects to a FastCGI server, in practice a PHP-FPM pool, and operates on that pool's cache from the outside. The project states the goal directly, clearing the bytecode cache without reloading php-fpm or using a web endpoint, which means no application code and no deploy hook are required. APCu and OPcache live in shared memory owned by the FPM master, so a separate process cannot reach them except by asking the pool to do it from inside. Three adapters are named, cli, fcgi and web, and fcgi is the common one because it talks straight to php-fpm. The documentation also gives the two reasons people reach for it: a cron job that handles cache invalidation on a schedule, and console statistics when something feels off.

## The fcgi adapter takes an address, a socket, or nothing

CacheTool needs to know where the pool lives, and the fcgi adapter accepts three forms of that answer. Leave the address blank and it looks for the php-fpm socket by itself, falling back to 127.0.0.1:9000 when it cannot find one. Pass an address and port directly, or pass a unix socket path:

```bash
php cachetool.phar apcu:cache:info --fcgi
```

```bash
php cachetool.phar opcache:status --fcgi=/var/run/php5-fpm.sock
```

A chrooted pool changes the picture, because the socket and the temporary directory sit inside the chroot, so the fcgi-chroot and tmp-dir parameters have to point at the right paths:

```bash
php cachetool.phar opcache:status --fcgi=/var/run/php5-fpm.sock --fcgi-chroot=/path/to/chroot --tmp-dir=/path/to/chroot/tmp
```

That extra configuration is the main operational difference between a plain FPM host and a chrooted or containerised one, and it is what turns a one line command into something a runbook has to carry.

## Download the phar, or pull gordalina/cachetool from a registry

The recommended install is two lines:

```bash
curl -sLO https://github.com/gordalina/cachetool/releases/latest/download/cachetool.phar
chmod +x cachetool.phar
```

That gives a single cachetool.phar you can place on any machine that has PHP available, which is the distribution model operations teams usually prefer for a tool that has to run alongside an existing deployment. Compressed builds are published for hosts with zlib or bzip2 enabled, and older versions stay downloadable under a tag in the file name, for example cachetool-3.2.2.phar, described as compatible with PHP >=5.5.9:

```bash
curl -sO https://gordalina.github.io/cachetool/downloads/cachetool-3.2.2.phar
chmod +x cachetool-3.2.2.phar
```

There is also a container image, published as gordalina/cachetool:latest and ghcr.io/gordalina/cachetool:latest. The Dockerfile in the repository compiles the phar with humbug/box and copies the result into a php cli alpine image whose entrypoint is cachetool, so a container run needs the FPM pool reachable from inside the container.

## stat:clear reaches one worker, not the whole pool

The file status cache is the weak spot, and the project says so without hedging. Unlike APCu and OPcache it is per-process rather than stored in shared memory, so running stat:clear against PHP-FPM only affects whichever FPM worker responds to the request. In a pool with several workers, realpath cache entries survive on the others, and a second stat:clear may land on a different worker and appear to have done nothing. The documentation links to a write-up by Julien Pauli on how the file status cache operates, and the command list includes stat:realpath_get and stat:realpath_size for inspecting what is there. If the goal is a guaranteed clean slate across a pool, the realpath cache is the part a single request cannot deliver.

## Retries apply to transport failures, not to failing PHP

Not every failure is the same kind, and the flags make the distinction explicit. When a FastCGI or web request fails, CacheTool retries it three times with a short delay, and the retries parameter changes that count:

```bash
php cachetool.phar opcache:reset --web --web-path=/path/to/your/document/root --web-url=http://url-to-your-document.root --retries=5
```

Errors raised by the PHP code itself are not retried, which is the sensible choice, since a script that throws will throw again. Timeouts are per adapter: 60 seconds for the CLI, a 5 second connection timeout with a 120 second read timeout for fastcgi, and default_socket_timeout for the web adapters. The timeout parameter sets the seconds for each request and applies to every retry, so the total wait can be several times the value you pass:

```bash
php cachetool.phar opcache:status --fcgi=127.0.0.1:9000 --timeout=10
```

## Format and sort flags turn console tables into scriptable output

Most commands print a table by default, and the format flag is where that stops being a problem. Alongside table there are json, csv and yaml, and the documentation is explicit that the machine formats carry raw values: memory sizes in bytes, times as Unix timestamps, with no rounding applied.

```bash
php cachetool.phar opcache:status --format=json
```

That choice saves the usual parsing work in a shell script or a monitoring job. For list output there is a sort flag that takes a column name from the json output keys, with a - prefix reversing the order, so the heaviest scripts in the opcode cache can be pulled to the top:

```bash
php cachetool.phar opcache:status:scripts --sort=-memory
```

If the column does not exist, the error message lists the valid column names, a small courtesy that makes a wrong key easy to correct without a second trip to the docs.

## The alternative is a pool reload or a route in your own code

The realistic alternative is not a competing cache tool, it is the two things the project itself names in its list of reasons to exist: reload php-fpm, or add a web endpoint to the application. A reload clears the bytecode cache for every worker at once, which is exactly what stat:clear cannot do, and it does so at the cost of interrupting requests in flight. A web endpoint lives inside your application, so it inherits your authentication, your deployment process and your exposure, and it only exists if someone writes and ships it. CacheTool sits outside both, asking a running pool to clear itself without a reload and without a route in your code. The trade-off is that it inherits the pool's access rules rather than your application's, which is why the web adapter needs a document root and a URL that point at a file you control.

## Two major versions on consecutive days is the upgrade cost

The activity level is high and recent. The last push to the repository was on 2026-10-18, and three releases landed inside a two day window: 10.1.0 and 11.0.0 on 2026-10-17, then 12.0.0 on 2026-10-18. Two major versions in one day is the part to plan around, because a major bump here is not the same as a patch release, and CHANGELOG.md at the top level is where the difference is written down. Old builds remain downloadable by tag, so rolling back means running a different filename rather than rebuilding anything. The licence is MIT, which means no copyleft obligation for the script that shells out to it and no per-use fee, though it gives no warranty for a tool that talks to a live FPM socket. For a scheduled job, pin the version you tested and upgrade on purpose rather than tracking the latest tag.

## Conclusion

CacheTool fits an operations team that needs to clear APCu or OPcache on a running PHP-FPM pool from a shell, a cron job or a container, without reloading the pool or shipping a web route in the application. It does not fit a team that wants the realpath cache wiped across a multi-worker pool, because stat:clear reaches only whichever worker answers the request, and it does not fit a host with no PHP runtime available. Before adopting it, confirm the pool is reachable at the socket or address you pass to the fcgi adapter, and read CHANGELOG.md before the next major bump, since 10.1.0, 11.0.0 and 12.0.0 all landed on 2026-10-17 and 2026-10-18.

## FAQ

### How do I install CacheTool on a server?

The project documents a two line install that downloads cachetool.phar from the latest release page and makes it executable. A container image is also published as gordalina/cachetool:latest and ghcr.io/gordalina/cachetool:latest.

### How do I clear OPcache without restarting PHP-FPM?

Use the opcache:reset command with the fcgi adapter, for example php cachetool.phar opcache:reset --fcgi. The tool connects to the running FPM pool over FastCGI and asks it to clear the opcode cache, with no reload and no web endpoint needed.

### Does CacheTool work with a unix socket and a chrooted PHP-FPM?

Yes. The fcgi adapter accepts a unix socket path, and for a chrooted pool you also pass the fcgi-chroot and tmp-dir parameters so the socket and temporary directory resolve inside the chroot.

### Can CacheTool output JSON so a script can parse the results?

Yes, the format flag supports table, json, csv and yaml, with table as the default. The json, csv and yaml formats carry raw values, so memory sizes are in bytes and times are Unix timestamps.

## Sources

- [gordalina/cachetool on GitHub](https://github.com/gordalina/cachetool)
- [License: MIT](https://github.com/gordalina/cachetool/blob/main/LICENSE)
- [Project website](https://gordalina.github.io/cachetool)
- [README](https://github.com/gordalina/cachetool/blob/main/README.md)
- [Releases](https://github.com/gordalina/cachetool/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/gordalina-cachetool
