0

So, let us say I am running a subshell with a background process as follows:

(command &)

I want to be able to store the PID of this subprocess into a bash variable so that I can kill the subshell and its running background process later. How can I do so?

Note: This may very well be a duplicate, but I am struggling to implement many of the other answers. So, even if this question is marked as a duplicate, I would appreciate it if someone could still provide an answer regardless.

Some things I have tried:

pid="$((echo "$BASHPID" && command &))"
pid2="$((command & echo "$BASHPID"))"
pid3=(echo "$BASHPID" && command &)
pid4=(command & echo "$BASHPID")
Gigi Bayte 2
  • 838
  • 1
  • 8
  • 20
  • is there a reason you're using `(command &)` instead of `command &`? I'm not suggesting your approach is right or wrong, just curious as to the reason why you picked this approach? – markp-fuso Feb 26 '23 at 21:57
  • 1
    @markp-fuso I have added some attempts as recommended. The reason I am using a subshell in the first place is to suppress background-process related output (e.g. `[1] ` and `[1]+ Terminated: 15 `) – Gigi Bayte 2 Feb 26 '23 at 22:01
  • `in the first place is to suppress background-process related output` ? There is no background output _in scripts_. Maybe just `set +m`? – KamilCuk Feb 26 '23 at 22:02
  • 2
    @KamilCuk I am a bit confused what you mean. In this case, the aforementioned background-process output occurs if I do not use a subshell. To clarify, this is for a function that I put in my `.bashrc`. – Gigi Bayte 2 Feb 26 '23 at 22:04
  • You are confusing command substitution (`$(...)`) with arithmetic expressions (`$((...))`). – chepner Feb 26 '23 at 22:16
  • @chepner Ah, I forgot about that syntax. I was foolishly trying to create a subshell in a command substitution expression. – Gigi Bayte 2 Feb 26 '23 at 23:41

3 Answers3

2

One idea:

$ read -r x < <(sleep 240 & echo $!)       # alternative: replace $! with $BASHPID
                ^^^^^^^^^        ^^    
$ echo "$x"
1887
^^^^
$ ps -aef|egrep sleep
myuser    1887       1 pty1     16:00:17 /usr/bin/sleep
          ^^^^                                    ^^^^^
$ pgrep -a sleep
1887 sleep 240
^^^^ ^^^^^^^^^
markp-fuso
  • 28,790
  • 4
  • 16
  • 36
  • 2
    But that will hide the output. You could do `exec 3>&1; read pid < <(sleep 240 >&3 & echo $!)` so that the background command can still write to stdout. – KamilCuk Feb 26 '23 at 22:20
1

There are many ways of https://en.wikipedia.org/wiki/Inter-process_communication . For example use a fifo:

pidfile=$(mktemp -n)
mkfifo "$pidfile"
(command & echo $! > "$pidfile")
read pid < "$pidfile"
rm "$pidfile"
KamilCuk
  • 120,984
  • 8
  • 59
  • 111
0

Perhaps the shortest way of achieving it is using coproc:

#! /bin/bash

coproc ./mycommand
pid=$COPROC_PID
Diego Torres Milano
  • 65,697
  • 9
  • 111
  • 134