Viewing a Go Program’s Command Line with /debug/pprof/cmdline
Learn how Go’s net/http/pprof cmdline endpoint exposes process argv, how to inspect NUL-separated output, troubleshoot access, and protect sensitive deployment details.
The /debug/pprof/cmdline endpoint reports the command-line arguments used to start the currently running Go process. It is a small but useful deployment-context check: before collecting CPU, heap, or goroutine data, you can confirm which executable and startup options are actually active.
This endpoint reports startup arguments, not a complete configuration dump. It does not directly show environment variables, the contents of configuration files, HTTP request parameters, or profiling data.
What the cmdline endpoint is for
In operating-system terminology, argv is the ordered argument vector supplied to a process when it starts. The cmdline handler returns that vector for the Go process serving the request.
This can answer questions such as:
- Which executable or program name started this process?
- Was the intended configuration file passed as an argument?
- Is the service using the expected listen address?
- Was a feature switch or operating mode enabled?
- Did the inspected replica receive the startup arguments expected by the deployment?
The result is evidence about process startup. It is not necessarily evidence about the current effective configuration. A service may later reload a file, receive remote settings, or change an in-memory value without changing its original argv.
What it does not report
| Configuration source | Visible through cmdline | Example | Debugging implication |
|---|---|---|---|
| Startup argument | Usually yes | --config=/etc/service/config.yaml | Startup flags and their values can be verified directly. |
| Environment variable | No | SERVICE_MODE=production | Inspect the process environment or application status separately. |
| Configuration file | Only its argument or path, if supplied | /etc/service/config.yaml | The endpoint does not reveal the file contents or which values won precedence. |
| Built-in default | No | A default timeout compiled into the program | A missing flag does not mean the setting is absent; a default may be active. |
| Runtime reload or remote configuration | No | A setting delivered by a control plane | Use application status, logs, or configuration-specific diagnostics. |
Where the endpoint comes from
net/http/pprof is a Go standard-library package that exposes HTTP debugging and profiling handlers. The usual path for this handler is /debug/pprof/cmdline.
A blank import loads the package for its initialization side effects:
import _ "net/http/pprof"
That import registers the pprof handlers on Go’s http.DefaultServeMux, also called the default ServeMux. A server that passes nil as its handler to http.ListenAndServe uses this default mux.
go func() {
_ = http.ListenAndServe("127.0.0.1:6060", nil)
}()
In this example, pprof is available on a loopback-only diagnostics listener. An operator on the same host can query port 6060, while the public application listener can remain separate.
Default mux versus custom mux
A custom ServeMux is an application-created HTTP multiplexer, commonly made with http.NewServeMux(). Registering pprof on the default mux does not automatically add those handlers to a custom mux.
mux := http.NewServeMux()
// Register the desired pprof handlers explicitly, or run a separate
// diagnostics server with http.DefaultServeMux.
If the application serves only mux, a blank import by itself may not make /debug/pprof/cmdline available on that server. The application must explicitly wire the desired pprof handlers, or expose http.DefaultServeMux through a separate diagnostics server. The exact registration approach depends on the handlers and routing policy the application chooses.
For an overview of the available handlers, see the pprof index.
Response format: an argv vector separated by NUL bytes
The response represents arguments in order, with a NUL byte between adjacent arguments. A NUL byte is the zero byte, written as \x00 in many tools. The response is commonly served as text/plain, but it is not line-oriented text.
For example, a process might have this argument vector:
argv[0] = /usr/local/bin/orders
argv[1] = --config
argv[2] = /etc/orders/config.yaml
argv[3] = --listen
argv[4] = 127.0.0.1:8080
argv[5] = --display-name
argv[6] = nightly orders service
The raw response is conceptually:
/usr/local/bin/orders\x00--config\x00/etc/orders/config.yaml\x00--listen\x00127.0.0.1:8080\x00--display-name\x00nightly orders service
The spaces in nightly orders service do not create additional arguments. That value remains one argv element because argument boundaries are marked by NUL bytes, not spaces.
Shell quoting used when the process was launched is not preserved. For example, a launcher command containing --display-name "nightly orders service" supplies the post-shell value nightly orders service. The endpoint reports that value, not the quote characters or the original shell syntax.
Browsers and ordinary terminal output may show NUL delimiters as odd characters, suppress them, or make the result look like one run-on string. Render the bytes deliberately when inspecting the response.
Accessing and inspecting the endpoint
Fetch the raw response locally
curl --silent http://127.0.0.1:6060/debug/pprof/cmdline
If pprof is attached to the application listener instead, replace the address and port with that listener. If it is on a separate diagnostics port, query that port directly:
curl --silent http://127.0.0.1:6060/debug/pprof/cmdline
When a reverse proxy exposes a protected internal route, use the proxy’s approved internal hostname and path rather than assuming that the public application address serves pprof.
Render one argument per line
curl --silent http://127.0.0.1:6060/debug/pprof/cmdline | tr '\0' '\n'
This changes only the display representation. It replaces each NUL separator with a newline so that each argv element is easier to inspect. Do not split the response on spaces; doing so would destroy the true boundaries of values that contain spaces.
Inspect the raw bytes
curl --silent http://127.0.0.1:6060/debug/pprof/cmdline | od -An -t x1c
The byte-oriented output lets you verify that separators are zero bytes. It is useful when a terminal renders the response confusingly or when an argument contains non-printing characters.
Preserve boundaries in shell processing
Tools that understand NUL-delimited input can preserve argument boundaries. For example, a NUL-aware command can consume the response with an option such as -0 or --null, when that option is supported. Avoid command substitutions that rely on whitespace splitting when exact argv boundaries matter.
Interpreting common output
The first item is conventionally the executable path or program name, known as argv[0]. It may be an absolute path, a relative path, or simply a program name, depending on how the process was launched.
Remaining items are positional arguments and flags. A flag may occupy one argument with its value in the same element, such as --config=/etc/orders/config.yaml, or two elements, such as --config followed by /etc/orders/config.yaml. The endpoint reports whichever form the program received.
argv[0] = /usr/local/bin/orders
argv[1] = --config=/etc/orders/config.yaml
argv[2] = --listen
argv[3] = 127.0.0.1:8080
argv[4] = --display-name
argv[5] = nightly orders service
In this example, argv[5] is one argument despite containing two spaces. This distinction matters when verifying a deployment command, wrapper script, or feature flag.
Using cmdline during deployment debugging
Suppose an orchestration configuration is expected to start a service with --config=/etc/orders/prod.yaml and --mode=active. Render the endpoint into separate lines and check whether those exact argument values appear.
If they do appear, startup argument delivery is probably not the source of the mismatch. Continue by checking file contents, environment variables, defaults, precedence rules, and runtime reload behavior.
If they do not appear, verify the queried instance and listener. A load balancer may route you to another replica. A container entrypoint or supervisor may also alter the command before the Go binary starts. The Go process’s argv can differ from the command shown in orchestration metadata or from the arguments of a wrapper process.
Supervisor and container boundaries
The endpoint describes only the Go process that serves the request. It does not necessarily describe:
- A shell or wrapper that launched the Go binary.
- A supervisor’s own process arguments.
- A container runtime’s complete entrypoint metadata.
- Arguments belonging to a sidecar or another process in the same workload.
Compare the returned argv with the runtime process list, container metadata, routing information, and instance identity before concluding that the deployment is incorrect.
Security and operational exposure
Command-line arguments are often visible to operators and, on some systems, to other users with process-inspection privileges. They may contain database URLs, access tokens, passwords, tenant identifiers, internal file paths, or deployment details.
Public exposure is risky even though this endpoint does not return CPU samples, heap samples, or goroutine profiles. Startup arguments can disclose credentials and useful information about internal infrastructure.
Prefer these controls:
- Bind a diagnostics listener to
127.0.0.1when only local access is required. - Place pprof on a private diagnostics network or dedicated diagnostics port.
- Require authentication and authorization through a protected administrative proxy.
- Restrict source networks with firewall or reverse-proxy policy.
- Avoid putting secrets in command-line flags.
- Use an appropriate secret-delivery mechanism, such as a protected file, credential store, or secret service, while considering the permissions and lifecycle of that mechanism.
location /debug/pprof/ {
allow 10.0.0.0/8;
deny all;
proxy_pass http://127.0.0.1:6060;
}
This reverse-proxy example illustrates network restriction, not a complete authentication policy. Combine allowlists with authentication, TLS, logging, and least-privilege access where appropriate.
Relationship to other pprof diagnostics
| Endpoint | Primary output | Typical debugging question | Sensitive information considerations |
|---|---|---|---|
/debug/pprof/ | Index and navigation to diagnostic handlers | Which pprof handlers are available? | Reveals that diagnostics are enabled and may list useful endpoints. |
/debug/pprof/cmdline | Process argv | How was this Go process started? | May expose secrets, paths, flags, and deployment details. |
/debug/pprof/profile | CPU profile over a sampling interval | Where is the process spending CPU time? | Profile data can reveal implementation and workload details. |
/debug/pprof/heap | Heap and allocation profile data | What objects and allocation sites use memory? | May expose application behavior and data-related details. |
/debug/pprof/goroutine | Goroutine profiles or stack information | Which goroutines are blocked, running, or stuck? | Stacks can reveal internal paths, services, and request context. |
/debug/pprof/trace | Go execution trace | How did scheduling and execution behave over time? | Trace data can reveal timing, workload, and internal activity. |
Use cmdline as an initial deployment-context verification step. Once you know that you are querying the intended process with the intended startup mode, choose the profile or trace that answers the performance question.
Limitations and platform considerations
- The endpoint reflects how the process was started, not necessarily its current effective configuration.
- Argument availability and exact representation depend on operating-system process semantics and runtime behavior.
- An empty or minimal result does not prove that the service has no configuration. Settings may come from environment variables, files, defaults, or remote services.
- The endpoint reports the Go process serving the request, which may differ from a supervisor, wrapper, container entrypoint, or sidecar.
- It is not a substitute for an authenticated configuration or status endpoint when current settings must be verified.
Troubleshooting
HTTP 404 for /debug/pprof/cmdline
- Check that
net/http/pprofwas imported or that the handlers were registered explicitly. - Confirm which listener serves pprof. The application port may not be the diagnostics port.
- If the application uses a custom mux, verify that the cmdline handler was wired into that mux, or query a separate server using
http.DefaultServeMux. - Check reverse-proxy routing and path restrictions.
The output is a run-on string or contains odd characters
The response uses NUL separators, which many viewers do not render as line breaks. Use tr '\0' '\n' for readable lines or od to inspect the bytes. Do not split on spaces.
An expected setting is missing
The setting may come from an environment variable, configuration file, built-in default, or remote configuration. It may also have changed after startup. Inspect the relevant source and application status, and verify that the queried process, host, replica, and listener are the intended ones.
The endpoint reveals a secret
Rotate the exposed credential, restrict or disable external pprof access, and move secret delivery away from command-line arguments. Treat command-line values as potentially observable operational data.
The executable or flags differ from the deployment command
A wrapper, supervisor, or container entrypoint may have transformed the command. Compare the Go process argv with runtime process information and orchestration metadata, then confirm that routing did not send the request to a different instance.
Summary
/debug/pprof/cmdlinereturns the running Go process’s ordered startup arguments, or argv.- Arguments are separated by NUL bytes, not newlines or spaces.
- Use
curl,tr, andodto fetch, render, and verify the response. - A blank import commonly registers pprof on
http.DefaultServeMux; custom muxes require explicit wiring. - The endpoint confirms startup context but does not reveal all current process configuration.
- Protect pprof because command-line arguments can contain sensitive credentials and deployment information.
After checking startup context, continue with the pprof handlers appropriate to the incident. Other runtime variables may be available through /debug/vars/, while an application’s pprof navigation page can be viewed at the default pprof view.