341

I want to have a shell script like this:

my-app &
echo $my-app-pid

But I do not know how the get the pid of the just executed command.

I know I can just use the jobs -p my-app command to grep the pid. But if I want to execute the shell multiple times, this method will not work. Because the jobspec is ambiguous.

Jeff Schaller
  • 67,283
  • 35
  • 116
  • 255
David S.
  • 5,589

4 Answers4

448

The PID of the last executed command is in the $! shell variable:

my-app &
echo $!
brandizzi
  • 2,864
  • 3
  • 22
  • 29
enzotib
  • 51,661
  • 1
    It is printing pid as for eg. [1] 893 . I want only number. – user3153014 Sep 04 '14 at 11:47
  • 51
    It should be noted that this stands for programs started in the background. If no background processes have been started the parameter is not set. – ramrunner Nov 17 '14 at 21:52
  • 7
    Another worthy solution is suggested in (a comment to an answer to) How to get pid of just started process: oh, and the "oneliner": /bin/sh -c 'echo $$>/tmp/my.pid && exec program args' & – sysfault Nov 24 '10 at 14:28 – imz -- Ivan Zakharyaschev Jun 02 '15 at 14:11
  • 17
    @user3153014 String s like "[2] 2625" are printed by shell after starting background task. This is not related to output of echo $! – Petr Gladkikh Jul 26 '15 at 05:21
  • I usually use such code in a script when I need to wait until the process ends. my-app & myVar=$! ; fg. fg brings the process to foreground again. I can then print echo $myVar later and I'm pretty sure that the my-app has already finished. – Vrata Blazek Mar 04 '19 at 17:17
  • If you are using that inside su {user} -c {command} as command, be sure to escape the $! (use \$!). See https://unix.stackexchange.com/questions/147916/getting-the-process-id-out-of-command-launched-with-su-c – Michele Piccolini Feb 28 '20 at 12:42
  • @VrataBlazek fg: no job control – Michael Apr 16 '20 at 00:09
  • @imz--IvanZakharyaschev Why is it necessary to pipe the PID to a file? If I try to wrap the shell call with $() it hangs at that point... why can't I get it into a shell variable directly? When I try to pipe it to a file I have another problem - now the PID of my command isn't the same as reported, whereas if I don't pipe it's the same! – Michael Apr 16 '20 at 00:25
  • @Michael Hiw do you want to get it into a shell variable directly? If you suggest a method, I could try to say whether it would work or not. As for $() wrapping, I can't try to explain the behavior without seeing the exact code. – imz -- Ivan Zakharyaschev Apr 18 '20 at 11:14
88

Get PID:

#!/bin/bash
my-app &
echo $!

Save PID in variable:

#!/bin/bash
my-app &
export APP_PID=$!

Save all instances PID in text file:

#!/bin/bash
my-app &
echo $! >>/tmp/my-app.pid

Save output, errors and PID in separated files:

#!/bin/bash
my-app >/tmp/my-app.log 2>/tmp/my-app.error.log &
echo $! >>/tmp/my-app.pid

echo "my-app PID's: $(cat /tmp/my-app.pid)"
  • 3
    The question didn't ask about redirection, then your answer is the mostly the same as the accepted one except that if an instance of my-app finishes, and perhaps even worse its PID gets reused later, you'll have bad information in your file. I don't think this answer adds much of value to the existing accepted answer really – Eric Renouf Jan 22 '16 at 15:12
  • 1
    @EricRenouf post updated! – Eduardo Cuomo Jan 22 '16 at 15:42
  • another derivative that might be useful. This gets the PID and at the same time treats it as a (mostly) foreground process: sleep 4 | grep INVALID & export MY_PID=$!; fg; echo $MY_PID returned with $? ` – mlathe Apr 26 '18 at 21:53
  • isnt APP=main & a way to grab PID? – MrMesees Aug 30 '18 at 07:54
3

Try something like

pidof my_app >> /tmp/my_app.pid
  • 2
    external command, and slow, if system can give PID directly why searching through all processes to find just that? and also, can't be certain you'll get correct value – papo Jan 02 '19 at 08:13
-5

Try something like this:

 ps ef | grep "[m]y-app" | awk '{print $2}'

Placing the first letter of your process between [ ] makes sure you do not get the grep process in your list. If needed you can also add a grep on your username.

Goez
  • 1,588
  • 11
    That's very fragile at best and doesn't work if my-app is executed more than once - davidshen84 specifically worries about that cas. – Mat Jan 30 '12 at 12:10
  • 4
    If you even go this route, you should use pgrep instead. – Willem Jan 19 '15 at 12:41