Skip to content

Installer modifies ~/.profile which is ignored for graphical terminals #2106

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

Closed
malaire opened this issue Nov 1, 2019 · 19 comments · Fixed by #2387
Closed

Installer modifies ~/.profile which is ignored for graphical terminals #2106

malaire opened this issue Nov 1, 2019 · 19 comments · Fixed by #2387

Comments

@malaire
Copy link

malaire commented Nov 1, 2019

Problem
When running installer using curl https://sh.rustup.rs -sSf | sh in Debian 10 "Buster", installer adds a line to modify PATH in ~/.profile. That file is not used at all in graphical terminals, so this is wrong. I would expect modified PATH to be active in both login shells and graphical terminals.

Steps

  1. run curl https://sh.rustup.rs -sSf | sh accepting defaults
  2. restart computer
  3. start graphical terminal, see that PATH has not been modified

Possible Solution(s)
The line to modify PATH needs to be added to ~/.bashrc instead of ~/.profile.

Notes

Output of rustup --version: none, as rustup is not in PATH
Output of rustup show: none, as rustup is not in PATH

@malaire malaire added the bug label Nov 1, 2019
@kinnison
Copy link
Contributor

kinnison commented Nov 1, 2019

I agree that this isn't ideal. We actually modify any/all of:

  • .profile
  • .bash_profile (if it exists)
  • .zprofile (if zsh)

I suppose in theory we should actually edit .bashrc and .zprofile instead. Hmm.

@kinnison
Copy link
Contributor

kinnison commented Nov 1, 2019

If someone wants to work on this, I'd suggest we ought to UNDO the change to .profile at the same time as adding to .bashrc so that might need some clever upgrade processing in src/cli/self_update.rs

Come along to the Discord and/or discuss here for further input.

@c3st7n
Copy link

c3st7n commented Nov 1, 2019

Am I correct in understanding that you are suggesting the installer actively removes the export line that adds the cargo bin directory to PATH in .profile if present and the user also has a .bashrc file?

@kinnison
Copy link
Contributor

kinnison commented Nov 3, 2019

I guess if we're going to add it to .bashrc then either it shouldn't exist in .profile or else we need to have a cleverer line to add which only adds $CARGO_HOME/bin if it's not already in the PATH.

@xiongmao86
Copy link

xiongmao86 commented Mar 20, 2020

If I remember correctly, terminal of mac os would be using .bash_profile. It is usually a non-login shell.

@workingjubilee
Copy link
Member

workingjubilee commented Apr 27, 2020

Hi, this past winter I got sniped by the "incorrectly modifying the wrong .bashrc/.profile/whatever file" issue. It took a surprising amount of executive function to figure out what was up and fix it for myself, in spite of being "easy", so I'd like to work on fixing this for everyone... and for myself, in case I ever forget this.

My understanding is currently:
If we're handling a Unixy environment, we can kiiinda set aside worrying about Windows compat being weird for this concern, hopefully, as long as we don't do anything too exciting, as hypothetically if we're worrying about .bashrc on Windows we'll be on some repackaging of Linux or BSD tools on a Windows platform.

There are three main Unix environments of concern:
Darwin (MacOS),
Linux,
(Free|Net|Open)BSD.
Of these, the "login shell" logic is almost universal for Linux, and I believe that the BSD clan shares the same logic. So we just need to see
if we're on Darwin
then
we can edit .bash_profile and the like instead. Except Mac now uses zsh by default, so that might be different... modifying all the kinds of .profile-flavored files we find is still a safe bet, unfortunately.
else
we can sniff the environment further, but we're probably on Linux, and similar logic will probably work fine on FreeBSD as well. If not, they know where we live, for better or worse. 😅 So we modify the .shrc-flavored files. There's still an off chance, however, that the graphical terminal will load a .profile-flavored file instead, but hopefully in those cases the .bashrc will also be loaded. I'm seeing some indications this was an issue before, though?
fi

as a one time thing for updating: we apply a similar logic, sniff around, and maybe ask the user if they'd like us to revert our previous mistake helpful command insertion? My main concern is doing that in a truly "one-shot" or easily configurable manner, it would be best otherwise to simply avoid updating incorrectly.

I'll be on the Discord to ask further questions in a more sync manner.

@jyn514
Copy link
Member

jyn514 commented Apr 28, 2020

I think choosing the file to modify based on the platform is not the right approach. For example, in #2311 I was using CentOS, not a BSD, there's no way to tell that from the operating system alone. Instead I think rustup should read the SHELL environment variable which should work in all Unix like environments.

@jyn514
Copy link
Member

jyn514 commented Apr 28, 2020

I guess if we're going to add it to .bashrc then either it shouldn't exist in .profile or else we need to have a cleverer line to add which only adds $CARGO_HOME/bin if it's not already in the PATH.

