Working with PowerShell Core on Linux

Here are some useful notes I have been updating whenever I have some new findings.

Installation

First thing first, here is the official documentation on installing pwsh or pwsh-preview on Linux OS.

A known issue

This is a known issue that pwsh will hang after executing any external command if $TERM is screen, i.e. you are running pwsh inside a screen. However, according to the GitHub comment, it seems screen is to blame.

Though this does not limit its usage with other system utilities, I’d like to know if readers like you have some handy solution… Comment below!

Prolog

To start writing a PowerShell script, you may start with the following

Note here we use pwsh as the shell name. It does not match the preview version of PowerShell ( pwsh-preview).

Exit code (from callees)

To retrieve the last exit code of an external executable, use $LastExitCode. This almost has the same meaning as $? in bash.

$? in PowerShell is a boolean value indicating whether the last command (Cmdlet or external executable) is successful or not.

Exit upon any error

Just like MS-DOS batch or Windows CMD batch script, PowerShell does not exit by default upon receiving non-terminating error records from the cmdlets or scriptlets. By error records I mean the records written with Write-Error cmdlet. This is what will happen if you try to cd into a non-existent folder, or to delete a file that you don’t have access to. Script will stop executing regardless when it receives Exception raised with throw expression.

Setting $ErrorActionPreference to "Stop" can stop the execution on the first error record.

Still, this does not affect failed external executables. So you might need an utility function to achieve this

Signals

Just like sh or bash, pwsh can work with other system utilities, such as systemd.service unit and cron. Like other .NET Core console applications, pwsh interprets SIGINT as Ctrl+C. If you want to capture such signal, you may consider using the approach mentioned in this SO post.

Another way to handle Ctrl+C in a more easier fashion, is to simply put your cleanup code inside finally part of a tryfinally block. However, note that this block will be called no matter if your are exiting the tryfinally block normally, with exception raised, or received Ctrl+C.

There is currently no built-in cmdlet for sending signals to other applications in PowerShell, so you may well use /usr/bin/env -sto achieve this. Note that kill is already an alias in PowerShell to Stop-Process. You need to use the full path to bypass the alias.

Suppress outputs

May commands and function calls in PowerShell have output. You might be caught in surprise sometimes because certain cmdlets or functions do have return value (i.e. output), such as New-Item:

If you forgot to collect the return value into a variable, or to discard them, it may be printed out, or worse, when you are writing a function, it will become one of the function’s return value. For example

What result do you expect from console? 6?

No. It’s 9. You can try it yourself, guess why, and propose a fix.

To Suppress the output of a cmdlet or an external command, you may use one the following snippets

Is Out-Null really that slow?

According to this SO post, you might want to think twice before using Out-Null because it has some overhead. However, the overhead seems relatively small on my PC. I used the following test script on 3 different environments

The result is as follows.

PowerShell 5.1 on Windows pwsh-preview 7.0-pre2 on Windows pwsh 6.2.2 on Ubuntu
00:00:17.8234508
00:00:00.3715146
00:00:00.6938085
00:00:00.7237914
00:00:00.6631330
00:00:00.3518360
00:00:00.5495256
00:00:00.5452132
00:00:02.6287777
00:00:01.9599901
00:00:02.5183607
00:00:02.5390679

It can be observed that on PowerShell, Out-Null is 48x slower than > $null, but on PowerShell Core, the gap is only 2x. It’s less performant, but not that slow.

And I love how it looks when using Out-Null. (Shhhhh)

[Keep updating!]

 

Leave a Reply

Your email address will not be published. Required fields are marked *

*

This site uses Akismet to reduce spam. Learn how your comment data is processed.