Skip to content

env: trace the environment changes under -v - #14401

Open
Socialpranker wants to merge 1 commit into
uutils:mainfrom
Socialpranker:env-verbose-cleaning-environ
Open

env: trace the environment changes under -v#14401
Socialpranker wants to merge 1 commit into
uutils:mainfrom
Socialpranker:env-verbose-cleaning-environ

Conversation

@Socialpranker

Copy link
Copy Markdown
Contributor

-v printed only the exec, not what it had just done to the environment:

$ env -v -i true          # GNU
cleaning environ
executing: true
   arg[0]= 'true'
$ env -v -i true          # uutils, before
executing: true
   arg[0]= 'true'

$ env -v -u A -u B FOO=1 true     # GNU
unset:    A
unset:    B
setenv:   FOO=1
executing: true
   arg[0]= 'true'
$ env -v -u A -u B FOO=1 true     # uutils, before
executing: true
   arg[0]= 'true'

The fix

apply_removal_of_all_env_vars, apply_unset_env_vars and
apply_specified_env_vars take the existing do_debug_printing flag and
emit their line, in the order they already run — which is the order GNU
prints them in. Column padding matches GNU (unset: and setenv: pad to
the width of executing:), and neither name nor value is quoted.

-i is a special case: it has already emptied the environment, so GNU
prints cleaning environ and no unset: lines at all. That is reproduced.

How the GNU behavior was established

By running the installed GNU coreutils 9.11 binary (Homebrew, genv) as a
black box over 11 combinations of -v, -i, -u and NAME=VALUE,
including -i with -u, several -u, a value containing a space and a
quote, and -v -i with no command, diffing stderr byte for byte against
uutils. All 11 now match. I did not read GNU coreutils source.

Testing

  • New test_debug_traces_environment_changes in
    tests/by-util/test_env.rs: the -u/assignment trace, the -i trace,
    the -i plus -u case that must log no unset, and the no--v case
    that must stay silent. Mutation-checked: reverting env.rs alone makes
    it fail.
    test_debug2_part_of_string_arg gains the setenv: line it now emits.
  • cargo test --features env --test tests test_env: 103 passed, 0 failed.
  • cargo clippy -p uu_env --all-targets -- -D warnings: clean.
  • cargo fmt --check: clean.
  • Differential A/B against GNU coreutils 9.11 over the 16 env
    invocations in my harness: mismatches 3 -> 2.

Not in scope

The two remaining mismatches are unrelated to -v: env A=1 -- printenv A
adds a use -[v]S to pass options in shebang lines line GNU does not
print, and env -S '\techo x' unescapes the \t in the program name it
reports as missing.

Disclosure

Prepared with AI assistance (Claude Opus 5, via Claude Code), per the AI
policy in CONTRIBUTING.md. Every GNU behavior quoted above came from
running the installed binary, not from reading GPL source. All testing was
run locally.

-v printed only the exec, not what it did to the environment first, so
the three lines GNU emits before it were missing:

    $ env -v -u A FOO=1 true
    unset:    A
    setenv:   FOO=1
    executing: true
       arg[0]= 'true'

and 'cleaning environ' for -i. The individual unsets are not logged when
-i is in effect, since it has already emptied the environment.
@github-actions

github-actions Bot commented Sep 5, 2026

Copy link
Copy Markdown

GNU testsuite comparison:

Skip an intermittent issue tests/cut/bounded-memory (fails in this run but passes in the 'main' branch)
Skip an intermittent issue tests/date/date-locale-hour (fails in this run but passes in the 'main' branch)
Skipping an intermittent issue tests/tail/tail-n0f (passes in this run but fails in the 'main' branch)
Congrats! The gnu test tests/tail/pipe-f is now passing!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants