Installing PowerShell on a RaspberryPi

When I discovered (admittedly a few months ago) that not only has Microsoft released PowerShell Core as an Open Source project on GitHub but that it had been ported to the Raspberry Pi I couldn’t resist.

Besides an object-oriented shell running on a Raspberry Pi just has to be cool…

(No – I’ve not been converted to the ‘dark side’ and PowerShell isn’t going to become my primary shell anytime soon, but it is interesting and very, very different from other UNIX shells).

To begin to install PowerShell Core on a Raspberry Pi 2 or 3 you need to be logged in as root.

sudo -i
Password: 

Or

su
Password: 

The first thing to do is ensure that your system it up to date.


apt-get update
Hit:1 http://mirrordirector.raspbian.org/raspbian stretch InRelease
Hit:2 http://archive.raspberrypi.org/debian stretch InRelease
Reading package lists... Done
apt-get upgrade
Reading package lists... Done
Building dependency tree       
Reading state information... Done
Calculating upgrade... Done
0 upgraded, 0 newly installed, 0 to remove and 0 not upgraded.
#

Before you can run PowerShell you need to install all the packages that it depends on.

Note – If you are using one of the Raspberry Pi Foundation’s Raspbian images then some of these may already be installed.


apt-get install ca-certificates icu-devtools libunwind8 libcurl3 tzdata
Reading package lists... Done
Building dependency tree       
Reading state information... Done
The following additional packages will be installed:
  libgmp10 libgnutls30 libhogweed4 libicu57 libidn2-0 libldap-2.4-2
  libldap-common libnettle6 libnghttp2-14 libp11-kit0 libpsl5
  librtmp1 libsasl2-2 libsasl2-modules-db libssh2-1 libtasn1-6 libunistring0
  openssl
Suggested packages:
  gnutls-bin
Recommended packages:
  publicsuffix libsasl2-modules
The following NEW packages will be installed:
  ca-certificates icu-devtools libcurl3 libgmp10 libgnutls30 libhogweed4
  libicu57 libidn2-0 libldap-2.4-2 libldap-common libnettle6 libnghttp2-14
  libp11-kit0 libpsl5 librtmp1 libsasl2-2 libsasl2-modules-db libssh2-1
  libtasn1-6 libunistring0 libunwind8 openssl
0 upgraded, 22 newly installed, 0 to remove and 2 not upgraded.
Need to get 11.3 MB of archives.
After this operation, 39.1 MB of additional disk space will be used.
Do you want to continue? [Y/n] 
  :
  :
  :
Processing triggers for ca-certificates (20161130+nmu1+deb9u1) ...
Updating certificates in /etc/ssl/certs...
0 added, 0 removed; done.
Running hooks in /etc/ca-certificates/update.d...
done.
localepurge: Disk space freed in /usr/share/locale: 424 KiB
localepurge: Disk space freed in /usr/share/man: 0 KiB
 
Total disk space freed by localepurge: 424 KiB

If you are using a minimal Raspbian installation you may also need to install  wget  to download PowerShell from GitHub (this step won’t be necessary if you are using one of the Foundations Raspbian images).

#
apt-get install wget
Reading package lists... Done
Building dependency tree       
Reading state information... Done
The following NEW packages will be installed:
  wget
0 upgraded, 1 newly installed, 0 to remove and 2 not upgraded.
Need to get 768 kB of archives.
After this operation, 2,734 kB of additional disk space will be used.
  :
  :
  :
Setting up wget (1.18-5+deb9u2) ...
localepurge: Disk space freed in /usr/share/locale: 1872 KiB
localepurge: Disk space freed in /usr/share/man: 0 KiB
 
Total disk space freed by localepurge: 1872 KiB

The most up to date release of PowerShell can be found on here on GitHub. At the time this page was written the latest stable release was 6.0.4 so that is what I’ve used.

Note – The Raspberry Pi uses the 32-bit arm version, not the 64-bit version.

#
wget https://github.com/PowerShell/PowerShell/releases/download/v6.0.4/powershell-6.0.4-linux-arm32.tar.gz
Resolving github.com (github.com)... 192.30.253.113, 192.30.253.112
Connecting to github.com (github.com)|192.30.253.113|:443... connected.
WARNING: The certificate of github.com is not trusted.
WARNING: The certificate of github.com hasn't got a known issuer.
HTTP request sent, awaiting response... 302 Found
  :
  :
  :
HTTP request sent, awaiting response... 200 OK
Length: 26030533 (25M) [application/octet-stream]
Saving to: powershell-6.0.4-linux-arm32.tar.gz. 
powershell-6.0.4-linux-arm32.tar 100%[==========================================================>]  24.82M  3.94MB/s    in 6.9s    
 
2018-09-07 00:09:59 (3.59 MB/s) - powershell-6.0.4-linux-arm32.tar.gz saved [26030533/26030533]
 
#
ls
powershell-6.0.4-linux-arm32.tar.gz

We need to create an empty directory to store the PowerShell files, and since you can install multiple versions of PowerShell side by side I’ve created a separate directory for version 6.0.4.

#
mkdir /opt/microsoft/
mkdir /opt/microsoft/powershell/
mkdir /opt/microsoft/powershell/6.0.4/
#

Extract the PowerShell files to this folder.

#
tar -xpf ./powershell-6.0.4-linux-arm32.tar.gz -C /opt/microsoft/powershell/6.0.4/

So that we can invoke the shell in the same way as other commands, we need to create a link in  /usr/bin/ .


ln -s /opt/microsoft/powershell/6.0.4/pwsh /usr/bin/pwsh
ls /usr/bin/pwsh -alis
9164 0 lrwxrwxrwx 1 root root 36 Sep  6 23:05 /usr/bin/pwsh -> /opt/microsoft/powershell/6.0.4/pwsh

To allow all users to be able to run PowerShell (and not just root) we need to change the file permissions on the executable.

#
chmod 755 -R /opt/microsoft/powershell/6.0.4/pwsh
ls /opt/microsoft/powershell/6.0.4/pwsh -alis
9420 68 -rwxr-xr-x 1 root root 67688 Aug  7 21:52 /opt/microsoft/powershell/6.0.4/pwsh
#

Looking at the files in the PowerShell folder there is an interesting entry.

#
ls /opt/microsoft/powershell/6.0.4/
DELETE_ME_TO_DISABLE_CONSOLEHOST_TELEMETRY
en-US
libclrjit.so
  :
  :
  :
System.Xml.XmlSerializer.dll
System.Xml.XPath.dll
System.Xml.XPath.XDocument.dll
WindowsBase.dll

#

Optionally you can choose to delete the file.

#
rm /opt/microsoft/powershell/6.0.4/DELETE_ME_TO_DISABLE_CONSOLEHOST_TELEMETRY 

Finally we can actually start PowerShell, which takes a few seconds to finish loading and display the prompt.

#
pwsh
PowerShell v6.0.4
Copyright (c) Microsoft Corporation. All rights reserved.

https://aka.ms/pscore6-docs
Type 'help' to get help.

PS > 

There are several different ways to display the PowerShell version.

PS > 
PS > $PSVersionTable
 
Name                           Value
----                           -----
PSVersion                      6.0.4
PSEdition                      Core
GitCommitId                    v6.0.4
OS                             Linux 4.9.59-v7+ #1047 SMP Sun Oct 29 12:19:23 GMT 2017
Platform                       Unix
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0...}
PSRemotingProtocolVersion      2.3
SerializationVersion           1.1.0.1
WSManStackVersion              3.0
 
PS > $Host
 
Name             : ConsoleHost
Version          : 6.0.4
InstanceId       : fac514bf-0ca7-465d-a716-922534013a9f
UI               : System.Management.Automation.Internal.Host.InternalHostUserInterface
CurrentCulture   : en-GB
CurrentUICulture : en-GB
PrivateData      : Microsoft.PowerShell.ConsoleHost+ConsoleColorProxy
DebuggerEnabled  : True
IsRunspacePushed : False
Runspace         : System.Management.Automation.Runspaces.LocalRunspace
 
PS > Get-Host
 
Name             : ConsoleHost
Version          : 6.0.4
InstanceId       : fac514bf-0ca7-465d-a716-922534013a9f
UI               : System.Management.Automation.Internal.Host.InternalHostUserInterface
CurrentCulture   : en-GB
CurrentUICulture : en-GB
PrivateData      : Microsoft.PowerShell.ConsoleHost+ConsoleColorProxy
DebuggerEnabled  : True
IsRunspacePushed : False
Runspace         : System.Management.Automation.Runspaces.LocalRunspace
 
PS > 

