Skip to content

Enable use of pwsh as login shell #186

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

Merged
merged 8 commits into from
Aug 5, 2019

Conversation

SteveL-MSFT
Copy link
Member

No description provided.

@TylerLeonhardt
Copy link
Member

TylerLeonhardt commented Jun 15, 2019

So is the intent that I'll be able to do:

chsh pwsh-login

And then I'll have PowerShell as my login shell with all the environment goodness?

Is that something that we'll ask the users to do?

@joeyaiello
Copy link
Contributor

@rjmholt I think we decided to go against most of this given the prototype you coded the other day, yeah?

@ExE-Boss
Copy link

I’m not sure how that would work with Windows though.

Given that if you have a script on Windows that calls pwsh ‑l with the expectation that ‑l stands for ‑LoadProfile, you’ll get unexpected results if you run the script unmodified on Unix (or vice versa), which is why I personally prefer the pwsh‑login script solution.

@fMichaleczek
Copy link

fMichaleczek commented Jun 25, 2019

I’m not sure how that would work with Windows though.

Maybe one day, it will be unix compat. :)
Shell launcher

@joeyaiello
Copy link
Contributor

I’m not sure how that would work with Windows though.

Given that if you have a script on Windows that calls pwsh ‑l with the expectation that ‑l stands for ‑LoadProfile, you’ll get unexpected results if you run the script unmodified on Unix (or vice versa), which is why I personally prefer the pwsh‑login script solution.

Windows doesn't have a concept of a login shell, we only preserve the -l there so you can call it consistently across operating systems. -LoadProfile was only the name because it was a no-op compared to not specifying -l (both of which loaded the profile). I wasn't crazy about the name because it wouldn't make sense on Linux after adding the login shell functionality (and is why I want to change it to -LoginShell).

In any case, pwsh on all platforms loads the PowerShell-specific system and user profile so long as -noprofile isn't specified. And with the the changes, -l -noprofile makes sense because you're making sure to get the system-wide environment (on Linux, /etc/profile, on Windows you get it anyway), but you skip loading of the PowerShell profiles (which means you match behavior on Linux and Windows).

I don't like pwsh-login because it requires users to know when applications plan to implicitly add -l to their invocation of the shell. E.g. if VS Code sticks -l on the end of a default terminal set by the user, that user has to know to actually point at pwsh-login instead of pwsh, and that won't be obvious across the board. I'd rather slip into the existing pattern of -l being a supported by the shell binary that the user already knows to call.

@SteveL-MSFT SteveL-MSFT added this to the 7.0-Consider milestone Jul 1, 2019
@rjmholt
Copy link
Contributor

rjmholt commented Jul 1, 2019

Ok so I've written a proper profiling script here: https://gist.github.com/rjmholt/1ec87842e1ab4655bac34405c7a719e2

Running 10000 iterations (~12 hrs) on an Ubuntu 18.04 VM looks like this:

Screen Shot 2019-06-30 at 10 03 07

It compares:

  • A baseline Hello World C# program (from dotnet new consoleapp)
  • pwsh master branch
  • pwsh my login branch (which has logic to detect a -Login parameter)
  • pwsh -Login from my login branch
  • pwsh-login.sh, a bash script that executes the profile and then execs pwsh from master

Both pwsh branches are compiled with crossgen and the C# program is compiled with Ready2Run enabled.

@rjmholt
Copy link
Contributor

rjmholt commented Jul 4, 2019

So experimenting more, I've found a kink in this proposal, which is that /bin/sh (the POSIX shell) doesn't support login as standard.

On macOS, /bin/sh -l -c 'echo "Hi"' doesn't execute the profile, and nor does executing a file with the same flags passed.

I believe on all the Linux distros we support, /bin/sh does point to something that does load the profile, but on macOS the solution is to run /bin/bash.

@rjmholt
Copy link
Contributor

rjmholt commented Jul 4, 2019

See my PR for this here: PowerShell/PowerShell#10050

@TylerLeonhardt
Copy link
Member

macOS Catalina is now in Public Beta which replaces bash with zsh as the default shell.

Might be worth checking if the bash behavior still works on this new OS

@rjmholt
Copy link
Contributor

rjmholt commented Jul 5, 2019

If /bin/sh points to /bin/zsh, that actually fixes the problem:

echo 'echo "PROFILE LOADED!"' >> ~/.profile
ln -s /bin/zsh ./sh
chmod +x ./sh
./sh -l -c 'echo "Hi"'

Given that /bin/sh is its own binary on macOS, that might not happen. But zsh does have POSIX compatibility mode.

Perhaps the best option for us is to just point to /bin/zsh now?

@rjmholt
Copy link
Contributor

rjmholt commented Jul 5, 2019

There's no indication bash is coming out, but it looks like the most correct option on macOS is /bin/zsh --emulate sh (zsh also examines the first character of its invocation to determine compatibility mode). Some details are here.

@TylerLeonhardt
Copy link
Member

This would mean that we wouldn’t be backcompat though? bash isn’t being removed from macOS (at this time, at least…) so bash might be the right call so long as it still works for this use case.

@SteveL-MSFT
Copy link
Member Author

I don't see any indication that Apple is removing sh or bash (https://support.apple.com/en-us/HT208050) just that zsh will be the new default shell. If zsh is available on all the macOS versions we support, it would be fine deferring to that on macOS.

@rjmholt
Copy link
Contributor

rjmholt commented Jul 6, 2019

I don't see any indication that Apple is removing sh

An important question is whether sh will change on macOS to point to zsh instead of bash --posix. There's a bug in the latter (fixed in bash 4+) where /bin/sh -l -c 'command' doesn't execute the login profile.

I've tested the scenario where sh points to zsh on macOS, and that works with the above invocation as expected.

It's likely bash is slightly faster than zsh, but we probably want to support zsh for security and forward compatibility reasons. As far as I can tell, zsh comes in-box on all macOS versions we support.

UPDATE: The current implementation invokes zsh in sh emulation mode.

@joeyaiello
Copy link
Contributor

Thanks to @SteveL-MSFT for the macOS updates. We'll have to continue revising that behavior to conform to Apple's changes over time.

On the whole, given the low performance impact and having played with builds of this behavior already, @PowerShell/powershell-committee has enough quorum via me, @SteveL-MSFT, @daxian-dbw, and @JamesWTruher to accept this one.

@joeyaiello joeyaiello merged commit afb8338 into PowerShell:master Aug 5, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants