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.