When running commands via pwsh -c '<command>'
, PowerShell will return an exit code of 1
in the event that <command>
returns an exit code greater than 0
. This is particularly problematic for tools like https://github.com/dense-analysis/ale/, which rely on an accurate exit code from the command which they spawn (a linter or fixer in this case).
pwsh -c "bash -c 'exit 2'"; echo $LASTEXITCODE
The exit code of the native application should be returned.
2
PowerShell returns a generic "failure" exit code of 1
.
1
Name Value
---- -----
PSVersion 7.0.0-rc.1
PSEdition Core
GitCommitId 7.0.0-rc.1
OS Darwin 18.7.0 Darwin Kernel Version 18.7.0: Tue Aug 20 16:57:14 PDT 201…
Platform Unix
PSCompatibleVersions {1.0, 2.0, 3.0, 4.0, 5.0, 5.1.10032.0, 6.0.0, 6.1.0, 6.2.0, 7.0.0-rc.1}
PSRemotingProtocolVersion 2.3
SerializationVersion 1.1.0.1
WSManStackVersion 3.0
In case you don't know this workaround, using the -File
parameter will return the actual exit code:
$ cat exit2.sh
#!/bin/sh
exit 2
$ pwsh -nop -noni -f exit2.sh || echo $?
2
Thank you for that; that's definitely a useful workaround, which I'll add to my repertoire. I must say, though, that having to generate and execute a temporary script just to get the expected exit code from the shell is... less than ideal. Honestly, if I tried to put that in a PR for ALE I expect it would be rejected immediately.
One code smell that I see very regularly is the amount of calls to cmd /c
out there in build scripts and "cross-platform" tools which have special cases for running on Windows. When I see an issue like this, however, I'm stuck having to agree that cmd
is actually the better option, which is sad given that it hasn't been touched for what... 20 years now?
It also makes it harder to break out of cases like https://github.com/dense-analysis/ale/blob/5e69aaf4c2b4ffbfd4fbe0af820e23bf559b8e14/autoload/ale.vim#L223 where functionality is based on the OS rather than the shell, which is becoming more important now that PowerShell runs on Linux and macOS (my current OS at work).
GitHub
Check syntax in Vim asynchronously and fix files, with Language Server Protocol (LSP) support - dense-analysis/ale
I agree that the behavior is problematic.
A more direct workaround is to append ; exit $LASTEXITCODE
to the -Command
argument:
pwsh -c "bash -c 'exit 2'; exit `$LASTEXITCODE"; echo $LASTEXITCODE
Note that executing _PowerShell_ scripts (*.ps1
) with -File
behaves differently from POSIX-like shell scripts:
In the _absence_ of an explicit exit
statement, POSIX-like shells report the
_last statement_'s exit code as the script's, whereas *.ps1
scripts _default to 0
_.
*.ps1
script from _inside_ PowerShell behaves differently again: $LASTEXITCODE
after a script invocation reflects whatever _external program_ was last called in the absence of exit <n>
, not implicitly 0
- see #11712 Summarizing the behavior of _PowerShell code_ with the CLI:
-Command
/ -c
behaves _almost_ like a POSIX-like shell in that it automatically uses the _last_ statement's success status, but discards the specific exit code in favor of mapping the abstract Boolean $?
to 0
or 1
(the behavior that prompted creation of this issue).
-File
with a *.ps1
files behaves differently from -Command
/ -c
and POSIX-like shells in that only _explicit_ exit
calls matter, whereas calling *.ps1
files PowerShell-internally behaves differently yet again.
This is expected and changing it would break existing scripts
This should get the expected behavior
powershell
pwsh -c "bash -c 'exit 2'; exit `$LASTEXITCODE"; echo $LASTEXITCODE
This issue has been marked as answered and has not had any activity for 1 day. It has been closed for housekeeping purposes.
@TravisEz13
I find reiterating an already-mentioned _workaround_ for the problematic behavior as the solution and dismissing a request to _fix it_ with a curt "this is expected" and "would break existing scripts" disappointing, and I suspect I'm not the only one.
I invite you to provide a more nuanced response at #13501
Most helpful comment
@TravisEz13
I find reiterating an already-mentioned _workaround_ for the problematic behavior as the solution and dismissing a request to _fix it_ with a curt "this is expected" and "would break existing scripts" disappointing, and I suspect I'm not the only one.
I invite you to provide a more nuanced response at #13501