I have some Python code that does: (this is a simplified version)
shell = os.environ['SHELL']
os.environ['PATH'] = ... # some new PATH value
if call(shell, '-c', 'program_that_checks_that_PATH_is_sane'): # hasn't been mangled by the rcfile
sys.exit('fix your .bashrc|.zshrc|.config/fish')
call(shell) # drops the user in a shell
I foolishly believed that $SHELL -c would've been enough for my purposes, but I recently discovered that the PATH check wasn't working on bash
I tried to look at some of the suggested solutions, but bash is much more brittle than i expected
Basically, I discovered that BASH_ENV, or manually sourcing with bash -c "source ~/.bashrc; do_your_stuff" won't work if some errors can be triggered by the sourced file
These same errors are not a problem if invoking bash interactively (that is, bash -i will ignore errors, and bash -c will silently fail). But bash -i is not a workable solution (I guess that this is because bash -i will "steal" the stdin, thus stopping the invoking python process)
The solution can't also simply be "don't use a broken ~/.bashrc":
- The code has to be robust in face of poorly configured environments
- This happens with a default
.bashrc, like the one supplied by ubuntu (this is an old version)
The error actually happens (found it by set -xe before sourcing) inside /usr/share/bash-completion/bash_completion at this line: [[ -f /etc/slackware-version ]] && sysvdirs=( /etc/rc.d ) (how can this fail the process of sourcing is beyond me)
After lots of tweaking, I found out how could I detect such errors when sourcing:
set -e && . ~/.bashrc & wait %% ; echo $?
Weirdly, the following will fail instead:
set -e ; . ~/.bashrc & wait %% ; echo $?
Still, this isn't good enough, because neither
bash -c "set -e && . ~/.bashrc & wait %% ; echo \$?"
call(['bash', '-c', 'set -e && . ~/.bashrc & wait %% ; echo $?'])
will print a nonzero exit code. I'd also prefer to avoid to rely on shell specific code like this.
How can I make sure that when invoking bash -c the .bashrc will be correctly loaded?
As an alternative to this whole issue, I'm thinking of munging the .{bash,zsh}rc, to identify problems with the PATH. It's a poor solution, but it'd cover 90% of the cases, and avoid forking extra processes.
import re
r = '^export PATH\s?=\s?([^:]+:)+(\$PATH|\${PATH})'
g = re.match(r, 'export PATH=/usr/bin:$PATH').groups()
any(check_collision(x[:-1]) for x in g[:-1])
Aucun commentaire:
Enregistrer un commentaire