Having installed PowerShell you will probably want to update the built in help.

PS > 
PS > Update-Help -Force -ErrorAction 0
 
 Updating Help for module Microsoft.PowerShell.Core
    Locating Help Content...
    [oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo]
 
PS > 

Below are a few commands you can try, remember that PowerShell functions that are not part of the core release will not be available – this includes  Get-IPAddress  (See below).

PS > 
PS > Get-ChildItem
 
    Directory: 
 
Mode                LastWriteTime         Length Name
----                -------------         ------ ----
--r---       10/08/2018     00:38       26030533 powershell-6.0.4-linux-arm32.tar.gz
 
PS >

 Get-ChildItem  returns all the child items in an object, and by default if no object is specified it lists all the child items in the current directory, which PowerShell treats as an object like everything else.

Alternativly you can call a methods in a namespace directly.

PS > 
PS > [System.Net.Dns]::GetHostbyAddress('127.0.0.1')
 
HostName  Aliases AddressList
--------  ------- -----------
localhost {}      {127.0.0.1}
 
PS > 

PS > 
PS > [System.Net.IPAddress]::Parse('127.0.0.1')
 
AddressFamily      : InterNetwork
ScopeId            : 
IsIPv6Multicast    : False
IsIPv6LinkLocal    : False
IsIPv6SiteLocal    : False
IsIPv6Teredo       : False
IsIPv4MappedToIPv6 : False
Address            : 16777343
IPAddressToString  : 127.0.0.1
 
PS >

You can define a function to return the IP Address (or Addresses) using  /sbin/ifconfig .

PS > 
PS > function Get-IPAddress {
>>     $_ipinfo = /sbin/ifconfig | Select-String 'inet'
>>     $_ipinfo = [regex]::matches($_ipinfo,"inet \b(?:\d{1,3}\.){3}\d{1,3}\b") | ForEach-Object value
>>     $_ipinfo = $_ipinfo.replace('inet ','') | Where-Object {$_ -ne '127.0.0.1'
>>     $_ipinfo
>> }
PS > 
PS > Get-IPAddress
192.168.0.149
192.168.0.189
PS > 

You can also return the addresses as IP address objects (as opposed to string objects), and display the addresses as strings using  .IPAddressToString  method.

PS > 
PS > function Get-IPAddress {
>>     $_ipinfo = /sbin/ifconfig | Select-String 'inet'
>>     $_ipinfo = [regex]::matches($_ipinfo,"inet \b(?:\d{1,3}\.){3}\d{1,3}\b") | ForEach-Object value
>>     $_ipinfo = $_ipinfo.replace('inet ','') | Where-Object {$_ -ne '127.0.0.1'
>>     ForEach ($Item In $_ipinfo) {[System.Net.IPAddress]::Parse($Item)}
>> }
PS > 
PS > Get-IPAddress
IsIPv6LinkLocal    : False
IsIPv6SiteLocal    : False
IsIPv6Teredo       : False
IsIPv4MappedToIPv6 : False
Address            : 2499848384
IPAddressToString  : 192.168.0.149

AddressFamily      : InterNetwork
ScopeId            : 
IsIPv6Multicast    : False
IsIPv6LinkLocal    : False
IsIPv6SiteLocal    : False
IsIPv6Teredo       : False
IsIPv4MappedToIPv6 : False
Address            : 3170937024
IPAddressToString  : 192.168.0.189
 
PS > (Get-IPAddress).IPAddressToString
192.168.0.149
192.168.0.189
PS > 

If we need the IP address of the name server address we have to get it from  /etc/resolv.conf .

PS > 
PS > [System.Net.IPAddress]::Parse(([string](Get-Content /etc/resolv.conf |
>> Select-String nameserver)).replace('nameserver ','')).IPAddressToString
192.168.0.254
PS >

As before if we just need the address as a string this simplifies things a bit.

PS > 
PS > ([string](Get-Content /etc/resolv.conf | Select-String nameserver)).replace('nameserver ','')
192.168.0.254
PS >

When you have finished you just exit like any other shell.

PS > exit
#

After a bit of messing about identifying the dependencies installing PowerShell on the Raspberry Pi turned out the be quite easy – but figuring out how to use it properly is going to take quite a while longer.


Raspberry Pi is a trademark of the Raspberry Pi Foundation

Advertisements
This entry was posted in Raspbian and tagged , . Bookmark the permalink.

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

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