From 0ea4797813b47350df3563f1b224838ad78190d5 Mon Sep 17 00:00:00 2001 From: Steve Lee Date: Mon, 6 May 2019 14:09:55 -0700 Subject: [PATCH 1/8] draft to enable pwsh to be used as login shell --- .../RFCnnnn-PowerShell-as-Login-Shell.md | 56 +++++++++++++++++++ 1 file changed, 56 insertions(+) create mode 100644 2-Draft-Accepted/RFCnnnn-PowerShell-as-Login-Shell.md diff --git a/2-Draft-Accepted/RFCnnnn-PowerShell-as-Login-Shell.md b/2-Draft-Accepted/RFCnnnn-PowerShell-as-Login-Shell.md new file mode 100644 index 00000000..22b75cf6 --- /dev/null +++ b/2-Draft-Accepted/RFCnnnn-PowerShell-as-Login-Shell.md @@ -0,0 +1,56 @@ +--- +RFC: RFCnnnn +Author: Steve Lee +Status: Draft +SupercededBy: N/A +Version: 1.0 +Area: Console +Comments Due: June 6, 2019 +Plan to implement: Yes +--- + +# Enable PowerShell as Login Shell on POSIX-based systems + +POSIX shells on Unix-based systems use a `-l` switch to start the shell as a login shell. +This means the shell is not being started from an existing configured environment and +needs to execute `/etc/profile` to populate environment variables along with other +environment changes. + +## Motivation + + As a PowerShell user, + I can use PowerShell as my login shell on Unix-based systems, + so that I can use PowerShell everywhere. + +## Specification + +`/etc/profile` is a Bourne shell (sh) script that is executed to configure the +environment and used with login shells. +On Linux systems, this script will typically call out to other scripts (`rc` files) +to perform their own configuration. +On macOS, this script executes `path_helper` which sets up the `$env:PATH` +environment variable and then if the shell is `bash` executes `bashrc`. + +Many existing tools expect `-l` to be accepted by a shell and to act as a login +shell. +Without supporting `/etc/profile`, some environment variables will be missing +in PowerShell rendering it limited as a login or default shell. + +If `-l` (or `-LoadProfile`) is specified, PowerShell will execute `/etc/profile` +using `sh` in a new process and dump out the resulting environment variables. +It will then set those variables in the current PowerShell process. + +On Windows, this switch will only explicitly load the PowerShell profiles. + +Since PowerShell is starting a new process to process `/etc/profile` which itself +may start child processes like `path_helper`, there should not be more than 100ms +impact when `-l` is specified. + +## Alternate Proposals and Considerations + +This RFC is not intended to address the default behavior of PowerShell to load +the PowerShell profile. +`-NoProfile` is still required to have PowerShell not execute PowerShell profiles. + +The implementation is intended to be limited to just environment variables. +`umask` settings, for example, will not be inherited to PowerShell. From 33019ae41d313c7e51aff6c0ca463e2a36a9d737 Mon Sep 17 00:00:00 2001 From: Steve Lee Date: Thu, 23 May 2019 12:47:47 -0700 Subject: [PATCH 2/8] update RFC per feedback --- .../RFCnnnn-PowerShell-as-Login-Shell.md | 57 ++++++++++++------- 1 file changed, 36 insertions(+), 21 deletions(-) diff --git a/2-Draft-Accepted/RFCnnnn-PowerShell-as-Login-Shell.md b/2-Draft-Accepted/RFCnnnn-PowerShell-as-Login-Shell.md index 22b75cf6..6d59714f 100644 --- a/2-Draft-Accepted/RFCnnnn-PowerShell-as-Login-Shell.md +++ b/2-Draft-Accepted/RFCnnnn-PowerShell-as-Login-Shell.md @@ -24,33 +24,48 @@ environment changes. ## Specification -`/etc/profile` is a Bourne shell (sh) script that is executed to configure the -environment and used with login shells. -On Linux systems, this script will typically call out to other scripts (`rc` files) -to perform their own configuration. -On macOS, this script executes `path_helper` which sets up the `$env:PATH` -environment variable and then if the shell is `bash` executes `bashrc`. - Many existing tools expect `-l` to be accepted by a shell and to act as a login shell. -Without supporting `/etc/profile`, some environment variables will be missing -in PowerShell rendering it limited as a login or default shell. -If `-l` (or `-LoadProfile`) is specified, PowerShell will execute `/etc/profile` -using `sh` in a new process and dump out the resulting environment variables. -It will then set those variables in the current PowerShell process. +`-l` (expanded form is `-LoadProfile`) will explicitly have pwsh load the PowerShell +profile. +This is effectively a no-op as if this switch is not specified, pwsh will load +the PowerShell profile and only doesn't load it if `-noprofile` is specified. + +This will allow tools that expect `-l` to be accepted to work. +There is no additional work to process `/etc/profile` when `-l` is used. -On Windows, this switch will only explicitly load the PowerShell profiles. +For cases where you do need `/etc/profile` to be processed, +such as using pwsh as your default shell, +the proposal is to include a Bourne shell script that can be specified as the +shell: -Since PowerShell is starting a new process to process `/etc/profile` which itself -may start child processes like `path_helper`, there should not be more than 100ms -impact when `-l` is specified. +```sh +#!/bin/sh -l +exec /usr/local/bin/pwsh "$@" +``` + +This script will be called `pwsh-login` and should be used whenever you require +a specific login shell. ## Alternate Proposals and Considerations -This RFC is not intended to address the default behavior of PowerShell to load -the PowerShell profile. -`-NoProfile` is still required to have PowerShell not execute PowerShell profiles. +### Process /etc/profile using sh and copy the env vars + +This proposal would be that if `-l` is specified, pwsh would run `/bin/sh -l -c export` +which would create a new shell process that does all the processing needed for +a login shell and export the environment variables that would be exported. +Additional code is needed to take those environment variables and copy them to +the parent pwsh process. + +The downsides to this approach is additional code to maintain, +but more importantly not getting a complete login shell environment as things +like ulimit and umask would not be inherited into pwsh. + +### pwsh to start `/bin/sh -l -c "exec pwsh"` + +This proposal would have pwsh when given the `-l` switch to start Bourne shell +as a login shell and start pwsh within that process. -The implementation is intended to be limited to just environment variables. -`umask` settings, for example, will not be inherited to PowerShell. +This would result in a complete login shell environment, however, would +incur the performance penalty of starting pwsh twice. From 37b444d12b0e4fe92f232f4a9ca39c5cc7ea9db1 Mon Sep 17 00:00:00 2001 From: Steve Lee Date: Thu, 6 Jun 2019 16:17:23 +0200 Subject: [PATCH 3/8] address feedback on different paths to pwsh for different OS --- 2-Draft-Accepted/RFCnnnn-PowerShell-as-Login-Shell.md | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/2-Draft-Accepted/RFCnnnn-PowerShell-as-Login-Shell.md b/2-Draft-Accepted/RFCnnnn-PowerShell-as-Login-Shell.md index 6d59714f..f1ec8589 100644 --- a/2-Draft-Accepted/RFCnnnn-PowerShell-as-Login-Shell.md +++ b/2-Draft-Accepted/RFCnnnn-PowerShell-as-Login-Shell.md @@ -5,7 +5,7 @@ Status: Draft SupercededBy: N/A Version: 1.0 Area: Console -Comments Due: June 6, 2019 +Comments Due: June 13, 2019 Plan to implement: Yes --- @@ -45,6 +45,14 @@ shell: exec /usr/local/bin/pwsh "$@" ``` +>[!NOTE] +> The actual path would depend on the operation system and whether PowerShell +> is a stable or preview release. +> For Linux, the path would be `/usr/bin`. +> For Snap, the path would be `/snap/bin`. +> For macOS, the path would be `/usr/local/bin`. +> Executable would be `pwsh-preview` for preview releases. + This script will be called `pwsh-login` and should be used whenever you require a specific login shell. From 0c9e029dee5826eb2876b099c424f4ca5d56a591 Mon Sep 17 00:00:00 2001 From: Steve Lee Date: Mon, 1 Jul 2019 10:33:59 -0700 Subject: [PATCH 4/8] change proposal to exec to sh -l pwsh --- .../RFCnnnn-PowerShell-as-Login-Shell.md | 55 +++++++++---------- 1 file changed, 27 insertions(+), 28 deletions(-) diff --git a/2-Draft-Accepted/RFCnnnn-PowerShell-as-Login-Shell.md b/2-Draft-Accepted/RFCnnnn-PowerShell-as-Login-Shell.md index f1ec8589..f7feea1a 100644 --- a/2-Draft-Accepted/RFCnnnn-PowerShell-as-Login-Shell.md +++ b/2-Draft-Accepted/RFCnnnn-PowerShell-as-Login-Shell.md @@ -5,8 +5,8 @@ Status: Draft SupercededBy: N/A Version: 1.0 Area: Console -Comments Due: June 13, 2019 -Plan to implement: Yes +Comments Due: July 15, 2019 +Plan to implement: Yes, PS7 --- # Enable PowerShell as Login Shell on POSIX-based systems @@ -27,34 +27,26 @@ environment changes. Many existing tools expect `-l` to be accepted by a shell and to act as a login shell. -`-l` (expanded form is `-LoadProfile`) will explicitly have pwsh load the PowerShell -profile. -This is effectively a no-op as if this switch is not specified, pwsh will load -the PowerShell profile and only doesn't load it if `-noprofile` is specified. +`-l` (expanded form is `-Login`) will: -This will allow tools that expect `-l` to be accepted to work. -There is no additional work to process `/etc/profile` when `-l` is used. - -For cases where you do need `/etc/profile` to be processed, -such as using pwsh as your default shell, -the proposal is to include a Bourne shell script that can be specified as the -shell: - -```sh -#!/bin/sh -l -exec /usr/local/bin/pwsh "$@" -``` +- On Windows, do nothing as the login shell concept doesn't exist. + No error, this param is ignored. +- On Unix based systems, exec `pwsh` using `sh -l` so that the normal login + shell processing occurs and the environment is pre-populated as expected. >[!NOTE] -> The actual path would depend on the operation system and whether PowerShell -> is a stable or preview release. +> The actual path to `sh` would depend on the operating system. > For Linux, the path would be `/usr/bin`. > For Snap, the path would be `/snap/bin`. > For macOS, the path would be `/usr/local/bin`. -> Executable would be `pwsh-preview` for preview releases. -This script will be called `pwsh-login` and should be used whenever you require -a specific login shell. +Since `pwsh` is simply starting an instance of itself, it should work the same +regardless if a stable or preview release. + +Initial performance tests indicate that `pwsh -l` will incur a 6% startup hit. +There is opportunity to bring this down a bit, but the impact seems acceptable +given that the login shell is typically the first shell you create and subsequent +use of `pwsh` would not be a login shell. ## Alternate Proposals and Considerations @@ -70,10 +62,17 @@ The downsides to this approach is additional code to maintain, but more importantly not getting a complete login shell environment as things like ulimit and umask would not be inherited into pwsh. -### pwsh to start `/bin/sh -l -c "exec pwsh"` +### `pwsh-login` script + +This proposal would be to include a Bourne shell script called `pwsh-login` +that would contain: + +```sh +#!/bin/sh -l +exec /usr/local/bin/pwsh "$@" +``` -This proposal would have pwsh when given the `-l` switch to start Bourne shell -as a login shell and start pwsh within that process. +The location of `sh` would depend on the specific operating system. -This would result in a complete login shell environment, however, would -incur the performance penalty of starting pwsh twice. +The perf impact of this compared to starting pwsh as a non-login shell is +approximately 4%. From 0b3b4e228b06f4097fbeee3ad3d68484dcf118e8 Mon Sep 17 00:00:00 2001 From: Steve Lee Date: Thu, 11 Jul 2019 12:09:08 -0700 Subject: [PATCH 5/8] add additional implementation details regaring inspecting argv[0] --- .../RFCnnnn-PowerShell-as-Login-Shell.md | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/2-Draft-Accepted/RFCnnnn-PowerShell-as-Login-Shell.md b/2-Draft-Accepted/RFCnnnn-PowerShell-as-Login-Shell.md index f7feea1a..10ad520a 100644 --- a/2-Draft-Accepted/RFCnnnn-PowerShell-as-Login-Shell.md +++ b/2-Draft-Accepted/RFCnnnn-PowerShell-as-Login-Shell.md @@ -44,9 +44,20 @@ Since `pwsh` is simply starting an instance of itself, it should work the same regardless if a stable or preview release. Initial performance tests indicate that `pwsh -l` will incur a 6% startup hit. -There is opportunity to bring this down a bit, but the impact seems acceptable -given that the login shell is typically the first shell you create and subsequent -use of `pwsh` would not be a login shell. +Compared to a pure Bourne shell script which has a 4% startup hit. +Most of that is simply processing the Bourne shell scripts to setup the environment. +As such, there is a relative 2% additional perf hit with this proposal. + +The impact seems acceptable given that the login shell is typically the first +shell you create and subsequent use of `pwsh` would not be a login shell. + +In addition, `pwsh` will need to be updated to detect if it was started with +a hyphen (for example, `-pwsh`) as that is another way that Unix based operating +systems start the default login shell and doesn't necessarily use `-l`. + +On Linux, this will be implemented by inspecting `/proc` on the filesystem. +On macOS, this will be implemented by calling `sysctl()` getting the process +information for the current process and inspecting `argv[0]`. ## Alternate Proposals and Considerations From 60a10bcf421064632797e222d173be3a40902fe8 Mon Sep 17 00:00:00 2001 From: Steve Lee Date: Mon, 5 Aug 2019 10:54:28 -0700 Subject: [PATCH 6/8] add mention of potential future work to support other default shells for processing profile --- 2-Draft-Accepted/RFCnnnn-PowerShell-as-Login-Shell.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/2-Draft-Accepted/RFCnnnn-PowerShell-as-Login-Shell.md b/2-Draft-Accepted/RFCnnnn-PowerShell-as-Login-Shell.md index 10ad520a..60c25bc3 100644 --- a/2-Draft-Accepted/RFCnnnn-PowerShell-as-Login-Shell.md +++ b/2-Draft-Accepted/RFCnnnn-PowerShell-as-Login-Shell.md @@ -87,3 +87,9 @@ The location of `sh` would depend on the specific operating system. The perf impact of this compared to starting pwsh as a non-login shell is approximately 4%. + +### Supporting different default login shells + +In the future, if relying on `sh` (and thus `/etc/profile`) is not sufficient, +we can allow an optional argument to `-login` to indicate the shell to use +to process the script that creates the environment. From dc0f8a6d8bb0827fd08dd014f2e08ab7c90b8558 Mon Sep 17 00:00:00 2001 From: Steve Lee Date: Mon, 5 Aug 2019 11:41:19 -0700 Subject: [PATCH 7/8] clarify `zsh` relationship --- 2-Draft-Accepted/RFCnnnn-PowerShell-as-Login-Shell.md | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/2-Draft-Accepted/RFCnnnn-PowerShell-as-Login-Shell.md b/2-Draft-Accepted/RFCnnnn-PowerShell-as-Login-Shell.md index 60c25bc3..dd429985 100644 --- a/2-Draft-Accepted/RFCnnnn-PowerShell-as-Login-Shell.md +++ b/2-Draft-Accepted/RFCnnnn-PowerShell-as-Login-Shell.md @@ -38,7 +38,9 @@ shell. > The actual path to `sh` would depend on the operating system. > For Linux, the path would be `/usr/bin`. > For Snap, the path would be `/snap/bin`. -> For macOS, the path would be `/usr/local/bin`. +> For macOS, there is an issue with `sh` not loading the login profile with +> our usage, so `pwsh` will use `zsh` with `sh` emulation mode to enable +> proper initialization of the environment. Since `pwsh` is simply starting an instance of itself, it should work the same regardless if a stable or preview release. @@ -93,3 +95,9 @@ approximately 4%. In the future, if relying on `sh` (and thus `/etc/profile`) is not sufficient, we can allow an optional argument to `-login` to indicate the shell to use to process the script that creates the environment. + +### macOS moving to Zsh by default + +Expectation is that macOS intends to switch to `zsh` as the default shell so +it may make sense to revisit this in the future to default to using `zsh` so +that `zprofile` gets processed. From e007e084f0c00a346853fa3fe7f5614ed3b0967e Mon Sep 17 00:00:00 2001 From: Joey Aiello Date: Mon, 5 Aug 2019 11:46:51 -0700 Subject: [PATCH 8/8] Update and rename RFCnnnn-PowerShell-as-Login-Shell.md to RFC0040-PowerShell-as-Login-Shell.md --- ...as-Login-Shell.md => RFC0040-PowerShell-as-Login-Shell.md} | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) rename 2-Draft-Accepted/{RFCnnnn-PowerShell-as-Login-Shell.md => RFC0040-PowerShell-as-Login-Shell.md} (99%) diff --git a/2-Draft-Accepted/RFCnnnn-PowerShell-as-Login-Shell.md b/2-Draft-Accepted/RFC0040-PowerShell-as-Login-Shell.md similarity index 99% rename from 2-Draft-Accepted/RFCnnnn-PowerShell-as-Login-Shell.md rename to 2-Draft-Accepted/RFC0040-PowerShell-as-Login-Shell.md index dd429985..fae80ed3 100644 --- a/2-Draft-Accepted/RFCnnnn-PowerShell-as-Login-Shell.md +++ b/2-Draft-Accepted/RFC0040-PowerShell-as-Login-Shell.md @@ -1,7 +1,7 @@ --- -RFC: RFCnnnn +RFC: RFC0040 Author: Steve Lee -Status: Draft +Status: Draft-Accepted SupercededBy: N/A Version: 1.0 Area: Console