Chapter 21Lesson 04~205 minutes

CLI Mode, Headless Execution, Result Files, and Reproducible Runs: Diagnostics, Failure Modes, and Production Practices

Headless operation fails in several distinct layers: the wrapper may point at the wrong file, JMeter may fail to load/initialize, samples may fail while the engine completes, the gate may reject otherwise valid samples, or report generation may collide with an old directory. Preserve the earliest evidence and identify the layer before changing load, heap, retries or the target.

Missing file-f hazardSecretsExit vs SLOVersion drift

Learning objectives

  • Recognize GUI load execution as a generator-validity problem.
  • Prevent evidence overwrite and unsafe force-delete use.
  • Keep secrets out of commands/manifests/logs.
  • Use jmeter.log to diagnose engine/config problems.
  • Separate process/engine success from sample/SLO pass.
  • Detect and control JMeter/Java version drift.

1. Preserve first-failure evidence

All runnable failure reproduction remains local at 127.0.0.1:8021, ≤2×4. Preserve exact command, cwd, versions, JMX/property hashes, wrapper/pre-manifest, JTL if any, jmeter.log, engine exit, gate output, report state, generator state and target events before repair. Do not delete/overwrite the failed run directory.

2. Diagnostic sequence

CLI failure diagnosis

CLI execution turns a JMeter plan into a reproducible process contract: explicit inputs enter one engine process, the process emits separate raw/log/report artifacts, and a post-run validator decides whether the observed workload is acceptable.

flowchart TD
E[Preserve command + JTL + jmeter.log + manifest + target evidence] --> V[Confirm JMeter / Java / plugin / tool versions]
V --> C[Confirm exact JMX / data / properties / CLI + authorized target]
C --> S[Validate tree scope + resolved variables/properties + expected sample count]
S --> P[Inspect protocol/session/data state]
P --> G[Inspect generator JVM / CPU / GC / disk / network]
G --> T[Inspect SUT telemetry / received work]
T --> X[Inspect CI/container/remote workspace/result-transfer state if relevant]
X --> F[Least destructive correction]
F --> R[Small controlled rerun]

3. Failure mode: running meaningful load in GUI

Symptoms: higher generator CPU/memory, UI freezes, retained listener data and harder-to-reproduce results. Repair: use GUI only to author/validate tiny cases; save the JMX and run the bounded load through the recorded CLI contract. Do not conclude the server is slow from a saturated GUI injector.

4. Failure mode: overwriting prior evidence

Broken:

jmeter -n -t plan.jmx -l results/results.jtl -j results/jmeter.log
# repeated tomorrow with the same paths

Depending on file/report behavior and surrounding scripts, the second invocation can mix/replace evidence or fail ambiguously. Repair: allocate a new run ID directory and refuse reuse.

5. Failure mode: unsafe -f

Broken automation constructs output paths from an unchecked variable and adds -f “so stale files never block the job.” Current JMeter defines -f to force-delete existing result files and web report folders.

Repair: remove -f from the general launcher. Use immutable run directories. If a specialized disposable workspace ever uses -f, verify the resolved path is a dedicated generated child of a known workspace before invoking JMeter.

6. Failure mode: embedding credentials in CLI

Commands can be visible in process listings, shell history, CI logs and manifests. Current JMeter docs explicitly warn that proxy credentials on the command line may be visible to other system users.

Repair: keep non-secret workload knobs in -J; inject real secrets using an approved secret mechanism that is not echoed/manifested, and redact diagnostic output. The mandatory fixture uses no authentication.

7. Failure mode: ignoring jmeter.log

A JTL may be empty or shorter than expected because JMX parsing, script/class/plugin initialization, report generation or engine shutdown had a problem. If the wrapper only parses JTL and discards jmeter.log, the root cause is lost.

Always retain -j run/jmeter.log and search ERROR/FATAL/WARN context before changing the SUT.

8. Failure mode: process exit success interpreted as SLO success

A JMeter invocation can complete at the process layer while JTL contains HTTP/assertion failures or an unacceptable p95. That is why the Chapter 21 gate parses result rows independently.

Never rewrite the engine exit code to “failed because p95” without also preserving the original engine status. Store both.

9. Failure mode: floating JMeter/Java versions

Two scheduled runners pick different JMeter or Java versions from PATH. Behavior/performance changes can then be attributed incorrectly to the SUT.

Repair: standardize/pin an approved runtime, capture jmeter -v and java -version every run, and reject/flag unexpected versions before a regression comparison.

10. Intentionally broken example: missing JMX file

Create a dedicated failure directory, then intentionally invoke a nonexistent plan directly so the JMeter process—not the safe wrapper's preflight—owns the failure:

