Unlike shell scripts written for POSIX-compatible shells such as bash
, PowerShell scripts (*.ps1
files) run in-process.
Therefore, all invocations of a given script (more generallly, all scripts) in a given PowerShell session (process) report the same value in the automatic $PID
variable, namely the current process' ID.
To run a .ps1 script
out-of-process, you'll have to call the PowerShell CLI (powershell.exe
for Windows PowerShell, pwsh
for PowerShell (Core) 7+), which creates a PowerShell child process; e.g.:
# Note: Passing a command via { ... } only works from *inside* PowerShell.
pwsh -NoProfile { ./some.ps1 }
# With arguments
pwsh -NoProfile { ./some.ps1 @args } -args foo, $PID
However:
PowerShell's startup cost is significant, so you pay a noticeable performance penalty.
Behind the scenes, XML-based serialization and deserialization is involved for communicating data types, and the type fidelity has limits, just as in PowerShell remoting. That is, if complex objects are passed to or received from the child process, you may only get emulations of these objects - see this answer for background information.
Note that if you're calling from outside PowerShell, use the CLI's -File
parameter to invoke a script (in which case only text in- and output is supported); e.g.:
pwsh -NoProfile -File ./some.ps1 foo $PID
For a comprehensive description of the PowerShell CLI, see this answer.
I think that $$ [in bash
] and $PID [in PowerShell] don't work in the same way.
They do: both report the current process' ID; the difference in observed behavior is solely due to the difference between execution in a child process vs. in-process execution.
As an aside: PowerShell too has an automatic $$
variable, but it serves an entirely different purpose than in bash
(where it is the equivalent of PowerShell's $PID
): It contains the last token of the most recently submitted command line and is intended for interactive editing convenience (e.g., after submitting Get-ChildItem someReallyLongDirectoryName
, you can refer to someReallyLongDirectoryName
with $$
at the next prompt).
As such, it is the equivalent of bash
's built-in $_
variable.