Corner case with bash-as-shebang from makeWrapper

I stumbled into a bash corner-case while setting up nix-based CI for the oil shell project. I’m mostly posting to document it somewhere, though it may also have some bearing on the idea I’ve seen previously of using a small C program as a wrapper.

Specifically, I’m debugging a few tests that break in Nix but not existing non-nix CI. The tests are part of a suite that compares behavior of multiple shells (they vary from test to test, but include: oil’s own osh, bash, mksh, dash, zsh, and busybox ash).

For each shell, each test does something like:

  • set/export PS1="" (to simplify comparing output from different shells, I think)
  • run commands in the shell
  • check the output

I eventually traced the problem back to bash: when non-interactive (and thus in any Nix-built/patched wrapper) it unsets PS1 (and PS2) on init.

FWIW, I only see this behavior from bash and bash-as-sh. (If you’re curious, you can run something like for shell in bash csh dash fish ksh mksh sh tcsh zsh; do env -i PS1="test" $shell -c 'printf "%5.5s: %s\n" $0 $PS1' 2>/dev/null; done).

My current workaround:

  • create an additional overridden bash, patched to disable this behavior (just using substituteInPlace to comment out two lines in shell.c)
  • substitute it into the relevant wrappers after the calls to makeWrapper

Aside from just writing the wrappers from scratch, I’m curious if anyone has better workaround ideas.