--- name: wordpress-cli-remote-execution description: Use when running wp-cli commands against a WordPress site living inside a remote jail/container (via ssh + a jail-exec wrapper). Covers the output-prefix stripping gotcha and the correct user/path invocation pattern. --- # WordPress CLI Remote Execution ## Invocation pattern ```bash ssh user@host "bastille cmd sh -c 'cd /path/to/site && su -m www -c \"wp --path=/path/to/site\"'" ``` Key points: - Run wp-cli as the **web server user** (`www`, `www-data`, etc.), not root — WordPress file ownership assumptions and some plugin behavior depend on this. - Always pass `--path=` explicitly rather than relying on `cd` alone propagating through every nested layer correctly. ## GOTCHA: jail-exec wrappers prefix their own output A wrapper like `bastille cmd ` prints a `[jailname]:` header line before the actual command output — this is the wrapper's own framing, not part of the real output. Any script that captures this output for further parsing must filter it out: ```bash OUTPUT=$(ssh user@host "bastille cmd " 2>&1 | grep -v "^\[\]:$") ``` Forgetting this is a common, easy-to-miss source of "the command mysteriously failed to parse" bugs when scripting on top of jail-exec wrappers. ## GOTCHA: `error_reporting(0)` in bootstrap files can mask real errors Some CMS/application bootstrap files set `error_reporting(0)` globally near the very top (often to suppress noisy legacy warnings). If you're writing a standalone diagnostic/one-off script that `require`s such a bootstrap file, your own errors after that point are ALSO silently suppressed — a script can fail with **zero output and just a bad exit code**, giving no clue why. Fix: explicitly `error_reporting(E_ALL); ini_set('display_errors', '1');` again **after** requiring the bootstrap, and add a `register_shutdown_function` that dumps `error_get_last()` — this turns a silent failure into an actual, readable error message. ## GOTCHA: glob patterns fail silently under some remote shells `bastille cmd grep -rln 'pattern' /some/path/*.php` can fail with `zsh: no matches found: ...` if the jail's default shell is zsh and the glob doesn't expand as expected in that invocation context — with no useful indication that this is a shell-globbing issue rather than "no files matched." Fix: drop the glob and grep the directory recursively instead (`grep -rln 'pattern' /some/path/`, no trailing `/*.ext`) — this avoids the shell needing to expand anything at all. ## When you need to run PHP with full application bootstrap, standalone If you need to call an application's own PHP functions/classes outside the normal web request flow (e.g. to directly test a code path), don't guess at which files to `require` — trace the **actual real bootstrap sequence** the application's own front controller uses (e.g. its `index.php`) by reading it, and replicate that exact require order in your standalone script. Skipping steps because "this part probably isn't needed" reliably produces a cascade of "undefined function/class" errors that have to be debugged one require statement at a time — reading the real bootstrap sequence once up front is faster than that cascade.