3

I'm trying to get the PID of a piped data collection command in a BASH script so that I can kill the process once another (foreground) process has completed. I've got a timeout on the data collection command, but I don't know beforehand how long it should be; anywhere from a few minutes to several hours.

This question How to get the PID of a process in a pipeline was informative, but it didn't pan out. Probably because I'm using BASH 2.05 (on an embedded system).

Initial testing on the command line for the jobs -p command looked promising. In practice, I replace ksmon command below with a piped command (ksmon | {various filters} | gzip -c > file) so the "$!" BASH variable gives the last process in the pipe, not the ksmon program I'm trying to kill:

Test:/ $  ksmon > /dev/null & jobs -p
[1] 2016
2016
Test:/ $  ps | grep ksmon
 2016 root        660 S   ksmon
 2018 root        580 S   grep ksmon
Test:/ $  kill $(jobs -p)
[1]+  Terminated              ksmon >/dev/null
Test:/ $  ps | grep ksmon
 2021 root        580 S   grep ksmon
Test:/ $

Whoohoo! So I tried to put that in a script:

Test:/ $  cat > test.sh << EOF
> #!/bin/bash
> # That's bash 2.05
> ksmon > /dev/null & jobs -p
> EOF
Test:/ $  chmod 755 test.sh
Test:/ $  ./test.sh
Test:/ $
Test:/ $  # Nothing ...
Test:/ $  ps | grep ksmon
 2025 root        660 S   ksmon
 2027 root        580 S   grep ksmon
Test:/ $  jobs -p
Test:/ $

This is the version I'm trying to get it working with:

Test:/ $  bash --version
GNU bash, version 2.05.0(2)-release (arm-Artila-linux-gnu)
Copyright 2000 Free Software Foundation, Inc.

Oddly enough, the above script does works on an Ubuntu host.

What do I have to do to make jobs -p work in a BASH 2.05 script, or is there an alternative?

One thought was to just subtract a fixed number from the $! variable, but I'm not sure if that a good idea ...

EDIT: The reason I'd like to kill the first program in the pipe, is that all the programs that follow in the pipe, particularly gzip will do a nice job of closing their output streams.

Community
  • 1
  • 1
Jamie
  • 7,075
  • 12
  • 56
  • 86
  • possible duplicate of [Why can't I use job control in a bash script?](http://stackoverflow.com/questions/690266/why-cant-i-use-job-control-in-a-bash-script), although I have no idea if that works with bash 2. – Mat Aug 30 '12 at 16:46
  • @Mat Although the other question tells me "Why" it doesn't really suggest a best practice for "How". I thought my question was specific enough. – Jamie Aug 30 '12 at 17:11
  • The answer does tell you how. – Mat Aug 30 '12 at 17:37
  • @Mat I'm not trying to be obtuse, but I don't see where it suggests a *best practice*; it only suggests that you can make `jobs` work. I read that is common place to not use `jobs` in a script and that "There is no reason why anyone would want it in scripts as you can just keep the PIDs of your background processes and wait on or kill them" [lhunath] ... In my mind, the question remains "How?" and particular, for a piped command. – Jamie Aug 30 '12 at 18:20

1 Answers1

2

I suggest you to use $! to get PID of the last process in the pipe; then use lsof to sequentially determine previous processes in chain by open file descriptors from /proc.

Community
  • 1
  • 1
user1643723
  • 4,109
  • 1
  • 24
  • 48
  • +1 Love the answer, but unfortunately I can't use it as I don't have `lsof` running on my embedded system. – Jamie Sep 09 '12 at 02:26