Search code examples
bashjobs

Convert job control number (%1) to pid so that I can kill sudo'ed background job


I often end up in this situation:

$ sudo something &
[1] 21838
$# Oh, shoot, it's hung, and assume the pid has scrolled off the screen
$ kill %1
-bash: kill: (21838) - Operation not permitted
$# Ah, rats.  I forgot I sudo'ed that.
$# Wishful thinking:
$ sudo kill %1
kill: cannot find process "%1"
$# Now I have to use ps and find the pid I want.
$ ps -elf | grep something
$ ps -elf | grep sleep
4 S root     21838  1928  0  80   0 - 53969 poll_s 11:28 pts/2    00:00:00 sudo sleep 100
4 S root     21840 21838  0  80   0 - 26974 hrtime 11:28 pts/2    00:00:00 sleep 100
$ sudo kill -9 21838
[1]+  Killed                  sudo something

I would really like to know if there is a better workflow for this. I'm really surprised there isn't a bash expression to turn %1 into a pid number.

Is there a bash trick for converting %1 to it's underlying pid? (Yes, I know I could have saved it at launch with $!)


Solution

  • To get the PID of a job, use: jobs -p N, where N is the job number:

    $ yes >/dev/null &
    [1] 2189
    $ jobs -p 1
    2189
    $ sudo kill $(jobs -p 1)
    [1]+  Terminated              yes > /dev/null
    

    Alternatively, and more strictly answering your question, you might find -x useful: it runs a command, replacing a job spec with the corresponding PID:

    $ yes >/dev/null &
    [1] 2458
    $ jobs -x sudo kill %1
    [1]+  Terminated              yes > /dev/null
    

    I find -p more intuitive, personally, but I get the appeal of -x.