WordPress plugin rebrand/conventions/remote-CLI patterns, Gitea release workflow, bastille jail provisioning, remote shell quoting safety, server fleet map, delegate brief writing, and verification discipline -- all derived from real incidents this session, plus two skills adapted (MIT license, attributed) from obra/superpowers and andrej-karpathy-skills.
70 lines
3.2 KiB
Markdown
70 lines
3.2 KiB
Markdown
---
|
|
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 <jail-name> sh -c 'cd /path/to/site && su -m www -c \"wp <command> --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 <jail>` 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 <jail> <command>" 2>&1 | grep -v "^\[<jail>\]:$")
|
|
```
|
|
|
|
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 <jail> 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.
|