$FailDir = "F:\Labs\p21-cli-lab\results\p21-missing-jmx"
New-Item -ItemType Directory -Force $FailDir | Out-Null

& "$env:JMETER_HOME\bin\jmeter.bat" `
  -n `
  -t "F:\Labs\p21-cli-lab\plans\missing-plan.jmx" `
  -q "F:\Labs\p21-cli-lab\config\local.properties" `
  -l "$FailDir\results.jtl" `
  -j "$FailDir\jmeter.log"

$EngineExit = $LASTEXITCODE
$EngineExit | Set-Content "$FailDir\engine-exit.txt"

Expected: non-success process/engine evidence, jmeter.log indicating plan/file load failure, no valid 8-sample JTL workload, and no matching target work events. Preserve all files. The target is healthy; this failure occurred before workload execution.

Repair: do not copy a random replacement plan or switch target. Use the existing hashed plans/cli-local.jmx through the safe launcher with a new run ID.

11. Failure mode: report output directory already contains files

-o requires a new/empty destination. A fixed report-output path from yesterday can make report generation fail even when JTL is valid.

Repair: generate inside a unique run directory or use a new directory for later -g. Preserve the raw JTL; report generation can be retried without rerunning target load.

12. Failure mode: global DEBUG under load

-LDEBUG can dramatically enlarge jmeter.log and consume generator CPU/disk. Use a narrow category only in a small reproduction. Record any logging override because the generator workload changed.

13. Causal symptom table

Symptom Generator/execution cause Target cause to distinguish Evidence
No target work events missing/invalid JMX, preflight/engine failure target down engine exit + jmeter.log + target health/event delta.
8 samples but some failed HTTP/assertion/data issue server correctness/error JTL failureMessage/code + target events.
p95 rises, target service time flat generator CPU/GC/log/save/report/network server slowdown generator state + JTL + target service_wall_ms.
HTML missing but JTL valid report path/generation problem SUT regression jmeter.log/report dir + complete JTL/target events.
CI differs from local version/path/workspace/container/runtime drift target regression manifest versions/hashes/cwd + target evidence.

14. Troubleshooting shortcuts to reject

  • Do not add blanket retries or arbitrary long sleeps.
  • Do not raise heap before identifying avoidable listeners/log/result cost.
  • Do not mass-disable listeners without evidence and then lose required diagnostics.
  • Do not use global property hacks to force missing runtime state.
  • Do not disable TLS/RMI verification.
  • Do not test a production endpoint because localhost/CI paths failed.
  • Do not increase threads/sample count while process/artifact validity is unresolved.
  • Do not delete failed JTL/log/manifests to free space before diagnosis.

Knowledge check

What proves the missing-JMX failure is not target saturation?

Why is -f omitted from the general launcher?

Why should a command manifest exclude secrets?

What if engine exit=0 but JTL failures=2?

What must be controlled before comparing two scheduled runs?

Next lesson

Checkpoint: fail safely, then restore a reproducible run

Lesson 5 assembles the launcher/evidence packet, predicts success/failure artifacts, executes from two shells, preserves the missing-file failure, and closes with the production CLI operating contract.

Official references and version notes

Version and compatibility note

Version-sensitive statements were rechecked against current Apache JMeter primary documentation on 2026-09-05. The course baseline remains Apache JMeter 5.6.3 with a Java 17 JDK; JMeter 5.6.3 requires Java 8+. JMeter's own manual says GUI mode is for building/debugging while CLI mode must be used for load testing. Current CLI flags include -n (CLI), -t (JMX), -l (JTL), -j (run log), -g <CSV> (report only), -e (report after test), and -o (report output). The report output folder must not exist or must be empty. -f force-deletes an existing result file/report folder before a test, so the safe launcher in this chapter intentionally does not use it; instead it refuses to reuse an existing run directory. CSV result files are smaller than XML and are the normal large-run choice. Current CSV defaults include timing/status/thread and byte fields such as timeStamp, elapsed, label, responseCode, success, bytes, sentBytes, grpThreads, and allThreads when their save-service fields are enabled (the current defaults required by the dashboard are documented as correct unless changed). Response data is not supported in CSV. JMeter process/engine completion is therefore treated separately from a post-run SLO/result gate: a launcher first records the engine exit code, then validates JTL sample counts/failures/latency. A zero engine exit is not used as evidence that every sample met an SLO.

Keep the academy open

Support free, practical DevOps education.

Every lesson is designed to remain readable in a browser, downloadable from GitHub, and usable without a paid learning platform. Contributions help expand and maintain the curriculum.

Ethereum / ERC-20
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0 Send only Ethereum/ERC-20 compatible assets to this address.