PowerShell/Core7

From Ever changing code
Jump to navigation Jump to search

Installing PowerShell on Linux

Note: Ubuntu 20.04 is an LTS release. PowerShell does not currently support this version. Support for this version is being considered for the PowerShell 7.1 release. PowerShell can only support the distributions that are supported by .NET. See the Core release notes for a list of supported distributions.

# Centos
curl https://packages.microsoft.com/config/rhel/7/prod.repo | sudo tee /etc/yum.repos.d/microsoft.repo
sudo yum install -y powershell

# Ubuntu
snap install powershell --classic
powershell 7.0.2 from Microsoft PowerShell✓ installed

$ powershell # run or use 'pwsh' to start it up
PowerShell 7.0.2
Copyright (c) Microsoft Corporation. All rights reserved.

https://aka.ms/powershell
Type 'help' to get help.

PS /home/piotr> $PSVersionTable

Name                           Value
----                           -----
PSVersion                      7.0.2
PSEdition                      Core
GitCommitId                    7.0.2
OS                             Linux 5.4.0-1015-aws #15-Ubuntu SMP Thu Jun 4 22:47:00 UTC 2020
Platform                       Unix
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0…}
PSRemotingProtocolVersion      2.3
SerializationVersion           1.1.0.1
WSManStackVersion              3.0

Concepts

  • $_ - current object

<syntaxhighlightjs lang="powershell"> Get-ChildItem /var | ForEach-Object -Process {$_.FullName} /var/backups /var/cache ... </syntaxhighlightjs>

  • source a script into the current session . ./functions.ps1. Use get-command functionName to verify loaded functions into the session context. This works similar to Linux shell sourcing.
  • module - set of related Windows PowerShell functionalities grouped together as convenient units
  • Scripts should end with .PS1 so they are loaded and run in the current process and it's expected behaviour of PowerShell. The magic number #! can be used, but script will be run in a new PowerShell instance preventing accessing to current process objects. This might be desirable when executing PowerShell from bash or another shell.
  • help
    • use Get-Member to get a list of available properties of an object
    • search a commands with Get-Command *user*, see filtered example below:

<syntaxhighlightjs lang="powershell"> CommandType Name Version Source


---- ------- ------

Alias Set-AzADUser 2.2.0 Az.Resources Function Disconnect-AzWvdUserSession 1.0.0 Az.DesktopVirtualization Cmdlet Add-AzApiManagementUserToGroup 2.0.1 Az.ApiManagement Cmdlet Get-AzADUser 2.2.0 Az.Resources Cmdlet Update-AzADUser 2.2.0 Az.Resources Application adduser 0.0.0.0 /usr/sbin/adduser Application adduser 0.0.0.0 /sbin/adduser </syntaxhighlightjs>

Environment profiles

Any commands included in the profile file will be executed during terminal/shell initialization. Note: This is not working while switching the shell and is executed on the new terminal initiation <syntaxhighlightjs lang="powershell"> > $profile /home/piotr/.config/powershell/Microsoft.VSCode_profile.ps1 </syntaxhighlightjs>

Pipeline

Everything in PS is an object, although we use '|' piping this is not the same concept as STDIN and STDOUT in Linux. <syntaxhighlightjs lang="powershell"> PS> Get-Process -Name whoopsie | Get-Member -Name CPU,Company PS> Get-Process -Name whoopsie | Select-Object -Property name,CPU

Name CPU


---

whoopsie 0.24

  1. When assigning to a variable we assign an object not just a string

$variable = Get-Process S> $variable | Select-Object -Property name,CPU | Sort-Object -Descending CPU | Select-Object -First 5

Name CPU


---

gnome-shell 11796.69 firefox 11012.4599999 Web Content 7573.22 Web Content 5085.47 Xorg 3593.26 </syntaxhighlightjs>

Variables

These are objects. <syntaxhighlightjs lang="powershell"> S /home/piotr> Get-Help *variable* Name Category Module Synopsis


-------- ------ --------

