PowerShell 101 from a Linux guy
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.
Observations
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
Man up
Help on powershell is quite good and for the Linux folks "man" works
|
The following pulls all new help files.
|
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).
|
Here are some more examples:-
Works with wildcards.
help alias help "*"
You can also search by parameter names or verbs.
|
- An alternative to help is "Get-Command" and is better in some cases. It will also tell you which of them are actual cmdlets and which are aliases. E.g.
Get-Command -Name ls Get-Command -Name Stop-Service Get-Command "resolve" Get-Command -Verb "Block"
Objectification of commands
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:-
|
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.
|
Because they are data structures, you can also reference the individual members in the shell which is very handy. For e.g.
|
Searching and filtering
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:</span>windows</span>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:</span>windows</span>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.
|
Variables and loops
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} $allprocs = (Get-Process) $allprocs_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 :-)" }
Other points
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.
- Several commands support -ComputerName and so you can run it on remote computers. You can also pass a comma separated list.
Get-Service -ComputerName <server1,server2>
You can search help for cmdlets that support this parameter.
|
- Providers - An interesting take on making some of the services available as a File system.
For e.g. you can access the registry and also make changes to it. "Get-Providers" will show the list of available providers.
|
Quick reference
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 } |