8000 #!/usr/local/bin/powershell bang should not load profile · Issue #992 · PowerShell/PowerShell · GitHub
[go: up one dir, main page]

Skip to content

#!/usr/local/bin/powershell bang should not load profile #992

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
vors opened this issue May 18, 2016 · 40 comments
Closed

#!/usr/local/bin/powershell bang should not load profile #992

vors opened this issue May 18, 2016 · 40 comments
Labels
Committee-Reviewed PS-Committee has reviewed this and made a decision Issue-Enhancement the issue is more of a feature request than a bug OS-Linux Resolution-No Activity Issue has had no activity for 6 months or more Usability (LEGACY) Helps filter issues that might be higher priority because they directly affect usability WG-Engine core PowerShell engine, interpreter, and runtime

Comments

@vors
Copy link
Collaborator
vors commented May 18, 2016

Steps to reproduce

Put in your PS profile

Write-Host 'PROFILE'

Create a script ./foo.ps1 and chmod +x on it

#!/usr/local/bin/powershell
Write-Host 'foo'

From bash call ./foo.ps1

Expected behavior

Should not load profile

ash-3.2$ ./foo.ps1
foo

Reason: that's how bash handles it

Actual behavior

Load profile

ash-3.2$ ./foo.ps1
PROFILE
foo

Environment data

v0.4.0

@vors vors added the Usability (LEGACY) Helps filter issues that might be higher priority because they directly affect usability label May 18, 2016
@andyleejordan
Copy link
Member

Ha! I don't see anyway this is going to work without a shim that executes with -noprofile.

@vors
Copy link
Collaborator Author
vors commented May 19, 2016

We just need to figure out who called us, you know.

Also, if you run the same way

#!powershell

Write-Host 'foo'
bash-3.2$ /Users/vors/dev/foo.ps1
Failed to load , error: dlopen(, 1): no suitable image found.  Did find:
    /usr/local/lib/: not a file
    /usr/lib/: not a file

@andyleejordan
Copy link
Member

I don't see how we would reliably determine who called us, and how to interpret it (I as a user might call PowerShell via env, and wouldn't want its behavior to change because it detected that env launched it instead of Bash, that's just a bad idea).

I think really we just want to run with -noprofile whenever an in-place script is run (and -noexit was not used). Said another way, a profile should only be loaded when PowerShell is launched into an interactive shell.

This would be much better behavior (but we'd need a way to specify -profile to reverse it).

@vors
Copy link
Collaborator Author
vors commented May 19, 2016

@lzybkr can you comment on the profile/noprofile, please ?

Should this work at all #!powershell ?

@andyleejordan andyleejordan added this to the Future milestone Jun 8, 2016
@vors vors modified the milestones: Aug17, Future Jun 8, 2016
@lzybkr
Copy link
Contributor
lzybkr commented Jul 21, 2016

I just noticed this in my .bashrc:

# If not running interactively, don't do anything
case $- in
    *i*) ;;
      *) return;;
esac

So I would say we should run the profile with #!powershell, but we should also find a clean way of detecting the process is interactive, e.g. if ($host.IsInteractive)

@vors
Copy link
Collaborator Author
vors commented Jul 21, 2016

👍
I was asking for $host.IsInteractive for ages.

@vors vors modified the milestones: 6.0.0-alpha.9, Aug17, Future Jul 21, 2016
@vors vors removed their assignment Jul 30, 2016
@joeyaiello joeyaiello added Issue-Enhancement the issue is more of a feature request than a bug OS-Linux WG-Engine core PowerShell engine, interpreter, and runtime labels Sep 2, 2016
@SteveL-MSFT SteveL-MSFT modified the milestones: post-6.0.0, 6.1.0 Mar 4, 2017
@iSazonov
Copy link
Collaborator
iSazonov commented Oct 7, 2017

Since #3558 merged it seems we can get a fix for this.
/cc @SteveL-MSFT @mklement0

@mklement0
Copy link
Contributor
mklement0 commented Oct 7, 2017

