Having spent my last 7 years concentrating mainly on Linux® and related technologies, I spent 3 days with PowerShell and here are the some observations and anecdotes. Why PowerShell? Curiosity for one and I wanted to learn it from a perspective of how to use it in configuration management tools like Chef. As an disclaimer, I’m not an expert in PowerShell and spending 3 days is just scraping the surface but I did learn quite a bit in that time. Also my prediction is that PowerShell will be real force (if not already) in Windows environments. It is a mindset change for several Windows administrators who have grown up on GUIs but that is about to change in the coming years. And if you are Linux administrator, you are likely to feel more comfortable interacting the PowerShell way. I definitely did.
PowerShell was born in 2006 and so it has been around for some time. From the buzz, it seems to be gaining more attention in the last 2-3 years.
Just like the Linux shell, if you know your commands and the switches, you can be quite effective. Part of the learning is exploring and getting the feel off the way things are structured and where to look for help.
There is a decent naming convention to the cmdlets, which helps in guessing. In my limited trials it has been followed well on the main Windows cmdlets. The convention is “Verb-SingularNoun”. E.g. “Stop-Service” , “Start-Job”, “Get-NetFirewallRule”
Auto complete can be annoying for a Linux admin as it does not work the same way as Linux shells but the intent is good and you need to get used to it’s way of working.
PowerShell comes in both versions; 32 bits & 64 bits. Non-intuitively, they are structured such that “system32” directory has 64 bit binaries and “syswow64” has 32 bit binaries. Also the version number of the directory inside Windows –> System32 –> WindowsPowerShell is the version the module and not version of PowerShell itself.
There are 3 main versions; 2.0 in Windows 2008, 3.0 in Windows 2012, and 4.0 which is was released in Feb 2014. For a new starter 3.0 and 4.0 are the most important releases. Version 3.0 requires .NET framework 4.0 You can find the current version of PowerShell using.
$PSVersionTable
Help on powershell is quite good and for the Linux folks “man” works
man <command name>
or
help <command name>
The following pulls all new help files.
update-help
Once done, you can also use specific switches to get things like examples. You can also tell it to open a browser with the help page (assuming you have internet connection on the server and a browser).
help <command name> -example
help <command name> -online
Here are some more examples:-
Works with wildcards.
help *alias*
help "*"
You can also search by parameter names or verbs.
help -Name "*" -Parameter computername
help -Verb "block"
Get-Command -Name ls
Get-Command -Name Stop-Service
Get-Command "*resolve*"
Get-Command -Verb "Block"
PowerShell commands generate objects as opposed to text which is what *nix shells tend to do, although some individual *nix commands may have options for things like json. This can be quite powerful, especially since this is implemented quite well across all commands and cmdlets. So you can pipe the objects to other utilities to change formats from lists to tables., csv, etc. Lot of these are available as default and there is also XML but let’s not go there. If you go back to Linux, all of this is text and you end up relying a lot on awk, sed, perl, regex vodoo. *nix admins may argue text is unstructured but simpler in model but having them as objects does lend some good use-cases.
Here are some simple examples:-
Get-Process | Format-List
Get-Process | ConvertTo-Csv
Get-Service | ConvertTo-Json
Get-Process | ConvertTo-HTML | Out-File ps.html
For almost all cmdlets, all properties are not displayed. There is an internal default on the views. Note, the properties are still generated by the cmdlet but it is the view that hides them. You can look for all properties or you can list specific properties.
ls | get-member
Get-Service | Get-Member
"hello world" | Get-Member
Because they are data structures, you can also reference the individual members in the shell which is very handy. For e.g.
(ls).name
(ls).CreationTime
("hello world").Length
Because of the objects, you can do some fancy querying and filtering.
Using the Select-Object option.
Get-NetFirewallRule -Enabled True | Select-Object -Property DisplayName,Profile,Direction,Action | Sort-Object -Property DisplayName
List files greater than a size and of type “.dll”.
cd c:\windows\system32
ls | Where {$PSItem.Length -GT 5000000 -and $PSItem.Name -Like "*.dll"}
There are in built respresentations for things like MB, GB. So you can do this.
cd c:\windows\system32
ls | where Length -gt 10MB
The commands themselves have filtering options and so there are several ways to do the same. The internal filtering is faster than the “where” clause or even the shell’s wildcard evaluation. Here’s an example of this using “Measure-command” which is the similar to “time” on Linux.
PS C:\windows\system32> measure-command { ls | where {$_.Name -like "*.exe"} }
<output truncated>
TotalMilliseconds : 431.5992
PS C:\windows\system32> measure-command { ls *.exe }
<output truncated>
TotalMilliseconds : 141.2392
PS C:\windows\system32> measure-command { ls -Filter "*.exe" }
<output truncated>
TotalMilliseconds : 27.3214
Variables - You can do simple assignments, arrays, hash tables or the output of another command.
$value = "hello world"
$num = @{1,2,3}
$alerts = @{"warning"=60; "critical"=90}
$all_procs = (Get-Process)
$all_procs_json = (Get-Process | ConvertTo-Json)
To print them, just type the variable name. “echo” works as well for the Linux guy.
$value = "hello world"
$value
echo $value
You can do loops. They also have “awk” like begin and end blocks as well.
for ($i=0; $i -le 10; $i++) { $i }
Get-Process | foreach -Begin { Get-Date ; "Time to loop"} -Process { $PSITem.Name ; $PSITem.CPU; "----"} -End {"My loop ended :-)" }
This is random collection of stuff, I gathered and found useful.
History.
Get-History
Print the last command.
$$
Create new aliases. “man” command is an alias to help and you can do this yourself. Now that we have grep. I feel more at home :-)
New-Alias -Name grep -Description grep Select-String
If you don’t want Windows to keep popping up confirmation boxes for several of the commands (Windows likes to do this.), you can do this
Set-Variable -Name ConfirmPreference -Value Low
#or
Set-Variable -Name ConfirmPreference -Value None
Piping to “more” is not ideal as it causes PowerShell to evaluate the whole command before sending it. This is better.
help "*network*" | out-host -paging
You can alias “out-host” to something more familiar and if you want “less”, there is an extension at Code Plex.
Get-Service -ComputerName <server1,server2>
You can search help for cmdlets that support this parameter.
help * -parameter ComputerName
For e.g. you can access the registry and also make changes to it. “Get-Providers” will show the list of available providers.
Get-Providers
cd HKLM:
ls .\SOFTWARE\Microsoft\Windows\CurrentVersion
Bash/Linux | PowerShell |
---|---|
ls | ls |
mv | mv |
cp | cp |
pwd | pwd |
rm | rm |
cat | cat |
grep | search-string |
echo | echo |
var=0 | $var=0 |
df | gdr or Get-PSdrive |
wc | measure-object |
ps | ps |
find | gci |
diff | diff |
kill | kill |
time | measure-command |
if [condition] then something fi | if (condition) { something } |
-e file | Test-Path file |
for ((i=0; i < 10; i++)) ; do echo $i ; done | for ($i=0;$i -lt 10; $i++) { echo $i } |
-e file | Test-Path file |
for ((i=0; i < 10; i++)) ; do echo $i ; done | for ($i=0;$i -lt 10; $i++) { echo $i } |
Learn more about IT Transformation
Use the Feedback tab to make any comments or ask questions. You can also start a conversation with us.