Clear-Variable Cmdlet Microsoft.PowerShell.Uti… … Get-Variable Cmdlet Microsoft.PowerShell.Uti… … New-Variable Cmdlet Microsoft.PowerShell.Uti… … Remove-Variable Cmdlet Microsoft.PowerShell.Uti… … Set-Variable Cmdlet Microsoft.PowerShell.Uti… … </syntaxhighlightjs>

if

<syntaxhighlightjs lang="powershell"> if ($var -gt 5) {

 write-host "true"

} elseif {

 write host "false"

} </syntaxhighlightjs>

do/while

<syntaxhighlightjs lang="powershell"> Do {

   $number = $number + 1 
   write-host "current nuber is: $number"

} while ($number -lt 10) </syntaxhighlightjs>

for each

<syntaxhighlightjs lang="powershell"> $names = "Bob","Jamse","Tom" $collection = $names $count = 0 foreach ($item in $collection) {

   $count += 1
   Write-Host "$item"

} Write-Host "$count" </syntaxhighlightjs>

Convert

Working with Powershell pipelines it means workign with objects, so we format output but not modifying it. This is power full combination allowing for object/output convertn at any time. <syntaxhighlightjs lang="powershell"> Get-Process | Sort-Object -Descending CPU | Select-Object -First 5 | ConvertTo-Json

  1. more convert formats

Convert-AzSqlDatabase... ConvertFrom-Json ConvertFrom-StringData ConvertTo-Json Convert-AzSqlInstance... ConvertFrom-Markdown ConvertTo-AzVMManagedDisk ConvertTo-ScriptExtent Convert-Path ConvertFrom-ScriptExtent ConvertTo-Csv ConvertTo-SecureString ConvertFrom-Csv ConvertFrom-SecureString ConvertTo-Html ConvertTo-Xml </syntaxhighlightjs>

Add calculated property field

<syntaxhighlightjs lang="powershell">

  1. Syntax: @{ Name = ; Expression = {}}

Get-Process | Select-Object -Property Name, @{ Name = 'MGB'; Expression = {$_.VM / 1gb -as [int]}} | Sort-Object -Property MGB -Descending | Select-Object -First 3

 # MGB - property name; $_  - current object

Name MGB


---

code 12 gnome-shell 4 pwsh 3 </syntaxhighlightjs>


Add a new property to an object by utilising 'ScriptProperty' to enrich an object with extra TypeSet (aka data, column etc.). <syntaxhighlightjs lang="powershell"> Update-TypeData -TypeName System.Diagnostics.process -MemberType ScriptProperty -MemberName MGB -Value {$this.VM/1gb -as [int]} Get-Process | Get-Member M* PS /home/piotr> Get-Process | Get-Member M*

  TypeName: System.Diagnostics.Process

Name MemberType Definition


---------- ----------

MachineName Property string MachineName {get;} MainModule Property System.Diagnostics.ProcessModule MainModule {get;} (...) Modules Property System.Diagnostics.ProcessModuleCollection Modules {get;} MGB ScriptProperty System.Object MGB {get=$this.VM/1gb -as [int];} </syntaxhighlightjs>

Function

<syntaxhighlightjs lang="powershell"> function func-name {

 set-location /opt/

} </syntaxhighlightjs>

Multiple scripting languages within Powershell

Using hash doc(aka hash string, hash notastion) we can execute multiple scripting languages within Powershell to bounce between multiple languages. Each output is an object with all PowerShell properties. <syntaxhighlightjs lang="powershell"> @'script.py'@

$index = @" <html>

<body>

Hello!

</body>

</html> "@

$index | Set-Content index.html # write variable content into the file </syntaxhighlightjs>

PowerShell7 remoting over SSH

<syntaxhighlightjs lang="powershell">

  1. Help on syntax

Get-Command New-PSSession -Syntax