Note: In this discussion, we're equating PowerShell profiles with one type of initialization file in POSIX-like shells, the "individual per-interactive-shell startup file", as Bash calls it, stored in ~/.*rc files; e.g., ~/.bashrc for Bash. In POSIX-like shells, profiles are distinct initialization files (which, unlike the ~/.*rc files, exist both on a system and at a user level) only sourced by login shells, irrespective of interactivity; A POSIX-like shell is a login shell only if the -l option is explicitly passed or invocation happens via the login utility - PowerShell has no equivalent to that, but in contrast with POSIX-like ~/.*rc files, PowerShell's profiles exist both at the current-user and all-users (and host) levels.

  • Shebang lines (#!...) on Unix platforms only every work with absolute paths.

  • Only 2 tokens are portably supported (#!/path/to/foo bar; macOS supports more, but Linux doesn't).

  • Given that the powershell binary (a symlink to it) is installed in different locations across supported Unix platforms (/usr/bin on Linux vs. /usr/local/bin on macOS), the only way to portably target PowerShell is to invoke it via env, relying on env's ability to locate it via the $PATH, i.e.: #!/usr/bin/env powershell

    • This means that if you want your script to remain portable, passing any parameters to powershell itself as part of the shebang line is NOT an option, given that #!/usr/bin/env powershell already uses up the 2 tokens that are portably supported.

  • POSIX-like shells (bash, ksh, zsh) do NOT load their initialization files (~/.*rc) if they themselves determine that they're being invoked non-interactively, such as via a shebang line.

    • Providing something like $host.IsInteractive would be helpful in general, but should not come into play here; in fact, initialization files doing their own interactivity detection causes nothing but trouble, because it gets in the way of non-interactive scripts purposely re-sourcing initialization files after their modification.
  • Thus, if PowerShell wants to fit into the Unix world specifically and more generally wants to provide a predictable scripting environment it mustn't load profiles by default when executing scripts; unfortunately, that is a breaking change; see Align PowerShell's CLI / startup behavior with POSIX-like shells such as Bash - command-line arguments #3743

@mklement0
Copy link
Contributor
mklement0 commented Oct 8, 2017

Here's how Bash determines if an instance is non-interactive - such as when invoked via a shebang line (as stated, non-interactive instances by default do not load any initialization files):

  An interactive shell is one started without non-option arguments 
  [read: a script filename operand optionally followed by its arguments] and
  without the -c option whose standard input and error are both connected
  to terminals (as determined by isatty(3)), or one started with  the  -i
  option.	 PS1 is set and $- includes i if bash is interactive, allowing
  a shell script or a startup file to test this state.

Note that the use of shebang line #!/bin/bash in, for example, script /tmp/foo results in invocation
/bin/bash /tmp/foo.

@iSazonov
Copy link
Collaborator
iSazonov commented Oct 8, 2017

Interesting, if we install PowerShell in different locations across supported Unix platforms why not create a link to current version in /bin? Have we bash on all platforms there?
Sometimes loading a profile in non-interactive mode can be useful, ex. loading a compatibility module. So automatic detection of non-interactive mode is not best way for PowerShell. Since we discuss using a short name (posh) we can resolve the problem with shebang by adding new wrappers:

  • #!/usr/bin/env posh-no-user-profile
  • #!/usr/bin/env posh-no-all-profile
  • #!/usr/bin/env posh-no-profiles

@mklement0
Copy link
Contributor
mklement0 commented Oct 8, 2017

why not create a link to current version in /bin

At least Linux platforms conform to the FHS (Filesystem Hierarchy Standard), according to which placing a symlink to the PowerShell binary in /bin would be inappropriate; similarly, it would be unexpected on macOS.

Do we have bash on all platforms there?

Probably yes, but how does that come into play here?

Sometimes loading a profile in non-interactive mode can be useful

You can always do that from within a script, if needed; e.g., . $PROFILE.

we can resolve the problem with shebang by adding new wrappers:

That seems like an obscure and cumbersome workaround.

@iSazonov
Copy link
Collaborator
iSazonov commented Oct 9, 2017

That seems like an obscure and cumbersome workaround

If we want to be bash-behaivor-compatible we should use bash startup code and embed it in PowerShell startup code. But it doesn't seem compatible with PowerShell behavior. Dead lock :-). I think we're doomed to be rude and break a wall somewhere. Until we have the right solution, I prefer to have a wrapper. When it becomes stable, we could gradually embed it in the main code.

@iSazonov
Copy link
Collaborator

@mklement0 3720 was closed and they don't track closed issues - so you should open new issue for GetFinalPathNameByHandle.

As for the solution I hope we'll able test this on next week after moving to .Net Core 2.1.

@mklement0
Copy link
Contributor

@iSazonov: Good idea - please see https://github.com/dotnet/core-setup/issues/4080

@lzybkr
Copy link
Contributor
lzybkr commented Apr 26, 2018

I'm really not a fan of using a different binary - I think far too many people will use pwsh because of familiarity and that will be fine on their machine and maybe in production, but will fail on some random dev box.

@iSazonov
Copy link
Collaborator
iSazonov commented May 9, 2018

We can look at it from the other side based on #3743 and introduce one exe as POSIX-like (or even POSIX-compliant) and second one with traditional behavior.
For example powershell.exe - traditional behavior, pwsh.exe - POSIX-like.

@rkeithhill
Copy link
Collaborator
rkeithhill commented Jun 5, 2018

It would really be nice to have something for 6.1 that works on Windows as well. I've been trying to use git pre-commit hooks on my Windows dev box to ensure I have the right email configured. This works but it slows down all my commits because it processes my profile scripts when it does not need to:

#!/usr/bin/env pwsh

# Verify user's Git config has appropriate email address
if ($env:GIT_AUTHOR_EMAIL -notmatch '@(non\.)?acme\.com$') {
    Write-Warning "Your Git email address '$env:GIT_AUTHOR_EMAIL' is not configured correctly."
    Write-Warning "It should end with '@acme.com' or '@non.acme.com'."
    Write-Warning "Use the command: 'git config --global user.email <name@acme.com>' to set it correctly."
    exit 1
}

exit 0

The only work around I've found is to put the PS script in a separate pre-commit.ps1 file and modify pre-commit to:

#!/bin/sh
pwsh.exe -NoProfile -File .git/hooks/pre-commit.ps1

But I'd rather there be just a single file. At this point, I'd be satisfied if I could do this:

#!/usr/bin/env pwsh-np
...

@mklement0
Copy link
Contributor

@rkeithhill:

It's obviously just a stopgap, but you can roll your own pwsh-np by creating a script by that name with the content below and by placing it in a folder in your PATH (works on both Windows and Unix-like platforms, but on the latter you must also mark the script as executable (chmod a+x pwsh-np)):

#!/bin/sh

pwsh -noprofile "$@"

Your hooks should then be able to use the shebang you mentioned (#!/usr/bin/env pwsh-np).

@nippyin
Copy link
nippyin commented May 20, 2019

Able to Run .ps1 script on zsh manually, however if call same ps1 from ansible playbook gets error that Connect-AzAccount is not recognized. #!/usr/bin/env pwsh is what i use in .ps1
Please help me to setup my environment variable.

@iSazonov
Copy link
Collaborator

@nippyin Please open new issue with step-by-step repo.

@rashil2000
Copy link
rashil2000 commented Sep 4, 2021

I just noticed this in my .bashrc:

# If not running interactively, don't do anything
case $- in
    *i*) ;;
      *) return;;
esac

So I would say we should run the profile with #!powershell, but we should also find a clean way of detecting the process is interactive, e.g. if ($host.IsInteractive)

Is $Host.IsInteractive planned? FWIW, [Environment]::UserInteractive always seems to return True, even in pwsh -c <command>.

I just realized that setting PowerShell as default shell on Linux (using chsh) is a very bad idea. All my programs display a lag of 3-4 seconds when starting up. Many applications use "$SHELL" -c <command> to run external commands, and in each of them PowerShell seems to load the profile, causing the delay (since $SHELL is now /usr/bin/pwsh). This is particularly noticeable in Neovim and Fzf, as examples.

Presence of $Host.IsInteractive would really help in aborting the sourcing of profile, as in the case of bash.

Copy link
Contributor

This issue has not had any activity in 6 months, if this is a bug please try to reproduce on the latest version of PowerShell and reopen a new issue and reference this issue if this is still a blocker for you.

1 similar comment
Copy link
Contributor

This issue has not had any activity in 6 months, if this is a bug please try to reproduce on the latest version of PowerShell and reopen a new issue and reference this issue if this is still a blocker for you.

@microsoft-github-policy-service microsoft-github-policy-service bot added Resolution-No Activity Issue has had no activity for 6 months or more labels Nov 16, 2023
Copy link
Contributor

This issue has not had any activity in 6 months, if this is a bug please try to reproduce on the latest version of PowerShell and reopen a new issue and reference this issue if this is still a blocker for you.

Copy link
Contributor

This issue has been marked as "No Activity" as there has been no activity for 6 months. It has been closed for housekeeping purposes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Committee-Reviewed PS-Committee has reviewed this and made a decision Issue-Enhancement the issue is more of a feature request than a bug OS-Linux Resolution-No Activity Issue has had no activity for 6 months or more Usability (LEGACY) Helps filter issues that might be higher priority because they directly affect usability WG-Engine core PowerShell engine, interpreter, and runtime
Projects
None yet
Development

No branches or pull requests

0