You can use
sh -c and
exec to get the command's PID even before it runs.
myCommand, so that its PID is printed before it begins to run, you can use:
sh -c 'echo $$; exec myCommand'
How it works:
This starts a new shell, prints the PID of that shell, and then uses the
exec builtin to replace the shell with your command, ensuring it has the same PID. When your shell runs a command with the
exec builtin, your shell is actually becoming that command, rather than the more common behavior of forking a new copy of itself, which has its own separate PID and which then becomes the command.
I find this to be much simpler than alternatives involving asynchronous execution (with
&), job control, or searching with
ps. Those approaches are fine, but unless you have a specific reason to use them--for example, perhaps the command is already running, in which case searching for its PID or using job control would make sense--I suggest considering this way first. (And I would certainly not consider writing a complex script or other program to achieve this).
This answer includes an example of this technique.
Parts of that command could occasionally be omitted, but not usually.
Even if the shell you're using is a Bourne-style and thus supports the
exec builtin with these semantics, you generally shouldn't try to avoid using
sh -c (or equivalent) to create a new, separate shell process for this purpose, because:
- Once the shell has become
myCommand, there's no shell waiting to run subsequent commands.
sh -c 'echo $$; exec myCommand; foo would not be able to attempt to run
foo after replacing itself with
myCommand. Unless you're writing a script that runs this as its last command, you can't just use
echo $$; exec myCommand in a shell where you are running other commands.
- You cannot use a subshell for this.
(echo $$; exec myCommand) may be syntactically nicer than
sh -c 'echo $$; exec myCommand', but when you run
), it gives the PID of the parent shell, not of the subshell itself. But it is the subshell's PID that will be the PID of the new command. Some shells provide their own non-portable mechanisms for finding the subshell's PID, which you could use for this. In particular, in Bash 4,
(echo $BASHPID; exec myCommand) does work.
Finally, note that some shells will perform an optimization where they run a command as if by
exec (i.e., they forgo forking first) when it is known that the shell will not need to do anything afterward. Some shells try to do this anytime it is the last command to be run, while others will only do it when there are no other commands before or after the command, and others will not do it at all. The effect is that if your forget to write
exec and just use
sh -c 'echo $$; myCommand' then it will sometimes give you the right PID on some systems with some shells. I recommend against ever relying on such behavior, and instead always including
exec when that's what you need.