I don't think existence of a .bashrc should be taken as an indication that the default shell is bash. In many cases this file is copied from /etc/skel when the user was first created, and just never deleted if the user changed their default shell. Reading SHELL is much simpler and more accurate.

@jyn514
Copy link
Member

jyn514 commented Apr 28, 2020

Note also that putting it in .bashrc alone will stop it from being seen by other shells such as dash, which is usually the non-interactive shell on Debian-based systems. Unfortunately it seems like the only way to have both is to check in both .profile and the rcfile (usually .bashrc but could be .zshrc or something exotic like .cshrc) if cargo is in PATH and not adding it if so. See https://github.com/jyn514/dotfiles/blob/master/config/profile#L3 for an example of what this could look like. Alternatively you could just have two copies of the directory in PATH which doesn't hurt anything.

@workingjubilee
Copy link
Member

Aha. Reading the SHELL env var as the main point of guidance works for me, but still have a bit of nervousness about that solution though due to Apple choosing to act Very Weird however and only read profile.

@jyn514
Copy link
Member

jyn514 commented Apr 28, 2020

Actually it looks like some apps will read .bashrc and some will read .bash_profile 🤦 https://scriptingosx.com/2017/04/about-bash_profile-and-bashrc-on-macos/

In that case there doesn't seem to be a good way to choose only a single file, since it's not even dependent on the shell but on the terminal emulator. IMO (as someone who isn't part of rustup and doesn't have to deal with angry users :P) this seems like too much of an edge case to support.

Note also that this is a bit of an unbounded problem in that anyone can write a shell and ask you to support it, for example fish has a different syntax from bash has a different syntax from tcsh.

@workingjubilee
Copy link
Member

Yes, that is why I formulated an intention of detecting *_apple_darwin environment and doing something different there.

And I am not a part of wg-rustup either! Yet I am working on fixing it, because no one else has, as wg-rustup effort has mostly been tied up in other tasks. Almost like it's some sort of community-project driven forward mostly by the effort of volunteers! 💦

@kinnison
Copy link
Contributor

I'd suggest that the best thing we could do would be to make .cargo/env be idempotent (i.e. if you source it more than once, it doesn't add itself to the path over and over) and then simply add instructions to source it from as many places as possible (.bashrc .bash_proifile .profile .zshenv etc)

@workingjubilee
Copy link
Member

workingjubilee commented Apr 28, 2020

OK, so apparently MacOS does something different now as of Catalina. I asked a MacOS Catalina user to go over their stuff and for their Terminal.app, their .zshrc was consistently sourced, both by their default and brew installed zsh, and so was their .bashrc (when loading bash). This was universal across all of their terminal apps, actually. As a result I am inclined to think that prioritizing rcfile manipulation (over *profile manipulation) and merely adding an additional caution to Mac users is sufficient, rather than special-casing their behavior overmuch.

I was examining an offered example, another project (starship) handles a similar problem by having an init binary which is eval'd and returns appropriate shell commands. This is slightly spooky to me, but on the other hand it would allow .cargo/env to not become split into several different shell scripts, and to have inspecting the path variable to see if it needs the path added be handled by a Rust program (so it can just use std::env to check the shell's paths, and then decide to not emit shell commands), so it could be a maintenance boon.

@workingjubilee
Copy link
Member

workingjubilee commented Apr 29, 2020

Here's the results of my investigation of {rc,pro}file usage over the suite of shells that commonly come with Rust supported platforms. I will be including a further expansion of my reasoning in my actual commits, but I thought I would leave the notes here in case some other poor benighted soul trawls this issue.

# POSIX, Non-Specified
/etc/profile
~/.profile

# Bash, Login
/etc/profile
~/.bash_profile || ~/.bash_login || ~/.profile
# Bash, Interactive Non-Login
~/.bashrc

# zsh, Always
/etc/zshenv
($ZDOTDIR | $HOME)/.zshenv
# zsh, On Interactive
($ZDOTDIR | $HOME)/.zshrc
# zsh appears to source .zshrc in interactive shells, even login shells.
# So .zprofile is irrelevant.

# tcsh, Always
/etc/csh.cshrc
~/.tcshrc || ~/.cshrc 

@rbtcollins
Copy link
Contributor

See also #975 (comment)

@rbtcollins
Copy link
Contributor

We should probably figure out how to play nice with nushell at some point.

@workingjubilee
Copy link
Member

workingjubilee commented May 1, 2020

ion shell is the shell for Redox which is a build target of Rust, so I would prioritize that over Nushell, tbh. I don't intend on handling either though (for this anyways).

@workingjubilee
Copy link
Member

OK, should be finishing up here soon after Suddenly, Learning More About Modules while I was futzing with refactoring things, but for note to the future: reading $SHELL won't work here because rustup-init.sh may pipe to a different shell than the user's default shell (this is, at minimum, the case on Debian systems).

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

Successfully merging a pull request may close this issue.

7 participants