Select-String
is probably not the hammer you wanna use for this particular nail (see below) :-)
Get-Process
has a -Name
parameter that takes a wildcard:
Get-Process -Name nginx
# or
Get-Process -Name *nginx*
To kill the process, either call Kill()
directly on the object:
$nginxProcess = Get-Process nginx |Select -First 1
$nginxProcess.Kill()
... or simply pipe the process instances to Stop-Process
:
Get-Process -Name nginx |Stop-Process
As you can see, we never actually need to locate or pass the process id - the Process
object already has that information embedded in it, and the *-Process
cmdlets are designed to work in concert - PowerShell is all about command composition, and this is an example of it.
That being said, Stop-Process
is also perfectly capable of killing processes by name alone:
Stop-Process -Name nginx
How did I know the *-Process
cmdlets had a -Name
parameter?
Apart from reading the help files and documentation (I get it, I don't want to read anything either unless I absolutely have to ;-)), a quick way to learn about the parameters exposed by a cmdlet is by running Get-Command <commandName> -Syntax
:
PS ~> Get-Command Stop-Process -Syntax
Stop-Process [-Id] <int[]> [-PassThru] [-Force] [-WhatIf] [-Confirm] [<CommonParameters>]
Stop-Process -Name <string[]> [-PassThru] [-Force] [-WhatIf] [-Confirm] [<CommonParameters>]
Stop-Process [-InputObject] <Process[]> [-PassThru] [-Force] [-WhatIf] [-Confirm] [<CommonParameters>]
The output shows us 3 distinct "parameter sets" (combinations of parameter input accepted by the command), and the required and optional arguments we can pass to it.
What's wrong with Select-String
?
The Select-String
cmdlet is the PowerShell cognate to grep
- it takes some input, and performs regular expression matching against it based on whatever pattern you give it.
But grep
is only useful when you're operating on strings - and as you've already found, Get-Process
returns structured .NET objects, not flat strings.
Instead, the PowerShell-idiomatic approach is to filter the data, using the Where-Object
cmdlet:
Get-Process | Where-Object Name -like '*nginx*'
Here, we instruct Where-Object
to only let through object that have a Name
property, the value of which must satisfy the wildcard pattern *nginx*
.
Where-Object
also supports arbitrary filter expressions, by accepting a scriptblock - PowerShell will assign the current pipeline object being evaluated to $_
(and $PSItem
):
Get-Process | Where-Object { $_.Name -like '*nginx*' }
... which you can extend to whatever degree you need:
# Only let them through if a specific user is executing
Get-Process | Where-Object { $_.Name -like '*nginx*' -and $env:USERNAME -ne 'Quarkly'}