skip to content

In JMeter's OS Process Sampler, what makes a failing command fail the sample?

level: middleimportance: nice to knowfreq 28%

answer

  1. Recording a value is not judging it
  2. One checkbox turns the code into a verdict
  3. One code is reserved by the tool itself
  4. Compare against Expected Return Code

basics

~20 s

Only the Check Return Code checkbox. The sampler always records the process exit code as the response code, but marks the sample successful whatever that code is unless Check Return Code is ticked and the code differs from Expected Return Code.

solid answer

~50 s

The **OS Process Sampler** runs a program on the injector and stores its exit status as the sample's response code. That is a record, not a verdict. The verdict comes from **Check Return Code**: unticked, the sample is marked successful no matter what the process returned; ticked, JMeter compares the exit code with **Expected Return Code** (`0` by default) and fails the sample on any difference, with a message naming both values. JMeter uses `500` as its own error indicator for an I/O failure, an interruption or an expired **Timeout**, so `500` must not be used as an expected code. Standard output and standard error are captured into the response data unless files are named for them. The sampler does no shell parsing or quoting, so shell built-ins must be passed to the interpreter as arguments.

code

text · 10 lines
text
Command:                CMD
Command Parameters:     /C
                        DIR
                        C:\TEMP
Check Return Code:      [x]
Expected Return Code:   0
Timeout:                5000

Response code:    3
Response message: Unexpected return code.  Expected [0]. Actual [3].

go deeper

for a junior

Recall that the exit code is stored as the response code but that the sample only fails when Check Return Code is ticked.

for a middle

Explain the reserved 500 indicator, the meaning of a 0 timeout, and why no shell sits between the sampler and the executable.

for a senior

Judge when shelling out belongs in a plan at all, and how to keep such a sampler portable between a developer laptop and a CI runner.

for a principal

Own the policy on what load plans are allowed to execute on an injector, given that a shelled-out command runs with the injector's own credentials and filesystem.

The **OS Process Sampler** is the shell-out escape hatch: it runs a command on the machine the thread is running on, which in a load plan is the injector rather than the system under test. Seeding an order queue with a fixture script, calling a broker's admin CLI to purge it, or invoking a tool that speaks a protocol no sampler covers are its honest uses. ## The exit code is recorded, not judged Every sample stores the process's exit status as the response code — a literal `0`, `1`, `3` and so on. But the success flag is decided separately: - **Check Return Code unticked** — the sample is marked successful, whatever the command returned. - **Check Return Code ticked** — JMeter compares the exit status with **Expected Return Code**, defaulting to `0`, and fails the sample when they differ. The response message reads `Unexpected return code. Expected [0]. Actual [3].` That default is the whole reason a plan can shell out to a script that has been failing for weeks and still show a green run. If you shell out, tick the box. ## Why 500 is reserved JMeter uses `500` as its own error indicator on this sampler. Three internal conditions set it: 1. an `IOException` while launching or running the command; 2. the sampler thread being interrupted; 3. the **Timeout** expiring, after which JMeter attempts to kill the OS process. The component reference says so directly and warns you not to use `500` as an expected return code — a process that legitimately exits `500` would be indistinguishable from JMeter failing to run it at all. ## The Timeout **Timeout** is in milliseconds and defaults to `0`, which means no timeout. A command that hangs therefore hangs the thread for the rest of the run. On any unattended plan, set a real value; on expiry the process is killed and the sample fails with `500`. ## What comes back - **Standard output (stdout)** and **Standard error (stderr)** name files. If a field is left empty, that stream is captured and returned as the sample's response data instead, where assertions and extractors can see it. - **Standard input (stdin)** names a file to feed the process. - **Working directory** defaults to the folder named by the `user.dir` system property. - **Environment Parameters** are key/value pairs added to the child process's environment. - The sampler data records the working directory, the environment and the exact command line it assembled, which is the first thing to read when a command behaves differently than it does in your terminal. ## No shell, no quoting This is the part that bites on the way to CI. The sampler passes the command and its parameters straight to the operating system: > *"The sampler deliberately does not do any parsing or quote handling. The command and its parameters must be provided in the form expected by the executable."* There is no shell in between, so wildcard expansion, pipes, redirection and quoting rules simply do not exist. Built-ins are not executables either — the Windows `DIR` command lives inside the command interpreter, so `DIR C:\TEMP` has to be entered as **Command** `CMD`, then parameters `/C`, `DIR`, `C:\TEMP`. The same plan will not be portable between operating systems, which is worth knowing before a `.jmx` written on a laptop is handed to a Linux CI runner. ## Where it goes wrong - **Check Return Code** left unticked, so a broken fixture script never fails a run. - `500` chosen as an expected code, colliding with JMeter's own error indicator. - A whole command line typed into **Command** as one string, so the OS looks for an executable with spaces in its name. - **Timeout** left at `0` on a command that can hang. - Forgetting that the command runs on the injector, so the sample's elapsed time measures local work, not the system under test.

  • Where does an OS Process Sampler's standard output end up?
    In the sample's response data, unless the **Standard output (stdout)** field names a file — in which case it is written there and not returned. Leaving the field empty is what lets a Response Assertion or an extractor work on the command's output. Standard error behaves the same way through its own field.
  • What does an OS Process Sampler Timeout of 0 mean, and what happens when a non-zero one expires?
    `0` means no timeout, so a hung command holds the thread until the test is stopped. With a value set, JMeter attempts to kill the OS process when it expires and the sample fails with response code `500` and the timeout's message. It is the same `500` used for launch failures, which is why that code should never be an expected return code.

saying these in an interview costs you the question

  • Assuming a non-zero exit status fails the sample by itself
  • Setting Expected Return Code to 500
  • Typing a full command line with arguments into Command
  • Expecting wildcards, pipes or quotes to be interpreted
  • Leaving Timeout at 0 on a command that can hang