> I’m willing to admit that PowerShell isn’t obviously better as a shell than something like bash, but it’s unquestionably a better language to use for scripting.
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.
I've lived in both the windows and linux/unix worlds and I will say that powershell is a better scripting language than bash. Bash is ok, but powershell is nicer. Powershell is sort of like python in that it tends to force down a path of doing things in a certain way.
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.
I'm not sneering at PowerShell because it's not Linux. And I think it's an impressive model. It's certainly a different way of doing things, and it's worth looking at and learning from.
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.
Personally I think an interactive shell that works well with objects is incredibly valuable. I love working in PowerShell and I wish there was a good Python based shell that I could use to replace zsh. I spend a lot of time in iPython but it's not quite the same.
If you take away the platform and command differences, then Bash is a worse scripting language than Powershell. Bash is a rough programming language to work in.
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.
> Bash is a worse scripting language than Powershell
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.
I work primarily in a Microsoft environment, although I have Linux shell experience as well, and I totally don't get Powershell. What is a cmdlet? Why does it need a stupid made-up name like that? Why are all the commands incredibly verbose and hard to remember? I avoid using it at every opportunity.
A cmdlet is a PowerShell native command. It reads and writes objects, where as Unix commands read and write plain text. Try this in PowerShell:
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.
As a Unix person, 'Restart-Service' seems a lot easier to remember than 'systemctl'.
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.
Or /etc/rc.d/apache2 restart, as one would find in the BSD world (and Slackware, with a bit of modification).
This isn't to mention that it should be relatively trivial to map "restart-service $foo" to "/etc/rc.d/$foo restart" or "systemctl $foo.service restart" or whatever if one so chooses.
Powershell cmdlets are different(ly named) than executables/commands because they don't preferentially emit text: they emit .NET object streams. I suspect this is for compatibility/interrop reasons.
(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.)
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.
I find Powershell extremely weird. We have a fair number of Powershell scripts for admin tasks and frankly I think they'd all be easier to understand if they were just written in C#.
Mhmm. I wrote a set of PowerShell scripts to do some basic deployment stuff a while back and I discovered...
- 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.
The tab completion in powershell is frustrating to me. I never want to cycle through every available option (especially when many PSH commands have literally hundreds of switches). I want the tab-completion to only show options for which I've started typing the prefix. I want double-tab to print a listing of said options so that I can see them all at once. Is this possible? Right now it feels like there's a major lack of discoverability in PSH.
> I want double-tab to print a listing of said options so that I can see them all at once. Is this possible?
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:
Yeah, that really bothered me coming from bash. I agree it's not as good from a discoverability perspective. Having said that, it's not the kind of thing that has continued to bother me over time. I've gotten used to it.
Agreed regarding the default tab completion. You might check out PSReadLine at some point - see https://github.com/lzybkr/PSReadLine. Its goal is to try to emulate readline except in PowerShell (this includes tab completion as well as emacs shortcut keys... vim shortcut keys are in the works AFAIK). It does require some additional configuration and it isn't installed by default, but I think it helps with this specific scenario quite a bit.
For what it's worth, Windows 10 enhances the basic command host to support some more things such as nicer tab completion directly out of the box (for both traditional cmd.exe and PowerShell) without having to switch to ISE.
Hm? After typing "xyz -fo" I will get completions beginning "-fo", such as "-foo" and "-foobar", but I won't get completions that don't begin with "-fo".
But yeah, I don't like the cycling, either. I'd also prefer to get a list of the possible completions.
As someone who used to use PowerShell rather extensively (back when my dayjob regrettably involved thousands of Windows machines that needed managing and support), I feel like trying to compare PowerShell to, say, bash is folly. To me, PowerShell has more in common with a proper scripting language - somewhere between Perl and Ruby, but with a nice-ish REPL - than a traditional shell like bash. Both the Unix-style text-centric paradigm and the PowerShell-style object-centric paradigm have their place.
That all said, the most recent PowerShell I've significantly touched was version 2; I've since moved on to greener pastures.
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.
>I dislike windows (and by extension, powershell) because a solution such as changing the port the webserver runs on looks something like:
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.
And THAT is the other thing. bash 7 years ago is the same as bash today, no changes based on some corporate overlords marketing idea of the month. Powershell is still in flux, and with MS as the owner, when will it ever be stable?
You're comparing the IIS management command lets to bash. PowerShell the language is largely the same, the same as bash. A more apt comparison would be to apachectl and the apache config files, which have changed.
So you're saying that if you expend zero effort to find the answers to these questions then those questions will remain unanswered?
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.
PowerShell has "providers" that let you interact with things as if they were a file system, which is what is going on in your example. I agree that it's not a great way to expose IIS settings.
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.
With conventional Linux distributions it is tricky to do this in a clean and idempotent way while preserving the entirety of the existing server configuration. The best solution of which I am aware is Augeas, which supports multiple file formats, and tools of similar type that specialize in a single file format (e.g., jq).
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.
Basically you're modifying a string that consists of:
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.
I started off as a PowerShell fan, but my introductory experience has been pretty poor. A little while back, I tried testing the output of a sorting algorithm with PowerShell. I wrote a line of bash to check my results:
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.
Yeah, actually. Though, I'd still include the cast to int, because I need to sort numerically, not lexicographically.
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.
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.
"I think many of the misconceptions I see on HN about PowerShell (and much of the Windows hate in general, actually) are because the typical use case on HN is quite a bit different than that of an internal IT department of a non-tech company, which is more Microsoft’s focus."
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.
Much of the time that PowerShell is mentioned here is in the context of a discussion about how nun-punchingly awful the Unix shell is, and what could possibly replace it. I have never used PowerShell, so I have nothing to add to those discussions, but the fish-out-of-water nature of much of the commentary about it, particularly the negative commentary, is because of this.
Sadly for those of us who detest the shell, nobody seems to have a good replacement at hand.
Much of the time that PowerShell is mentioned here is in the context of a discussion about how nun-punchingly awful the Unix shell is, and what could possibly replace it.
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.
I have not used powershell so I can't vouch for it. It is mainly because I couldn't find simple tutorials regarding them. Unix shell on the other hand is dead simple to use. However I get all icky if I have to use them on scripts. The outputs are always raw and never structured so it feels like a hackjob everytime. It also leads way to a different kind of vulnerabilities from incorrect parsing of outputs.
I think this is the part where powershell from what I heard comes off as superior. The output is structured and you can work straight with the results.
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.
The real "gotcha" for Powershell, for me, is the huge differences between versions. As the author mentions, v3 is much better than v1. The original version is pretty bad. A lot of parsing cmdlets don't work right. And a lot of the really useful ones aren't included, which also blocks some of the cool cmdlets you can download and install.
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.
Powershell definitely has its quirks, and unfortunately one of its best features - powerful remote administration - is also painful to configure and troubleshoot and is often unreliable and slow.
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.
I started reading this article not knowing anything about powershell, and finished horrified by the issues he tried to dispel in it. No remoting, no scripting? Are they serious?
You didn't read deep enough. Remoting and Scripting are <em>off by default</em> but available. Remoting is not great, but getting better soon (as in now-ish) with SSH support getting baked into PowerShell. (Yeah, that SSH, OpenSSH.) Scripting IS great, you just have to turn it on. (It's off by default because Microsoft didn't want it to be a virus vector for your Grandfather's machine who doesn't need shell scripting and likes to click on every attachment he sees in his email.)
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:
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.)
Powershell data is not just plain-text, it's all objects. On *nix when you run "ls -l" you get text. On powershell when you run "gci" you get objects. But the objects are nicely formatted automatically for you when they hit stdout so it ends up looking the same.
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.
And yet scripts for them are still written in a bash-like language for backwards compatibility reasons, which is really a shame in my opinion, because it is not a particularly convenient family of languages.
zsh and fish are mostly interactive shells, are they not? How does your claim of them being ahead in "tab completion and other general niceties" contradict ossreality's claim of PowerShell being superior in "text and object manipulation"?
Some of us do, but we've given up trying to expose HN to the shell. The anti-Microsoft culture that built up in the late 1990s and early 2000s has too much inertia on HN to overcome by occasional articles.
Keep in mind that much of what seemingly makes Powershell so great on Windows is inapplicable in a Unix shell environment. So there's still some juvenile "M$ hyuck hycuk" nonsense, but there's also some pretty spot-on discussion of the difficulty of trying to move tools between very different systems.
As your emphasizing comment embodies, that culture is still strong, and seems incorrigible. Microsoft are The Unredeemable. Even their current era of open sourcing isn't enough to wash away the sins of the past executives.
On a more topical note, one of the limitations of Powershell is it can only do basic math and (obviously) basic Algebra. To extend this, you can invoke .NET from the command line. Try these:
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.