New-PSSession [[-ComputerName] <string[]>] [-Credential <pscredential>] [-Name <string[]>] [-EnableNetworkAccess] [-ConfigurationName <string>] [-Port <int>] [-UseSSL] [-ApplicationName <string>] [-ThrottleLimit <int>] [-SessionOption <PSSessionOption>] [-Authentication <AuthenticationMechanism>] [-CertificateThumbprint <string>] [<CommonParameters>] New-PSSession [-ConnectionUri] <uri[]> [-Credential <pscredential>] [-Name <string[]>] [-EnableNetworkAccess] [-ConfigurationName <string>] [-ThrottleLimit <int>] [-AllowRedirection] [-SessionOption <PSSessionOption>] [-Authentication <AuthenticationMechanism>] [-CertificateThumbprint <string>] [<CommonParameters>] New-PSSession [-VMId] <guid[]> -Credential <pscredential> [-Name <string[]>] [-ConfigurationName <string>] [-ThrottleLimit <int>] [<CommonParameters>] New-PSSession -Credential <pscredential> -VMName <string[]> [-Name <string[]>] [-ConfigurationName <string>] [-ThrottleLimit <int>] [<CommonParameters>] New-PSSession [[-Session] <PSSession[]>] [-Name <string[]>] [-EnableNetworkAccess] [-ThrottleLimit <int>] [<CommonParameters>] New-PSSession -ContainerId <string[]> [-Name <string[]>] [-ConfigurationName <string>] [-RunAsAdministrator] [-ThrottleLimit <int>] [<CommonParameters>] New-PSSession -UseWindowsPowerShell [-Name <string[]>] [<CommonParameters>] New-PSSession [-HostName] <string[]> [-Name <string[]>] [-Port <int>] [-UserName <string>] [-KeyFilePath <string>] [-SSHTransport] [-Subsystem <string>] [<CommonParameters>] New-PSSession -SSHConnection <hashtable[]> [-Name <string[]>] [<CommonParameters>] </syntaxhighlightjs>


Ssh session <syntaxhighlightjs lang="powershell">

  1. Install packages

sudo apt install openssh-server openssh-client

  1. Ssh-server 'sshd_config' adjustments for 'pssession' to make it work

sudo vi /etc/ssh/sshd_config PasswordAuthentication yes PubkeyAuthentication yes Subsystem powershell /usr/bin/pwsh -sshs -NoLogo -NoProfile # depends on your OS

  1. Subsystem powershell /snap/powershell/132/opt/powershell/pwsh -sshs -NoLogo # <- Ubuntu 20.04 uses snap package
  1. PSSession

Entry-PSSession -HostName 127.0.0.1 -UserName piotr # get into ssh session [localhost]: PS /home/piotr>

New-PSSession -HostName 127.0.0.1 -UserName piotr # create an object piotr@localhost's password:

Id Name            Transport ComputerName    ComputerType    State         ConfigurationName     Availability
-- ----            --------- ------------    ------------    -----         -----------------     ------------
12 Runspace11      SSH       localhost       RemoteMachine   Opened        DefaultShell             Available

</syntaxhighlightjs>

File manipulation

<syntaxhighlightjs lang="powershell">

  1. Output to a file

Get-Process | head | ConvertTo-Json | Out-File output.json # saves 10 top lines using Linux command

  1. Read a file content

$data = Get-Content ./output.json | ConvertFrom-Json

  1. This is still an object, check 'get-member' or using 'measure' you can see that only 10 lines have been selected

$data | Sort-Object -Descending CPU | measure </syntaxhighlightjs>

Cloud provider tools

AWS

AWS Tools <syntaxhighlightjs lang="powershell"> Get-Module # get currently installed modules Get-Module -ListAvailable -Refresh

  1. Aws Tools

Install-Module -Name AWS.Tools.Installer -Force Install-AWSToolsModule AWS.Tools.EC2,AWS.Tools.S3 -CleanUp Get-AWSPowerShellVersion -ListServiceVersionInfo

Install-Package -Name AWSPowerShell.NetCore # install a software from PSGallery Install-Module -Scope CurrentUser -Name AWSPowerShell.NetCore -Force Install-Module -name AWSPowerShell.NetCore Install-Module -name AWSPowerShell.NetCore -Force # force untrusted repository Import-Module AWSPowerShell.NetCore # import the module and bring into our profile

Get-Command -Module AWSPowerShell.NetCore | Out-Null # piped to null-out as there is over 4k commands Get-Command *aws* # display avaialble AWS cmdlets

  1. Set credentials

