New-ItemProperty IIS:\sites\DemoSite -name bindings -value @{protocol="http";bindingInformation=":8081:"}
http://www.iis.net/learn/manage/powershell/powershell-snap-i...What did I just modify? Is it persisted to the hard disk? How do i back that up? How do I revert the change? How do I move this change (and 20 others) from one server to another? It's three months later, and I want to do something similar, where can I find the current state of DemoSite and mimic it for DevSite?
I like plain text. Clearly companies succeed on microsoft products and people make money administering them. Doesn't mean I have to like it.
Doesn't look that much different or arcane to how you'd do it in Linux.
Except more structured (which is good).
>What did I just modify? Is it persisted to the hard disk? How do i back that up? How do I revert the change? How do I move this change (and 20 others) from one server to another?
Oh, the humanity of learning a different way of doing things.
IIS:\>New-WebBinding -Name "Default Web Site" -IPAddress "*" -Port 80 -HostHeader TestSite
https://technet.microsoft.com/en-us/library/ee790599.aspxWouldn't it be, for his example of changing the port:
Set-WebBinding -Name 'RadWebServer' -IPAddress "*" -Port 443 -PropertyName Port -Value 4430
I don't have a huge amount of PowerShell experience so maybe that's incorrect or has extra bits.By the way, please stop. I'm having SMIT flashbacks.
Oh, god, the running man. Don't trip, donttripdonttripdontripdontrip...
If you want to become a systems administrator of Windows servers then I'd suggest reading at least one book on the subject, you're not going to get there by copying and pasting one command you found on the internet.
Just as it is with linux/unix. Just as it is with anything.
Pretending otherwise is disingenuous and intellectually dishonest.
IIS has its' own set of commands that you may be more comfortable with, appcmd is sorta like apachectl (just more verbose). http://www.iis.net/learn/get-started/getting-started-with-ii....
The other place you see providers in use is when you use PS to edit the registry, but it's HKLM:\ (or whatever other hive) instead of IIS:\, and it makes a lot more sense there since people naturally think of the registry in a filesystem sort of way.
More info if you're curious about providers:
https://technet.microsoft.com/en-us/%5Clibrary/Ee126186(v=VS...
What these generally do is parse the entire configuration file into an abstract syntax tree, apply the modifications you have asked for to the tree, then serialize the result back into the configuration file format. This ensures that the input and the output are both at least syntactically valid; as a result it is less error-prone than sed/awk. Unlike with configuration file templates (e.g., Ansible's Jinja2 templates) the changes can be applied on top of the distribution's default configuration if desirable and reapplied when that default configuration is updated.
IP Address:Port:Virtual Host
For example: 172.16.1.1:80:www.example.com
The raw values reside in an XML config file called "applicationHost.config" which replaces the old school and rather opaque IIS6 metabase.Admittedly that example is a bit old school, there's better commandlets available now that wrap having to manipulate these string values directly. e.g. the New-WebBinding and Set-WebBinding examples shown in sibling comments in this sub-thread.
A site config looks like:
<site name="MyWebSite" id="3" serverAutoStart="true">
<application path="/" applicationPool="MyWebSite">
<virtualDirectory path="/" physicalPath="D:\websites\mywebsite\www" />
</application>
<bindings>
<binding protocol="http" bindingInformation="172.16.1.1:80:example.com" />
<binding protocol="http" bindingInformation="172.16.1.1:80:www.example.com" />
<binding protocol="https" bindingInformation="172.16.1.:443:" />
</bindings>
</site>
None of this is particularly mysterious, and the documentation is pretty good.get-command
get-command | where CommandType -eq "alias"
Notice the lack of parsing. In Unix you'd typically do this kind of thing with grep, but then you'd have to watch out that you don't accidently include the wrong rows because some other column happened to contain the string "alias"
Try this:
Get-Command | Out-GridView
There's this thing called PowerGUI. It has a text editor for writing PS and a computer management GUI tool. It's written in PS itself. At first I wasn't too impressed, but then I noticed in the computer management thing there's an option to "view code". And then I saw how simple it is, how these nice interfaces were implemented with a trivial amount of PowerShell. Now I think PowerShell is great.
Edit: Restart-Service is also easier to remember than /etc/init.d was.
Edit 2 (rate limit): `service` on RHEL is great, but it's a Red Hat-ism. Which is fine, I used to work at Red Hat, but still.
It's also pretty limited: you use service to start/stop/restart, but you still use systemctl to list services, or list /etc/init.d (technically /etc/rc.d/init.d on RHEL) on older boxes.
On Windows, to get services, it's `get-service`
Fun exercise for readers, given that you now know `restart-service` and `get-service`:
- Guess what the powershell command to get processes is.
- Guess what the powershell command to stop a process is.
- Guess what the Powershell command to install a package is.
There's some weird ones - dmidecode on Linux becomes get-wmiobject on Powershell (see the rosetta stone link posted earlier) - but for the most part it makes more sense than Linux and Unix.
(They are implemented as .NET classes loaded from within libraries, as I recall. Eg, `import-module activedirectory` will load the entire library of AD cmdlets.)
Here's what you can do with object streams:
Get-ADUser | select FirstName,LastName,EmailAddress,Department | where {$_.FirstName -contains "Jeffery"} | format-table
In a traditional Unix pipeline, you'd have to make sure that none of the other fields contained "Jeffery", or you could get false positive results. For example, you might have to use multiple named pipes or temporary files for each of the table columns, and reinterpolate them into a table/CSV/whatever after doing the grep. You could always use Python/Perl/Ruby/Tcl instead of course, but those aren't really shells.
You can also do math, method calls, etc. The example above was just a trivial one.
- Timing issues with something as simple as "remove file," where the agreed upon Stack Overflow solution was to call it "a few more times until you didn't get an error."
- Broken implementations of recursive folder copy.
- Okay, we'll call upon "rm" and "rmdir" -- oh, PowerShell intercepts those and invokes the previously described buggy routines. (Eventually figured out that I needed to shell out completely.)
In the end I regretted writing these crummy house-of-cards PowerShell scripts.
There's a missing "on Windows" here. Sure, PowerShell is clearly a tool designed for the Windows environment. And if you're a Windows system administrator, it has more tools and glue for that environment. You could use PowerShell to replace things that you'd otherwise have to write in Python or similar, not shell.
But that doesn't make it "unquestionably a better language to use for scripting" overall; it makes it a better fit for its target platform, which is certainly true.
And an earlier part of the document made exactly that point: PowerShell on Linux would be as uncomfortable as Cygwin is on Windows. There's an impedance mismatch there.
Powershell isn't just "more tools and glue for windows stuff", it's a different way of doing things. In powershell you get named command-line parameters for free, that's a huge win. You get usage messages and simplified man-page help baked into the way things work, that's also huge. In powershell you don't just work with text, you work with objects, which pass along the pipeline. That means that instead of using sed and awk to muck up the output of some other script you can just use simple select, where, and format commands. This is incredibly powerful and an area where linux has fallen behind.
I like linux a lot, but this attitude of sneering down at windows and powershell merely because it's not linux is amateurish and parochial. People should be thinking about adapting the innovations that powershell has made and building on them instead of looking at it as some bizarre alien beast that will never be relevant to them.
But Powershell people dismiss the bash and Linux model of "everything's a file", too, the same way others dismiss the Powershell model. They're different; neither is "unquestionably" better for all cases.
Personally, once I start wanting stateful objects I can pass around to multiple methods, I switch from Bash to Python or Rust. I don't think Bash fits that use case well either, but that's not the only use case around.
This whole comment about "on Windows" is completely beside the point. And the impedance mismatch, as you said, was already commented about in the article.
Debatable, and certainly not "unquestionably" as the article suggests. You could certainly make the argument, but you don't get to drop the mic afterward.
Sounds like both shells have one of those problems... ;)
A Powershell object piping system would be great on Unix too. Scraping text is fragile and slow.
Obviously for a Unix port you wouldn't write cmdlets in .net like Powershell but something popular in the Linux/Unix admin world, most likely Python.
In PowerShell 5 (at least in Windows 10), Ctrl-Space yields a list of matching completions. You can then use the arrow keys (ip, down, left, right) to pick one and hit enter or space to select.
It works for commands as well as for options/parameters and parameter values.
I.e. you can type get-pr[ctrl-space] and powershell responds with:
Get-PrintConfiguration Get-PrinterDriver Get-PrinterProperty Get-Process
Get-Printer Get-PrinterPort Get-PrintJob Get-ProvisionedAppxPackage
Choose Get-Process (right,right,right,space). Now the cmdline shows Get-Process _
Hit [-][ctrl-space]. Powershell now shows: PS C:\Users\zaphod> Get-Process -Name
Name IncludeUserName FileVersionInfo ErrorAction ErrorVariable OutVariable
Id ComputerName Verbose WarningAction WarningVariable OutBuffer
InputObject Module Debug InformationAction InformationVariable PipelineVariable
Pick "Name" and hit space: PS C:\Users\zaphod> Get-Process -Name _
Now hit [ctrl-space] again. PowerShell now completes on running processes on the system, offering the list of all of the process names.Personally I don't think this is elegant, but that's what I usually encounter in the wild.
But yeah, I don't like the cycling, either. I'd also prefer to get a list of the possible completions.
I live and breathe Linux. But Powershell is so far ahead of bash for text and object manipulation, it's not really even a close call.
P.S. *nix shell != bash, there's zsh and fish that are light years ahead re: tab completion and other general niceties.
On powershell if I want to find a list of files that are more than 100k in size I can just do "gci | where Length -gt 100000". If I want to see the top 10 processes that have the most handles open I just run "get-process | sort handles -desc | select -first 10". That way of interacting with things extends all the way through every aspect of powershell and it's incredibly potent. If I want to query a bunch of build jobs from a service I can just create a simple couple line script that talks to a web service and returns queries. Then I can use the built in select, where, format, etc. commands to get at the data I want. I can filter by jobs that have failed, I can filter by jobs of a certain type, or that ran on one machine. All of that is basically free on powershell, it's just baked into the way everything works. It saves you from all the ridiculous overhead of using perl, sed, awk, etc. just to get at the data you want.
Aside from that, with powershell you get things like man-page-style help and usage messages, named parameters, parameter type checking, etc. at very low cost, as just the natural way of doing things.
The Unix philosophy has always been about having small tools that you can use together to get big stuff done, powershell very much embodies that philosophy.
FTFY
diff <(cat output.txt) <(cat output.txt | sort -n)
Then I wrote the PowerShell: get-content output.txt | foreach-object { [Int] $_ } | sort-object | out-file -encoding ascii sorted.txt
compare-object (get-content output.txt) (get-content sorted.txt)
Yeah, it's a lot longer. It was the bug that really soured me, though. The files compare as identical even if output.txt is not sorted.You go read Microsoft tutorials [1] and they tell you to use Get-Content (cat) and Compare-Object (diff) like this for comparing files, but what they don't tell you is that order is ignored. Given how often I see the above code cited online for comparing files [2][3], I'm not sure that many people actually understand this.
I still haven't actually figured out how you properly compare files with PowerShell. I call fc.exe now, but its output is pretty gnarly so all I use is the return value.
[1] https://technet.microsoft.com/en-us/library/Ee156812.aspx [2] http://blogs.technet.com/b/heyscriptingguy/archive/2015/04/0... [3] http://serverfault.com/questions/5598/how-do-i-diff-two-text...
diff (cat out.txt | sort | out-string) (cat out.txt -raw)
do it?I suppose the lesson is that if you want to preserve line order, you need to use -raw to prevent Get-Content (cat) from splitting the file into multiple lines. That still ruins the output text from Compare-Object (diff), but it's cleaner than fc.exe.
Thanks.
Sadly for those of us who detest the shell, nobody seems to have a good replacement at hand.
EDIT: superfluous "I" removed
Precisely my impression as well. It's the PowerShell promoters who tend to be the ones that bait first.
I'm personally not partial to PowerShell, but I hardly loathe it, either. I think the likes of the Inferno shell and es show the right path to what a modern shell should resemble.
Get-Help about_Execution_Policies # Tells you everything you need to know about
So the first thing I typically do in PowerShell in user accounts I control is:
Set-ExecutionPolicy RemoteSigned -Scope CurrentUser
After that I can run all the scripts I want to run. (From there it's a quick jump over to Chocolatey for application installs and PsGet for useful PowerShell scripts like PoshGit that adds your friendly Git branch info to the PowerShell prompt.)
Here's map/filter/reduce. Golf welcome.
@(1, 2, 3) `
| % { $_ + 1 } `
| ? { $_ -gt 2 } `
| Measure-Object -Sum
| Select Sum
You can write a generic reduce like this: $reduce = {
param ([scriptblock]$reducer)
begin { $initialised = $false }
process {
if (-not $initialised) {
$agg = $_
$initialised = $true
} else {
$agg = &$reducer $agg $_
}
}
end { $agg }
}
And then use it like this: @(1, 2, 3) | &$reduce { param($agg, $i) $agg + $i }That all said, the most recent PowerShell I've significantly touched was version 2; I've since moved on to greener pastures.
I also agree with the author, you don't try enough or don't bother trying.
i LOVE nix environnements, but i HAVE to work on Windows. And yeah, at first, it's a pain. Nothing works as expected and you get bunch of errors ... but you have to remember that you're not on a nix terminal !
You don't expect to master a environnement on a first try, do you ? Remember this is not the term you know and love. And if you take some time to get used to, here is your reward:
you will be able to rocks the term on Windows too, and that's pretty badass.
This, and vice versa that you see in other online communities. Debating your religious position is almost becoming safer than stating your technology choices, which like religion are quite often not your choices to start with.
As far as verbosity, its a mixed bag for me. It makes it easy to read at a glance with minimal mental parsing but at the same time seems such an incorrect fit for a shell where it is optimal to have it under a screen line. You can equate it to trying to write a rant on twitter.
Having to port a script from Powershell v5 to Powershell v2 is dumb, but sadly necessary. Usually I'll write a script on the oldest server in the farm to ensure interoperability. But often the workarounds for v2 break v5's implementation of select-string or other parsing tools.
And this doesn't get into remote execution or remote script enablement, which are both separate. Powershell fragmentation is a serious problem that complicates Windows adminstration and use of this powerful tool.
I wish the team in charge of Powershell would take a page from the Python community and adopt an opinionated, "one right way to do everything" stance. For anyone using or looking in to Powershell, here are a few best practices I've compiled:
- Concurrency in Powershell is generally ugly and painful. Background jobs are OK if you want to background something while you're working at the command line (although you could just open another window) but they're a pain to use in scripts, plus they're very heavyweight and slow if you need any semblance of performance. There are other ways of doing concurrency but they are not well documented and are fairly messy. Events/observer pattern is possible but weird. If you need concurrency, head for C#.
- Handling exceptions is way better than it used to be (trap), but still annoying. For your sanity and everyone else's, set $ErrorActionPreference = "Stop" at the top of every script, along with Set-StrictMode -Version Latest.
- Keep track of what you're outputting to your pipeline - anything that generates output that you're not capturing into a variable gets thrown in the pipeline, which can wreak havoc, especially if you end up with different types of objects being emitted. Sprinkle Out-Null around to avoid this. Combine multiple data fields into a new psobject if necessary (this is also good for scripts that output a bunch of information at the end).
- Don't use Write-Host - it's not output and thus can't be redirected. Use Write-Verbose frequently, and consider adding $VerbosePreference = 'Continue' in your profile to see verbose output all the time.
- If you need to access a SQL database, use ADO.NET. Invoke-SqlCmd and the rest of the sqlps module are a mess, at least the last time I looked. You can use sqlcmd.exe too but then you're back to text output.
- Add this to your profile. With this, any time you run something at the command line, it will be stored in $LastObject. I always forget to store stuff in a variable.
function Out-Default { $input | Tee-Object -var global:LastObject | Microsoft.PowreShell.Core\out-default }