Repository navigation
Description
Related: #3743
On macOS, unlike on Linux, all (user-)default shell instances are started as login shells.
There are two mechanisms for invoking a shell as a login shell: (a) setting its argv[0] to contain - as the 1st character (that's what Terminal.app does) or (b) passing the -l (or --login) option to the shell executable.
If you make pwsh your default shell on macOS, certain applications may invoke pwsh with -l, which currently breaks the invocation.
Specifically, Visual Studio Code does that, so on a macOS system that uses /usr/bin/pwsh as the default shell, the integrated terminal fails to load (unless you happen to have the PowerShell extension installed and happen to open a *.ps1 file).
It would be sufficient for pwsh to accept -l / --login and otherwise simply ignore it, as the behavioral implications of this option in the context of bash don't apply to PowerShell.
Steps to reproduce
pwsh -l
pwsh --loginTo see the problem in action with Visual Studio Code:
- Add
/usr/local/bin/pwshto/etc/shells - Make PowerShell your default shell with
chsh -s /usr/local/bin/pwsh - Open a new terminal and close existing Visual Studio Code windows.
- Use
code <file>to open a file for editing, where<file>must not be a PowerShell file. - Try to access the integrated terminal, which crashes due to invoking
pwshwith-l.
Expected behavior
An interactive PowerShell session should start, as if the option hadn't been specified.
Actual behavior
Invalid argument '-l', did you mean:
...
The argument '--login' is not recognized as the name of a script file. Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
...
Environment data
PowerShell Core v6.1.0-rc.1 on macOS 10.13.6
PowerShell Core v6.1.0-rc.1 on Ubuntu 16.04.4 LTS
PowerShell Core v6.1.0-rc.1 on Microsoft Windows 10 Pro (64-bit; Version 1803, OS Build: 17134.165)
Windows PowerShell v5.1.17134.165 on Microsoft Windows 10 Pro (64-bit; Version 1803, OS Build: 17134.165)
Activity
[-]The pwsh CLI should support the -l option for macOS compatibility, e.g. in VSCode[/-][+]The pwsh CLI should support the -l / --login option for macOS compatibility, e.g. in VSCode[/+]iSazonov commentedon Sep 5, 2018
If we add the
-lwhether users expect that we fully support PowerShell Core as login shell?mklement0 commentedon Sep 5, 2018
We would have to document that it is an effective no-op.
De facto using
pwshas the default shell already works fine on macOS, after applying the workaround described in #6027 (comment)Eventually we'll need a documentation topic that describes all limitations with respect to using
pwshas the default shell on Unix-like platforms, currently summarized here: #975 (comment)iSazonov commentedon Sep 5, 2018
Michael Klement (@mklement0) Could you please clarify about
Is it
pwsh -?Can this resolve the Issue too?
mklement0 commentedon Sep 5, 2018
No, it is not an argument that reflects
-, it is the name of the executable, reflected inargv[0]in C terms and in$0in POSIX-like shell terms, which the caller sets to an arbitrary value - see below for details.Given that we're currently not modifying the behavior based on whether we're invoked as a logon shell or not, it's not even necessary to detect
--prefixed invocations; of course we will have to, if we ever decide to change that (though it's not exactly clear what honoring login-shell status means, given that PowerShell cannot interpret/etc/profiledirectly).Not necessarily, because other tools - such as VSCode and at least hypothetically other terminal applications - may still use the
-loption rather than the--prefix technique.That's why I think we should fix it in PowerShell rather than asking VSCode to modify its default-shell invocation.
The
--prefix conventionBy convention, shells should consider themselves login shells if the 1st character of
$0(argv[0]) is-(as an alternative to being passed the-l/--loginoption as an argument).The caller can "fake" the name/path of the executable it invokes as reported in
$0, so even though it ispwshthat is invoked,$0contains-pwshwhen invoked from Terminal.app (and also from popular third-party alternative iTerm.app) while configured as the default shell.On Unix-like platforms, for instance, you can use Bash's
execbuiltin with the-aoption to set$0, and theloption automatically prepends-to it.The tricky part is to get PowerShell to obtain this value, because
[Environment]::GetCommandLineArgs()doesn't reflect it (it just contains the DLL path, e.g.,/usr/local/microsoft/powershell/6-preview/pwsh.dll).The only way I personally know of to get this information from inside PowerShell (I haven't looked hard) would be to call the
psutility as follows, but that is obviously an undesirable cost to incur on startup:iSazonov commentedon Sep 5, 2018
Seems we have already discussed that we could use different file names to address such scenarios (login shell, hide console windows, graphical shell and etc.). For the Issue we could create
pwshlorpwsh_loginrunner.mklement0 commentedon Sep 5, 2018
That would add unnecessary complexity:
It requires creating, maintaining, shipping, documenting a new executable, even though its sole purpose would be to ignore the
-l/--loginoptions.User will need to know and remember that they must specify that a different executable when changing their default shell to PowerShell with
chsh -s, which is far from obvious (adding the right executable to/etc/shellsas a prerequisite should be done by the installer, which may already be happening).iSazonov commentedon Sep 5, 2018
With -l option we only fix VS Code issue not Terminal.app
I found the PowerShell Committee approvement #992 (comment)
mklement0 commentedon Sep 5, 2018
There is nothing to fix for Terminal.app or any other tools that use the
--prefix convention, because PowerShell doesn't and need not care about whatargv[0]truly contains - it simply has no impact.The approval you link to is in a way the opposite of what we're discussing here: a dedicated
pwsh-npwould suppress loading of profiles, whereas option-lin POSIX-like shells explicitly loads profiles (even in non-interactive shells) - and we definitely want to load$PROFILEif-lis passed.iSazonov commentedon Sep 6, 2018
My idea was that we should use one approach if we want to follow the "standard"/bash/posix behavior.
These settings are not for end users. Users should continue to use pwsh. System settings is for the installer or for the distributive creator - in this case, the end user does not need to know that another file is being launched.
mklement0 commentedon Sep 6, 2018
That would be nice, but it's already not true for
pwsh-np: As a script author, you must know to use it as the executable in the shebang line in order to get predictable behavior that doesn't load$PROFILE.Unfortunately, backward-compatibility concerns leave us no choice there, so a separate executable is required.
Similarly, as stated, the end user would need to know that it's not
pwsh, butpwshl(or whatever it would be) that must be passed tochsh -sin order to make PowerShell the default shell.Fortunately, in this case we do have the option to support that with the existing executable, by implementing
-l/--loginas no-op switches.iSazonov commentedon Sep 7, 2018
Modern devices is locked - owners haven't root permissions. Corporate users too. Special devices (net devices, storage systems and so in) is locked too. Only a manufacturer configure the device. Or there is a config tools. Or installer. If user has a root permission one is high quality professional user. On windows systems we traditionally have GUI that helps eliminate errors in the configuration. In PowerShell we can add cmdlets to configure shells, schedule tasks and so on in right way.
Posix discribes Bash behaviors. If somebody want to implement something Posix-compatible one have to implement or port new-Bash. For any other shell like PowerShell we are forced to seek a compromise and implement only what is possible.
If the team published PowerShell specifications under Posix, we would be so Posix-compatible :-)
I think real way is to develop and publish RFC to standardize PowerShell shell behavior. Then any manufacturer of distributions and systems can embed PowerShell in a standard and compatible manner. It may even be quite different than Posix/Bash.
It should also be noted that in the 6.x version we must comply with backward compatibility, but we can do some useful workarounds (like you suggest). But this should be done so that in next 7.x version we could make more significant changes.
mklement0 commentedon Sep 7, 2018
Ilya (@iSazonov):
Honestly, I have no idea what your first paragraph is talking about and how it relates to this discussion.
As for the second paragraph:
As an aside: No, POSIX comprises a specification for a shell, whose executable is
/bin/sh. Bash is a POSIX-like shell, but even when you run it in POSIX compatibility mode it isn't fully POSIX-compliant.And implementing
-l/--loginas quiet no-op options is exactly such a compromise.No one is looking for 100% POSIX compatibility, which fundamentally cannot be achieved by PowerShell.
What matters is that in practice you can use it as your default shell on all of the supported platforms, and the proposed change is a step in that direction.
If someone wants to take on the work of formalizing the extent to which PowerShell is POSIX-compatible, that's great, but doing so is not a prerequisite for the change proposed here.
iSazonov commentedon Sep 7, 2018
Michael Klement (@mklement0) Thanks for great discussion!
Yes, adding '-l' we resolve the Issue with VS Code.
My main fear was and is that with getting '-l' users will expect that we implementfully fully functional login shell. So first of all we need to create RFC and describe all shell modes. This will allow Community to use PowerShell in the standard way.
It is a question for PowerShell Committee.
SteveL-MSFT commentedon Sep 19, 2018
@PowerShell/powershell-committee would accept adding
-lthat output a warning message akin to: "The -l switch was used to indicate starting a login shell, however, PowerShell Core 6 does not currently support this meaning that certain environment variables will not be available or complete.". This would allow tools that expect-lto be there to work and pwsh to startup and allows us to support the complete work of a login shell in the future.mklement0 commentedon May 9, 2019
Resolved in #9528, which adds a
-l/-LoadProfileswitch that is a no-op for now.See also: the RFC to make
-lfunctional: https://github.com/PowerShell/PowerShell-RFC/pull/171/files