Set-AWSCredentials -AccessKey AKI... -secretKey Zo... -StoreAs aws-profile-1 Get-AWSCredential -ListProfileDetail ProfileName StoreTypeName ProfileLocation


------------- ---------------

aws-profile-1 SharedCredentialsFile /home/piotr/.aws/credentials

  1. Preview credentials file

Get-Content /home/piotr/.aws/credentials [aws-profile-1] aws_access_key_id=AKI... aws_secret_access_key=Zo...

  1. Set default AWS profile

Set-AWSCredentials -ProfileName aws-profile-1 </syntaxhighlightjs>


Manage a resource <syntaxhighlightjs lang="powershell"> PS> New-S3Bucket -BucketName foo123example-powershel7 PS> Get-S3Bucket CreationDate BucketName


----------

17/07/2020 13:10:39 foo123example-powershel7

  1. Upload a file

PS> Write-S3Object -File ./.bashrc -BucketName foo123example-powershel7

  1. List files

PS1> Get-S3Object -BucketName foo123example-powershel7 ETag  : "fe225aefed67a397fd160d5a0b4e7e35" BucketName  : foo123fffowjkgpowj Key  : .bashrc LastModified : 17/07/2020 13:41:50 Owner  : Amazon.S3.Model.Owner Size  : 5655 StorageClass : STANDARD

</syntaxhighlightjs>

GCP Google Cloud Platform

Note: Please be aware that GoogleCloud module may not support all security services or operations, but with each release more covarage is being added on

Install gcloud cli

Install Powershell GoogleCloud

<syntaxhighlightjs lang="powershell"> PS> Install-Package GoogleCloud Name Version Source Summary ---- ------- ------ ------- GoogleCloud 1.0.1.10 PSGallery PowerShell cmdlets for the Google Cloud Platform.

  1. As part of the import you will be prompted to install 'gcloud' utility and Google Cloud SDK

PS> Import-Module GoogleCloud PS> Get-Module

ModuleType Version PreRelease Name ExportedCommands


------- ---------- ---- ----------------

Script 1.0.1.10 GoogleCloud {Add-GcdChange, Add-GcdManagedZone, Add-GceAddress, Add-GceFirewall…} (...clipped)

Get-Command -Module GoogleCloud # get all Cmdlets added </syntaxhighlightjs>


Create and delete a resource <syntaxhighlightjs lang="powershell"> New-GcsBucket -Name bucket-1-fkwejafp # bucket name need to be globally unique DNS compliant formatted name Name TimeCreated Updated


----------- -------

bucket-1-fkwejafp 07/06/2020 08:07:07 07/06/2020 08:07:07

PS> Get-GcsBucket -Name bucket-1-fkwejafp | measure # Note there is just one object

Count  : 1 Average  : Sum  : Maximum  : Minimum  : StandardDeviation : Property  :

PS> Get-GcsBucket -Name bucket-1-fkwejafp | Remove-GcsBucket # pipe that object to 'remove-' cmdlet PS> Get-GcsBucket -Name bucket-1-fkwejafp Get-GcsBucket: Storage bucket 'bucket-1-fkwejafp' does not exist.

  1. Create VM

$disk = Get-GceImage "windows-cloud" -Family "windows-2012-r2" $config = New-GceInstanceConfig "my-vm-1" -MachineType "n1-standard-4" -DiskImage $disk $config | Add-GceInstance -Project $project -Zone us-central1-b

Get-GceInstance -Name my-vm-1 -Zone us-central1-b

Name CpuPlatform MachineType Zone TimeCreated


----------- ----------- ---- -----------

my-vm-1 Intel Haswell n1-standard-4 us-central1-b 2020-07-17T06:36:37.018-07:00

$instance = Get-GceInstance "my-vm-1" Stop-GceInstance $instance Set-GceInstance $instance -AddMetadata @{"newKey" = "newValue"} # in UI it's called 'Custom metadata' </syntaxhighlightjs>

Azure

Install Az Microsoft Azure PowerShell from PowerShell Gallery or as alternative use PowerShellGet.

Install-Module -Name Az
Import-Module Az
Get-Module # lists all new available commands
Get-Module -name Az -ListAvailable # include modules source directory



References