PowerShell/Core7
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
. Useget-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 frombash
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:
- use
<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
- 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
- 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">
- 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">
- 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">
- Install packages
sudo apt install openssh-server openssh-client
- 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
- Subsystem powershell /snap/powershell/132/opt/powershell/pwsh -sshs -NoLogo # <- Ubuntu 20.04 uses snap package
- 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">
- Output to a file
Get-Process | head | ConvertTo-Json | Out-File output.json # saves 10 top lines using Linux command
- Read a file content
$data = Get-Content ./output.json | ConvertFrom-Json
- 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
- 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
- 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
- Preview credentials file
Get-Content /home/piotr/.aws/credentials [aws-profile-1] aws_access_key_id=AKI... aws_secret_access_key=Zo...
- 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
- Upload a file
PS> Write-S3Object -File ./.bashrc -BucketName foo123example-powershel7
- 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.
- 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.
- 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
- Known Issues for PowerShell on Non-Windows Platforms - read about case sensitivity Linux/Windows
- .NET Core Home GitHub