-
-
Notifications
You must be signed in to change notification settings - Fork 632
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
startup files and XONSH_INTERACTIVE #4096
Comments
Hi @bestlem -- there's a |
No sorry I want to run xonsh in non-interactive mode but load the startup files e.g. ~/.config/rc.xsh - I can then test in the file to see if interactive or not |
Got it. We removed static config files a while back, but sounds like we might want to bring those back. |
I think we are still at cross purposes here or else we are using different names for startup files. The files I am talking about are still there and used by xonsh, looking at old documentation https://xon.sh/xonshconfig.html (well that's another bug)
I am talking about the run control file. The initialisation files e.g .xonshrc ~/.config/rc.xsh i.e. the files listed in $XONSHRC are still picked up if you don't provide a command or file on the command line. xonsh will then read the file and set $XONSH_INTERACTIVE from other shells I would expect these to be independent actions Although looking at history this decision was made long ago for 0.6.0 The changes start at 1f464fb I disagree with the comment - but my view does need to be checked. I tried Interactive is not the same as as reading startup files they are independant. Comment is As per discussions with @asmeurer -- if xonsh is being used to launch a script,
then it should not load the Basically, if you need a xontrib to be loaded for your script, load it in your |
Looking at other issues especially #3176 Interactive and possibly login shells are not used much in xonsh and have some rough edges. |
Also similar issue #3579 |
No this has nothing to do with the question in #3579 That refers to reading sh scripts from /etc/profile.d The questions states that existing environment variables are not read - which are in .sh files. The second comment does suggest that xonsh has something similar but that does not solve the actual problem. So I think that should be 2 separate items (I suspect that this is an example of why I think xonsh startup files are confusing as various concerns are not been separated) This is simply that the standard initial file is ONLY read when in interactive mode. The best description of startup files I see is zsh http://zsh.sourceforge.net/Doc/Release/Files.html#Files However even given that clearly in the official documentation Apple and Debian have put the environment settings the /etc/zprofile file (they just copied without thinking the POSIX setup) xonsh does not need separate files and then tset $XONSH_INTERACTIVE and $XONSH_LOGIN to choose what code to use. This is also how fish does startup files. https://fishshell.com/docs/current/index.html#initialization |
@bestlem could you give the examples of the commands with expected behavior aligned with other shells? In example: xonsh --interactive --flags some.xsh # This command should read the RC file than run xsh
xonsh some.xsh # this command should just run the xsh file
# etc |
@anki-code you are correct that is how xonsh runs now but other shells run the other way round, always loading the startup files in a well defined order. e.g. zsh http://zsh.sourceforge.net/Intro/intro_3.html (bash and other POSIX shells are similar woth different files) I am just showing the user's files in their HOME directory, there are defined places for system wide files zshenv command.sh # runs ~/.zshenv and then the shell zsh t.zsh outputs That is the default is ALWAYS load the default startup file. The other issue #3374 about multiple files is not an issue in zsh as there is only one file on the command line, that is what zsh executes after the startup file (usually just the .zshenv ones ) everything else after the command file is a parameter to that file fish https://fishshell.com/docs/current/#initialization-files is more similar to xonsh in that there is only one user startup file (default is ~/.config/fish/config.fish) and you use the status command to see if the shell is interactive or login . So your startup files test that and only do interactive (e.g. GUI) stuff if the interactive flag is set. fish is actually more complex as it does not just read a file - but also can be set up to read all scripts from ~/.config/fish/conf.d This is also needed as function as and aliases are usually setup to be in separate files. A similar setup to zsh using echo will give In summary other shells have defined startup files and always loads some of them. There is no flag to load a different startup file Given that xonsh only has the idea of one startup file I would look at the fish model but only load the one file. not a directory as fish needs to scan directories for its functions and aliases whilst xonsh uses normal python mechanisms for this. |
Thanks for the details @bestlem ! Let's try to understand what xonsh is doing and what you want to change. # Let's use docker to test in isolated environment
docker run --rm -it python:3.9-slim /bin/bash -c "pip install xonsh; /bin/bash"
# Prepare RC files and script:
echo 'print("Hello from /etc/xonshrc")' > /etc/xonshrc
echo 'print("Hello from ~/.xonshrc")' > ~/.xonshrc
mkdir -p ~/.config/xonsh
export XDG_CONFIG_HOME='/root/.config'
echo 'print("Hello from ~/.config/xonsh/rc.xsh")' > ~/.config/xonsh/rc.xsh
echo 'print("Hello from ~/custom_rc")' > ~/custom_rc
echo 'print("Hello from script.xsh")' > ~/script.xsh
# Tests:
xonsh ~/script.xsh
# Hello from script.xsh
xonsh -i ~/script.xsh
# Hello from /etc/xonshrc
# Hello from ~/.config/xonsh/rc.xsh
# Hello from ~/.xonshrc
# Hello from script.xsh
xonsh --no-rc ~/script.xsh
# Hello from script.xsh
xonsh --no-rc -i ~/script.xsh
# Hello from script.xsh
xonsh --rc ~/custom_rc -- ~/script.xsh
# Hello from script.xsh
xonsh -i --rc ~/custom_rc -- ~/script.xsh
# Hello from ~/custom_rc
# Hello from script.xsh
xonsh -i --rc ~/custom_rc --no-rc -- ~/script.xsh
# Hello from script.xsh Please copy this example (starting from "Test") and add the changes you suggest. For example: xonsh ~/script.xsh
# PROPOSE: Hello from ~/.xonshrc
# Hello from script.xsh To begin and end code blocks on Github we use three back quotes. Example: ```python code here ``` |
I think you have understood - the last example should have the proposed line. I am on an Apple Silicon Mac Mini so I can't run Docker yet. This also means that I have no reason to see if a shell is a login shell or not. From the others - we need to see what $XONSH_INTERACTIVE and $XONSH_LOGIN are. I think that these are set correctly but from other issues might not be available early enough in the script. The /etc/xonshrc - I have no view on - fish says don't do it. POSIX does use it. I am a programmer not a system administrator so only really manage one login so haven't thought about the pros or cons of having it. Re ~/.xonshrc and ~/.config/xonsh/rc.xsh - I am using the latter and I have no view on what happens if you have both. It is probably an error if you have both but I don't know what xonsh does now. I also note that you can supply several --rc files - again I have no view on this. I think other shells just read in one file or directory so there is no example to follow for multiple startup files. I think other shells don't allow config files on the command line, they just allow one file on the command line and that is equivalent to script.xsh, so again no example to look at. I will ignore ~/.xonshrc in the tests for simplicity # Tests:
xonsh ~/script.xsh
# PROPOSE: Hello from /etc/xonshrc
# PROPOSE: Hello from ~/.config/xonsh/rc.xsh
# Hello from script.xsh
xonsh -i ~/script.xsh
# Hello from /etc/xonshrc
# Hello from ~/.config/xonsh/rc.xsh
# Hello from ~/.xonshrc
# Hello from script.xsh
xonsh --no-rc ~/script.xsh
# Hello from script.xsh
xonsh --no-rc -i ~/script.xsh
# Hello from script.xsh
xonsh --rc ~/custom_rc -- ~/script.xsh
# PROPOSE : Hello from ~/custom_rc
# Hello from script.xsh
xonsh -i --rc ~/custom_rc -- ~/script.xsh
# Hello from ~/custom_rc
# Hello from script.xsh
xonsh -i --rc ~/custom_rc --no-rc -- ~/script.xsh
# PROPOSE - This is an error you can't have --rc and --no-rc in the same command
# or if xonsh does accept this command line (but what does --no-rc mean here?
# PROPOSE : Hello from ~/custom_rc
# Hello from script.xsh For a fuller test - set the config files to be more like if $XONSH_INTERACTIVE:
print("Hello interactive custom_rc")
if $XONSH_LOGIN:
print("Hello login custom_rc")
print("Hello custom_rc always") Then xonsh -i --rc ~/custom_rc -- ~/script.xsh
# PROPOSED : Hello interactive custom_rc
# Hello custom_rc always
# Hello from script.xsh
xonsh --rc ~/custom_rc -- ~/script.xsh
# Hello custom_rc always
# Hello from script.xsh Also just running the xonsh shell as your shell should give xonsh --rc ~/custom_rc
# Hello interactive custom_rc
# PROPOSED : If you run from the command line as here there should be no login print which the current xonsh does.
# Hello custom_rc always
$ .... |
Looking at premain() I note the test for --norc is combined with --rc so --no_rc means that --rc is not checked for. |
The rationale for the current startup looks like commits by gforsyth on 28 Sep 2017 These were presumably to fix an issue that arose then but I can't see a discussion other than the comment on 1f464fb As per discussions with @asmeurer -- if xonsh is being used to launch a script,
then it should not load the Basically, if you need a xontrib to be loaded for your script, load it in your |
This is based on the startup order described in xonsh#4096 (comment) and adds an (ugly) parameterised test which tries lots of different CLI combinations, and verifies which RC files (if any) get loaded, and in what order.
This is based on the startup order described in xonsh#4096 (comment) and adds an (ugly) parameterised test which tries lots of different CLI combinations, and verifies which RC files (if any) get loaded, and in what order.
* test_main: test lots of startup order combinations This is based on the startup order described in #4096 (comment) and adds an (ugly) parameterised test which tries lots of different CLI combinations, and verifies which RC files (if any) get loaded, and in what order. * test_script_startup: skip on windows
Not sure if this is the best issue to add to. However, the fact that xonsh has no way of doing non-interactive shell config breaks many things. Such as PATH setup for non-interactive sessions. In bash, many setups load interactive resources only after checking Was it expected that there should always be a parent interactive xonsh that sets up the env? My current problem is I cannot use xonsh as my default shell on a remote machine, because it breaks tools that use an ssh connection to connect to remote services (here libvirtd). Creating the ssh connection necessarily runs the shell. The tools expect a sh/bash like shell. Admittedly they have a bug in their invocation, but that bug does not break in sh/bash. https://gitlab.com/libvirt/libvirt/-/issues/273 Adding to this issue, because if I could use such rc files, I could fixup this bug locally with a function. |
What does I think that sort of hieroglyphics is a reason I use xonsh :) |
|
I want to leave here some nice representation of how it works in bash/sh/zsh from twitter post: |
After reading this thread and #5491, #5488, #5496, #5099. @bestlem sorry but you introduced statements that are wrong and because I feel pressure I want to break it all one by one:
Closing eyes on all of this I'm personally ok with #5099 (except #5491) and I want to help you with your use case but I can't see the use case (OS, list of commands, problem). |
I was use rc files as generic name for all startup files xonsh and fish do not have the split in files that zsh and bash has - so I was using rc files in fish/xonsh terms not the split between zshrc and zshenv zsh loads .zshenv in a non interactive shells (In practice I think I am only after the settings that go in here) I don't think xonsh is not nearer zsh than fish - I think this is where we look at things from differently - xonsh has one rc file zsh has several I see as the major difference. Out of the tools that I use fzf broot, iterm all in fish test for --is-interactiove in fish. I am starting to use nix and the setup there goes through and extra layer and that layer has curated many of the other tools to put them inside is interactive guards. I agree that not all do For zsh and bash the examples do >>~/.zshrc >>.bashrc so will not be loaded in non-interactive shells so zsh/bash does not have this issue. So the standard install only loads them for interactive use. zsh/bash does not need the explicit test if it is interactive or not - it does that by putting interactive commands in a different file than things that run non-interactive and interactive. The use case is the equivalent of .zshenv into non interactive shells ie loading in environment variables most obviously $PATH - this is made more obvious on macOS as there is not necessarily a login shell that set $PATH to be inherited into the script. Also if run from a service/cron - but that case is more complex and if you are doing that you are able to work out to use --no-rc or the default or be very explicit. re "Interactive mode and RC files are from parallel worlds and we need to just load all RC forever" In xonsh we do not have the split in files that zsh and bash does, xonsh is like fish in that they only way for the shell to work out whether to run stuff from the config if it is interactive or not is to make a test on $XONSH_INTERACTIVE the loading of rc files in xonsh has three states.
Is another case login shells? - I don't know the startup of X11 etc but aren't they non interactive and if so where do they get environment from. I suspect in practice no-one is using xonsh at that level as it is rather sh/bash dependent. So my end point is
|
@anki-code But you are not being explicit on thi - or perhaps given your emphasis on comments about loading ALL rc you might be. The issue is ~/.xonshrc does not contain JUST interactive stuff as bashrc and zshrc do. If you want that split you need to have two separate files. Currently xonshrc = zshenv+zprofile+zshrc but xonshrc ≠ zshrc which is what I think you are trying to implement. (given the bash diagram I won't try to work out what it is in bash) Another issue is that bash and zsh include both or none of ~/.zshrc and /etc/zshrc - I think you are trying to include /etc/xonsh/* but not ~/.xonshrc and I think that might be inconsistent. |
Now I understand our misunderstanding I think. At this time (here, now) I'm ok with #5099 and I have no plans to change this or doing split you described. I'm going to get popcorn and see what users say when they see unexpected loading of RC. It's not a sarcasm (or a bit) I'm really interesting. What I want in #5491 is to just reduce the uncontrolled unexpected unintended stream of errors that will be produced by "user error" because of current expectation in the world that home based So it looks like we have no direct contradictions now. |
I apologise for wasting lot of time here. Looking at what I wrote in 2021 that does agree with @anki-code. But I think not what was implemented then did not match my example. I made a mistake in not fully testing and reading what I said in my examples. I assumed that xonsh would read only one of only ~/.config/xonsh/rc.sh and ~/.xonshrc as I thought only one would be loaded. So missed exactly what was going on. As I never have both I have never seen that. So in the latest comments I was considering ~/.config/xonsh/rc.sh only and @anki-code is looking at both. I am also confused - in that is all the patch does is actually implement what was in the suggestions that ~/.xonshrc is not loaded when running a script? However the new documentation does make it a bit clearer in that .xonshrc and ~/.config/xonsh/rc.xsh are treated differently and are both loaded. It will be surprising to some that both to some that both are loaded but that has been the case for some time. We have ended up with a mixture of how bash/zsh and fish deal with it and it is a unique way, but so is xonsh and I don't think anyone has got it fully correct. (Whatever it is better than bash anyway) |
Yes, the key is here: # Defaults
$XONSHRC
# ('/etc/xonsh/xonshrc', '/USERHOME/.config/xonsh/rc.xsh', '/USERHOME/.xonshrc')
$XONSHRC_DIR
# ('/etc/xonsh/rc.d', '/USERHOME/.config/xonsh/rc.d') All of these will be executed both interactive or non-interactive modes (#5099). My last question: does current behavior solve your case? |
For testing I think I have done fuller checks here. This is on xonsh 0.16.0 running on zsh and a brand new VM of macOS - just MacPorts and Xode command line tools installed. script.xsh is
All the config files - ~/.xonshrc, ~/.config/xonsh/xsh.rc and ~/custom_rc are
I think we need 6 tests of the flags a)interactive or not - against b)3 rc states (however see the end of this comment I assumed that command line flag order does not matter but it does)
I think @anki-code wants to just change the first one to remove ~/.xonshrc and change no other results.
However whilst we are here. Note the 5th one |
Current behaviour solves my case - albeit accidentally - I don't use ~/.xonshrc What does confuse me now is your comment
Doesn't your change mean that users would now see a unexacting NON loading of RC, the change does not load any new rc just less than currently. |
Nope. Sorry, it was personal joke about popcorn. I just know persons who are using xonsh home based
Perfect. Thank you for attention to this case and improvements! |
|
### Motivation In #5099 was introduced the logic where all RC files are loaded in interactive and non-interactive modes. This logic is not working good for home based `~/.xonshrc` file. First of all `~/.xonshrc` is the buffer/accumulator of settings focused on interactive mode. Most tools with integration with xonsh (e.g. `conda`, `zoxide`, etc) offer to just do `echo "init_tool()" >> ~/.xonshrc` (`conda` has around 20 lines of init code) to start using the tool and users are doing this without any doubts. But because of after 5099 `~/.xonshrc` is executed in non-interactive mode the adding code to it leads to unexpected and unintended side effects: * If you run a script with shebang (e.g. `#!/usr/bin/env xonsh` or [xonsh-awesome-cli-app](https://github.com/anki-code/xonsh-awesome-cli-app)) or just from `xonsh script.xsh` the code will be unexpected and unintended slower. * If you're using xonsh-based tools (e.g. you install them using pip) and run them in environment that has no packages that initiated in `~/.xonshrc` you will see epic errors. * Additional context: * Bash and Zsh do not load `~/.bashrc` and `~/.zshrc` in non-interactive mode by the same reasons. * We have welcome message `Create ~/.xonshrc file manually or use xonfig to suppress the welcome message` and we don't want to make the process of creating this file complex. All of this leads to bad unexpected and unintended experience. This PR is to fix this. ### Expectation By doing this fix we assume that experienced user who wants to build good repeatable run control files will use another ways to create config files and this has [reflection in docs](https://github.com/xonsh/xonsh/blob/8860f2bd5273d5f3fc08ccf6be6af8163bfec0bd/docs/xonshrc.rst). In the nutshell if you want to create the RC files that affect every run of code you should use one or many of these ways: * Cross-desktop group (XDG) compliant `~/.config/xonsh/rc.xsh` control file. * The system-wide control file `/etc/xonsh/xonshrc` for Linux and OSX and in `%ALLUSERSPROFILE%\xonsh\xonshrc` on Windows. It controls options that are applied to all users of Xonsh on a given system. * The home-based directory `~/.config/xonsh/rc.d/` and system `/etc/xonsh/rc.d/` can contain .xsh files. They will be executed at startup in order. This allows for drop-in configuration where your configuration can be split across scripts and common and local configurations more easily separated. In your configs you need to check `$XONSH_INTERACTIVE` and `$XONSH_LOGIN` explicitly. ### Before `~/.xonshrc` is used in non-interactive mode. ```xsh echo "echo RC" >> ~/.xonshrc cd /tmp echo "echo Script" > script.xsh xonsh script.xsh # RC # Script ``` ```xsh cd /tmp echo 'echo RC' >> ~/.xonshrc echo '#!/usr/bin/env xonsh' > myscript chmod +x myscript ./myscript # RC ``` ### After `~/.xonshrc` is not used in non-interactive mode. Use `-i` if you need it. ```xsh echo "echo RC" >> ~/.xonshrc cd /tmp echo "echo Script" > script.xsh xonsh script.xsh # Script xonsh -i script.xsh # RC # Script ``` ```xsh cd /tmp echo 'echo RC' >> ~/.xonshrc echo '#!/usr/bin/env xonsh' > myscript chmod +x myscript ./myscript ``` Closes #5488 #4096 #5496 ### Fun I want to leave here some nice representation of how it works in bash/sh/zsh from [twitter post](https://twitter.com/paxx39/status/1742768007154479109): ![image](https://github.com/xonsh/xonsh/assets/1708680/cd7b3803-483f-4d5d-bf9d-baa61c794f68) ## For community ⬇️ **Please click the 👍 reaction instead of leaving a `+1` or 👍 comment** --------- Co-authored-by: a <1@1.1> Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Ah, it's not a bug. @bestlem cd /tmp
echo 'echo 1' > 1.xsh
xonsh --rc 1.xsh 1.xsh # run interactive with two rc files
# 1
# 1
# prompt
xonsh --rc 1.xsh -- 1.xsh # run script with one rc file
# 1
# 1 |
OK you need -- to run a script after --rc. Every thing after --rc until a -- is treated as a config file. Makes sense , however not documented I think |
I am trying to use xonsh as my shell.
Interactive use works well and as expected.
But xonsh does not seem to read any startup files if it is launched non interactively. This differs from POSIX shells and fish where the .profile .zshenv and other config files are read in all cases.
I want to be able to control my configuration when I run say a compile process from my editor or from cron and then test on $XONSH_INTERACTIVE to control what is done.
How do I read startup files when run such that $XONSH_INTERACTIVE == False
I know there there is a --rc flag but not all tools all extra parameters to be passed in other than the command to be run.
For community
⬇️ Please click the 👍 reaction instead of leaving a
+1
or 👍 commentThe text was updated successfully, but these errors were encountered: