Microsoft’s PowerShell Core Offers Cross-Platform Automation
thenewstack.io
thenewstack.io
But in practice, I find it both cumbersome and very, very slow.
For example:
marcel@vger[Downloads]time pwsh -c 'ls' >/dev/null
real 0m0.824s
user 0m0.636s
sys 0m0.213s
marcel@vger[Downloads]time sh -c 'ls' >/dev/null
real 0m0.011s
user 0m0.003s
sys 0m0.005s
marcel@vger[Downloads]
That's around a factor 80. Hmm. OK, startup costs, JITs hard time, yadda yadda.But it's not just that. For example I found a simple
dir -r
to be more around 50x slower than the equivalent ls -lR
And so on.I just don't find PowerShell fills a niche I need to fill, even though it seems to be really powerful and designed by smart people. I guess if I worked on Windows it would fill a niche since it has hooks into the system that are harder to reach in other non-MS languages.
It's not good for programming or scripting. There are so many good ideas in PowerShell but it's wrapped in a weird body.
At least, it doesn't insult you like Ansible tooling with the ^ YOU MADE A MISTAKE HERE BUT WE CAN'T BE CLEAR WHAT IT IS
It's such a shame powershell didn't come 2 years later, I feel like they'd have had no choice but to use C# instead of inventing a new language.
When you look at how admins get their job done, it starts in the interactive shell and then when the do things frequently, they put it into a simple script and when then need it to be more formal, they invest in making it production quality.
That is the flow that PowerShell was designed to support.
Jeffrey Snover [MSFT]
It's worth noting that all code in .NET is enclosed within a type (at a fundamental level .NET code is either contained within a value type or reference type, but knowing those names isn't important when you're starting out), so this doesn't limit you to creating/importing data types, you can use it to write inline C# functions too.
It's also interesting to note that the .NET Framework comes with its own .NET compiler, so you don't need to install any dev tools on Windows to code in C#, it's possible to do so with the tools that are available out of the box.
If you want to try out referencing C# code using Add-Type, the following article is a good introduction:
https://blogs.technet.microsoft.com/stefan_gossner/2010/05/0...
I can't pinpoint what I like so much about it either... It just draws me in well. It does devolve in readability when trying to squeeze out every drop of speed, though.
IPC is what I find to be the most challenging for me in PoSH, but I'm not sure if that's due to incompetence.
Jeffrey Snover [MSFT]
If these are flavors of ice cream, they're all pretty similar and taste good. Where is Powershell in this? It's certainly not vanilla or chocolate... it's more like pepperoni. It's like C# and Perl had a really ugly baby. Even simple things like using -eq and -ne for comparisons seems 40 years out of date.
That whatever space powershell fills on windows its not a niche .. not a niche at all
I agree with you, powershell is powerful and I guess benefit from being new .. it has amazing uniformity and amazing discover-ability
Anyway, I was saying, powershell fills automation on windows, it is THE automation tool on windows and has been for a while, there is hundreds of commands that you can you to manage and deploy and update almost anything important on windows
This is not a niche, not a niche at all .. it is as far from niche as i can think of
And now that it is being ported to other systems, it had the potential to be THE automation tool for many organization that have mixed environments
So you see, when it was primarily windows, it was not a nice, again because automation on windows is not a niche .. now imagine it beyond even windows
Powershell is about automation, not scripting, and not just the command line ... it is really about automation
Instead of following steps, you automated with one script ..or possibly a small GUI app
I was simply saying that PowerShell doesn't serve a unique purpose in my environment that isn't better served by other languages or shells. "Niche" was short-hand for, "This language is particularly well-suited for this task or set of tasks", and I wasn't (intentionally) saying anything about its popularity.
All programming languages have a niche where they are strong. It is not a way of saying, "This language is obscure or not used a lot." It's a way of saying, "For the things I do, I can rule it out, because I don't need to do the things this language does better than others." From what I can tell, scripting (or, "automating", if you prefer that term) Windows is PowerShell's niche. I don't need to script Windows, so I don't need PowerShell.
In short: Saying PowerShell doesn't fill a niche I need to fill is not an insult to PowerShell or a statement about how popular it is. It's merely saying I don't find it suits my needs in my environment (which contains no Windows servers).
That's where powershell failed abysmally.
PowerShell is useful on Windows because it does something that could not be done easily or at all before, that being automation without using GUI's. It does this by providing hooks into the Windows infrastructure to change settings and perform tasks without fragile registry edits and GUI manipulation. But UNIX systems have no need for this by virtue of it's command-line first design. If MS was still using DOS and ini files the situation would be similar.
So what does PowerShell really offer in UNIX land? Configuring and automating nix systems is drastically different than doing the same on Windows systems, so having a common scripting language probably does not help much.
I guess a better question would be what does PowerShell offer in the way of "automation" that is so much superior to bash and *nix command line programs.
1- it runs on both unix and windows .. and hopefully more in the future
2- uniformity, all command have the same form, verb-noun
3- discover-ability, you dont need google to find the cmdlet, you can glob search the help system
4- support, there are cmdlets for many systems that bash will never, ever, ever, ever approach or support
5- GUI, you can create a GUI in powershell
More than that, it has the entire CLR at its disposal, including the C FFI.
Jeffrey Snover [MSFT]
They've fixed this in recent versions by shipping actual curl binaries, but it's a useful illustration of how just aliasing popular shell commands to their Powershell alternatives isn't necessarily helpful.
& notepad.exe
Which isn't complicated I agree but annoyed me.
Just typing "notepad" is enough to launch it. The problems with powershell and executables only really come in to play when argument passing, where some escaping is necessary.
If you want to execute the EXE stored in a variable or whatnot, then yes, you need `&`, which I think is borrowed from Perl. But otherwise, the rules in PowerShell are the same as a Unix shell: if it's in the PATH, just type the command name (with or without the .exe); otherwise, use the full path.
The SO answer isn't wrong. The EXE there has a space in the path. The answer uses a string literal for it and thus needs &. It could of course escape the spaces with ` instead; then it wouldn't need a string literal and thus not need &.
I've done almost nothing with PowerShell due to the brutal syntax, would love to use a nice language like C# or Python for the control structure (logic, looping, etc) and then just calling out to PowerShell when needing to execute a function. Seems like that should be a possibility, although passing data through may be problematic.
Personally, for quick interactive stuff, I just `ls` when I'm sitting on a non-Windows machine. My finger muscle memory just does `ls -al` and `rm -rfv` when I'm sitting on a Linux box.
But if I need to do some heavy sorting/filtering, I'd much rather save the minutes wrestling grep/awk/sed/xargs than save the minutes on execution (or the hours on having just done some operation based on some grep/awk/sed/xargs work that I didn't properly test).
A few examples of the absurd things I found along the way:
It is impossible to update windows remotely with powershell. The only API to windows update is apparently a COM interface that refuses to be called remotely. I found a hack on a forum where I have to create a scheduled task that runs as a local admin user and trigger that task remotely. This is farcical.
The equivalent of ssh is something called powershell remoting. Of course opening that interface is a significant security risk that need to be monitored. However windows events records all failed authentication attempts on powershell remoting as a local connection and therefore does not expose the IP of the attacker. So much for monitoring.
Very few basic functions have been implemented in powershell, half of my powershell script is actually made of traditional batch commands, with all sort of random behaviors (like nslookup makes the script fail), inconsistent API, etc. It feels like using Windows 10 where we are stuck with half of our settings in an old control panel and the other half in a new one, feels sort of half baked. In addition some powershell commands managed to be inferior to their batch equivalent. Setting a registry key is a prime example (and god knows it is a common task), it takes several commands in powershell for something that is done in one command with reg.exe.
Of course there is no way to run a ps1 with admin privileges directly from the windows shell [1]
etc.
[1] winaero has a hack to do that: https://winaero.com/blog/run-as-administrator-context-menu-f... But come on Microsoft, don't you use your own product?
>nslookup
[System.Net.Dns]::GetHostAddresses('google.com') | % ToString
>In addition some powershell commands managed to be inferior to their batch equivalent. Setting a registry key is a prime example. ... it takes several commands in powershell for something that is done in one command with reg.exe. sp 'HKLM:\path\to\key' name 'value'On the registry, your command will fail if HKLM:\path\to\key doesn't exist whereas reg.exe would create the key automatically
It does not "crash" a powershell script for any meaningful definition of "crash".
I know a lot of people love Powershell though.
However some things will always be slower, aince powershell does more for you than bash does. Compare productivity from not scraping to consider the tradeoffs.
I think a lot of the bizarreness comes from trying to be multiple things, an interactive shell and systems automation language. It is case-insensitive, with seemingly no consensus on what case to use for things. Kinda makes sense for a shell environment with a case-insensitive file system, but very odd when writing automation. It can be written to look like any modern C-like language; set variables, pass variables to functions, etc. But idiomatic PowerShell seems to be (at least in some circles) piping one function to the next in very long chains. Again, that makes sense in a shell, but becomes somewhat unreadable in an application.
Most of what I've seen PowerShell used for is automation, from small 1000 line scripts to seriously large applications with libraries and databases. And I can't help but think that Python would have been so much nicer, if only it was built-in to Windows. Python has libraries for working with the Win32 API and COM objects, there is even IronPython which runs on the CRL and can integrate with .NET.
I don't think anyone was asking for an interactive shell and a serious programming language to be combined, and it would have been nice if they were separate. Instead they have an awful terminal console, an oddly verbose shell language, and a slow case-insensitive programming language.
There are naming conventions in PowerShell, but you don't need to know about them when you start out. For example, it's common practice to use camel case for variable names, such as $myVariableName.
> "But idiomatic PowerShell seems to be (at least in some circles) piping one function to the next in very long chains."
For the code I've seen and written, it's rare to see pipes longer than 4 commands long. If you get any longer than that, it's easy to store the output object in a variable and continue to work with this variable as a shorthand.
Is it ForEach, Foreach, foreach, or ForEach-Object? Official documentation[1][2][3][4][5] has all four variations. Same for True/False, While, Write-Output, etc. Everything is case-insensitive and the docs can't decide which to use. Again, it kind of makes sense for a shell language when your users are used to case-insensitivity, but I much prefer stricter consistency in programming languages.
[1] https://docs.microsoft.com/en-us/powershell/module/microsoft...
[2] https://docs.microsoft.com/en-us/powershell/module/psworkflo...
[3] https://docs.microsoft.com/en-us/previous-versions/windows/i...
[4] https://technet.microsoft.com/en-us/library/hh551144.aspx
[5] https://docs.microsoft.com/en-us/powershell/module/microsoft...
https://blogs.technet.microsoft.com/heyscriptingguy/2014/07/...
Going back to the naming conventions, the conventional way to write ForEach is in PascalCase. The variations slip into code as it's also an alias, and aliases tend to be in all lower case, and also because naming convention guidelines are just suggestions, not something that is strongly enforced (Foreach does seem to be commonly used, even if it's not necessarily in the standard styles).
Generally speaking, PowerShell coding style is similar to .NET coding style. You can read a discussion about it here:
https://github.com/PoshCode/PowerShellPracticeAndStyle/issue...
By the way, I respect your right to use whatever language you like best, I'm just clarifying that whilst PowerShell may not have it's "PEP-8" or gofmt, there are still conventions that PowerShell coders follow.
The terminal is absolutely horrible. If you are going to use powershell, try ConEmu. I also agree with you on the language drawbacks, but it's object-oriented nature makes up for it in my opinion. Whereas on linux/unix you are generally passing and processing text to and fro, the ability to deal with objects can make things a bit easier and more robust.
But considering that the windows world had to live with cmd/ms-dos forever, anything else seems like a god send.
Edit:
As an example where they did object-based scripting better, I'd look to F#, which also is a vastly better language. But it doesn't have good on-the-fly capabilities (you have to set up a project each time and need VS), and it doesn't come built in.
<rant>
> [...] the ability to deal with objects can make things a bit easier and more robust.
There are drawbacks to that too, though. As a heavily object-based scripting language, PS would depend even more on tooling than scripting languages do anyway. But that in turn means that the tooling we get just isn't good enough. Windows is notorious for its bad CLI windows, which hasn't changed much even with Win10. Discovering objects in PS is a usability nightmare. The little tab completion there is might be fine for one-off commands, but for anything interesting, it'll fall flat on its face.
If you have heavily state-dependent task, ISE contains more friction than value. Until today, I haven't found a simple and fast way to wipe the shell window clean, for example. If you still have things like sockets lying around (which means you'll have to restart the process for a clean state, it seems you're SOL).
Which brings me to
> If you are going to use powershell, try ConEmu.
I'd love to. I can't. In many business environments where you're not in control, "just installing independent tool X" is not an option. Yes, organizational BS is a separate problem, but you're not getting anything done fighting it. And honestly: It's about effing time MS distributes actually usable tools with their OS. I really don't get why that's the particular thing they fail so gloriously at.
The same problem extends to all sort of things. For example: Why the hell aren't the Sysinternals tools built-in already? It's been what? A decade? And there still is no decent Task manager in Windows? Gimme a break!
</rant>
Edit: Added a quote for clarity
Please don't link to articles from The New Stack. Their articles are often nothing more than warmed over press releases...
It's too bad that the focus wasn't put on creating an amazing .net interpreter for the commandline.
git add --all && git commend
(commend being an alias for "commit --amend --no-edit")
or
npm install && npm prune && npm run watch
This is the main reason I use git-bash as my primary terminal whenever I'm working on Windows.
There are some community tools to fake it a little better (Get-ExitBoolean).
Also, a big GitHub issue tracking it: https://github.com/PowerShell/PowerShell/issues/3241
I would say it's a little more than semantics. Consider
cd /some/dir/with/a/typo && some_destructive_cmd .
vs the semi-colon equivalent.I agree though, a good short-circuiting Boolean operator would be nice.
You're welcome.
A general purpose programming language where you write statement and it stays there and gets executed million times is very different model than shell language where you write statement, throw it away and move on with next. Combining both is creating Frankenstein that’s good at neither. It’s just quite funny that PowerShell syntax doesn’t allow == but does need curlies. Who in the world would have thought of that?
Also the view that everything in shell should output structured data is plain wrong. Shell should output human readable formats. always. It’s tool’s job to do proper parsing and deal with related complexity. The convenience should always be afforded to humans, not tools. Even if one changes all built-in commands to comply this, vast majority of programs won’t.
So lot of above leads to Frankenstein-ish design that looks like awkward hodge pudge of bandaids. While cross platform is good, MSFT needs to start brand new effort, leave PowerShell behind and take command line to next generation with right first principles.
Bash ports on Windows can be messy especially if it involves non-Latin codepages, especially when it involves language like Japanese, which frontend is still not migrated fully into UTF-8. (Also WSL handles it more gracefully.)
I am program in C# a lot, so extensibility via CmdLet is also interesting. (Although, I haven't explored this much, yet...)
I can't comment on the other options you listed, but I would agree that PowerShell has good features for parsing arguments (if you use advanced cmdlets, which only require one extra line to enable on basic cmdlet code, for [CmdletBinding()] ). Aside from built-in attributes for enabling common argument checks (like checking for nulls), you can completely customise parameter validation using ValidateScript, which allows you to set up a script that must evaluate as true in order for an argument to be valid. I'd be interested to find out if any Unix command line scripting language offers something similar.
Bash.
Bourne shell is a clumsy, ugly, footgun-laden automation language and the toolset uses text formatting and parsing in its piping io. The whole thing could really stand to be rethought.
Not to mention the way it reports errors to the user is incredibly verbose. However, it seems very par for the course for a strong Microsoft tool. If you are able to get in the correct headspace, it's magical. I'm just sad I have to sell my soul to the cult to use it
I find this an odd assertion since powershell lets you tab-complete cmdlets and argument options and has Get-Member.
Get-Help, Get-Command
Everything from there on is discoverable through what you learn from those 2 cmdletsThere are points of criticism I could level at PowerShell, but discoverability is not one of them.
If you want to explore PowerShell without using any formal tutorials, I'd recommend five commands:
* Get-Verb
* Get-Alias
* Get-Help
* Get-Module
* Get-Command
Get-Verb is useful as it gives you clues about the PowerShell naming convention. Aside from aliases, the vast majority of the commands in PowerShell start with one of the verbs listed by Get-Verb. You can use tab completion to cycle through all currently available commands, e.g. type "Get" (without quotes) then keep pressing the tab key to see the available commands (that are currently loaded).
Get-Alias shows you the command aliases that have been setup for use in your PowerShell session. The reason I recommend it here is twofold:
1. The aliases provided by default are assigned to the most commonly used commands, so Get-Alias can give you a shortlist of commands that are good to explore first.
2. If you have prior experience with the Windows command line or the Linux terminal, Get-Alias will give you clues about what different commands do. For example, dir and ls are both aliases for Get-ChildItem.
Get-Help gives you access to command documentation. One hint I'd give about help in PowerShell is if you need to update the PowerShell help available on your machine, run Update-Help from an elevated command prompt (e.g. on Windows, run PowerShell as an administrator before running Update-Help). If you haven't got local admin permissions, Get-Help is still useful, and will point you in the direction of relevant online documentation if it can't find the help documentation locally.
Get-Module lists the commands by the module they're found in. By default it only shows the modules that are currently loaded, but with Get-Module -ListAvailable you can see all the modules you can choose from. In later versions of PowerShell running a command automatically loads the module it's in (in earlier versions you have to use Load-Module beforehand if the module wasn't already loaded). Note that the -ListAvailable option could've been discovered using Get-Help (e.g. Get-Help Get-Module).
Get-Command allows you to explore the metadata about a command. You're better off reading up on what it can do (Get-Help Get-Command would be a decent start), but to give you one example of why you might find it useful when starting out is that it lets you explore the parameter sets associated with a command. Parameter sets are ways of allowing different groups of parameters to be used with a single command. For example, if you're testing the network connection of computers on a work network, you may choose to reference the computer by IP address, or you may reference the computer by computer name. In this case, parameter sets are a way of making one of those parameters mandatory. Note that commands have a default parameter set, and if you try running a command with mandatory parameters in the default parameter set without passing them in, it will request the minimum information the command requires to function. With all that said, I'd leave Get-Command alone until you're more familiar with the basic operations in PowerShell.
As a final piece of advice, if you're on Windows I would recommend using PowerShell ISE when you start out. It might not look as pretty as VS Code (which also has decent PowerShell support), but it's good at exposing what you need to write effective PowerShell scripts. I use it regularly at work, even for simple tasks that the standalone PowerShell command line would work for. Also worth noting that it ships with Windows, simply search for PowerShell ISE using the Windows menu search.
How so? Remember that the "text" convention was not chosen haphazardly, but rather very consciously.
> bash
Nope. Show me the script that gets a list of mounted filesytems for locally attached disks and flags any that are larger than 20G and are more than 90% full.
Since it is cross platform it will run the same on linux/bsd/os x and windows, right?
That's sort of cheating though. In that instance, Bash isn't really being cross platform, so much as Windows bent over backwards to re-implement lots of Linux underneath Bash, so Bash could treat Linux and Linux (on Windows) identically.
Or to restate that: If Linux apps get to claim they are 'cross-platform' because of WSL, then Windows apps get to claim they are 'cross-platform' because you could run them in WINE.
https://en.wikipedia.org/wiki/HP-UX
I used HP-UX for a while; it was good. In fact I first wrote this Unix utility [1] (and later an IBM developerWorks article about it) on an HP-UX system, for a big manufacturing client. HP-UX was pretty stable and had a good patch management system. Had some good tools from HP on top of the OS, such as GlancePlus, Ignite-UX, Process Resource Manager, etc., and another high-end one called MC ServiceGuard.
https://en.wikipedia.org/wiki/Ultrix
https://en.wikipedia.org/wiki/Tru64_UNIX
Edit: Sorry, forgot to add the link I quoted above. Done now:
[1] https://jugad2.blogspot.in/2014/09/my-ibm-developerworks-art...
It's a tutorial on the topic: Developing a Linux command-line utility (in C).
Also, I only used it on HP business servers - the PA-RISC series, not on their workstations. Don't know, but there could be some differences in the HP-UX versions between the servers and workstations, the latter which, IIRC, were based on the acquisition of Apollo (but don't know much about that).
I still build a cross-compiler toolchain for HP-UX PA-RISC 2.0 long-mode (64-bit address mode).
My rule of thumb is that if a bash script is > 10-20 lines or needs a function, then I rewrite it in Python. It's simply way more readable.
The main downside to using Python is that if you're running on a minimal system, in a container, or on Windows, Python is a large install.
But I don't see how porting Powershell to _nix solves that issue. _nix systems are more common in most web-centric companies nowadays. If you're a company that uses both you're better off installing Python on your Windows boxes IMO since they probably have bigger disks anyways to handle the large OS.
I'd say the main reason to install PowerShell on Linux is if you want to use the tools for managing Azure. Aside from that, there are other scripting languages that are have a more mature library ecosystems on Linux.
I can't help but thinking the praise Powershell got is just because Windows people have suddenly realised there's more to life than point and click. Well no shit, guys. This is why we've been using Linux this whole time.