PID of the background function, F, in commands invoked in subshells inside F
Clash Royale CLAN TAG#URR8PPP
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty margin-bottom:0;
up vote
0
down vote
favorite
When foo
is run in the background, the BASHPID
of foo
(bashpid_of_foo
) is not available inside the bodies bar_1
to bar_n
via $BASHPID
, since they get invoked via the Command Substitution feature of bash
:
function foo()
local bashpid_of_foo=$BASHPID
local output
# desired to be shared by all Command Substitutions
# in the body of this function.
local log=/path/to/log.$BASHPID
... >> $log
output=$(bar_1 ...)
...
output=$(bar_n ...)
function bar_1()
# log only specific (and NOT all) messages
# to the shared log file of the invoking thread.
... >> /path/to/log.$BASHPID
foo &
foo &
Question: Is there an elegant way around the above limitation, without having to pass bashpid_of_foo
via adhoc environment variables or external disk files?
By elegant, I mean, being able to keep the interfaces and bodies of bar_*
functions clean by relying only on bash-provided features. (Eg BASHPID
is a bash
feature.)
If I try to override the value of BASHPID
, like this,
out_1=$(BASHPID=$BASHPID bar_1 ...)
... it (rightly) complains about BASHPID
being a readonly variable.
EDIT: (1) Added the definition of bar_1
above. (2) Added the 2nd call to foo
in the background. Each foo
invocation needs to maintain its own log file, since writing to a common file could result in garbled contents.
NOTE: Whatever logging happens in the runtime context of foo
, I want it to go into the foo
-specific log file, /path/to/log.$BASHPID
WITHOUT passing around the name of this log file or even the PID of foo
. foo
can have multiple instances running in the background.
bash process background-process
 |Â
show 1 more comment
up vote
0
down vote
favorite
When foo
is run in the background, the BASHPID
of foo
(bashpid_of_foo
) is not available inside the bodies bar_1
to bar_n
via $BASHPID
, since they get invoked via the Command Substitution feature of bash
:
function foo()
local bashpid_of_foo=$BASHPID
local output
# desired to be shared by all Command Substitutions
# in the body of this function.
local log=/path/to/log.$BASHPID
... >> $log
output=$(bar_1 ...)
...
output=$(bar_n ...)
function bar_1()
# log only specific (and NOT all) messages
# to the shared log file of the invoking thread.
... >> /path/to/log.$BASHPID
foo &
foo &
Question: Is there an elegant way around the above limitation, without having to pass bashpid_of_foo
via adhoc environment variables or external disk files?
By elegant, I mean, being able to keep the interfaces and bodies of bar_*
functions clean by relying only on bash-provided features. (Eg BASHPID
is a bash
feature.)
If I try to override the value of BASHPID
, like this,
out_1=$(BASHPID=$BASHPID bar_1 ...)
... it (rightly) complains about BASHPID
being a readonly variable.
EDIT: (1) Added the definition of bar_1
above. (2) Added the 2nd call to foo
in the background. Each foo
invocation needs to maintain its own log file, since writing to a common file could result in garbled contents.
NOTE: Whatever logging happens in the runtime context of foo
, I want it to go into the foo
-specific log file, /path/to/log.$BASHPID
WITHOUT passing around the name of this log file or even the PID of foo
. foo
can have multiple instances running in the background.
bash process background-process
3
BASHPID
may be special, butbashpid_of_foo
is not. You should be able to use that in the command substitutions.
â Kusalananda
Jul 27 at 7:28
2
@Harry If you save$BASHPID
inbashpid
, then the only thing you have to do differently in your command substitutions is to not press shift when typingbashpid
.
â Kusalananda
Jul 27 at 8:02
2
These are the types of best practices or tricks you have to resort to @Harry as Kusalananda is saying by keeping complex software in Bash.
â slmâ¦
Jul 27 at 8:04
@Kusalananda "then the only thing you have to do differently in your command substitutions is to not press shift when typing bashpid" Lol that was astute! Ok, bro.
â Harry
Jul 27 at 8:34
My boss was pressuring me to write my script in Java (yuck!). This is a customer's server - it has Java andbash
, but no Perl, Python, Ruby, etc. I fought with him to let me do it inbash
since I'm mostly using/bin
and/usr/bin
commands - coding which in Perl, Python, and Ruby can be relatively more verbose thanbash
. And now I run into this dead-end - which I can surely workaround (like you suggested) but would've preferred not to (by relying some existing facility. Btw, I feel, this is a feature-flaw inbash
: Abash
function (and, not an external program) should be allowed +
â Harry
Jul 27 at 8:39
 |Â
show 1 more comment
up vote
0
down vote
favorite
up vote
0
down vote
favorite
When foo
is run in the background, the BASHPID
of foo
(bashpid_of_foo
) is not available inside the bodies bar_1
to bar_n
via $BASHPID
, since they get invoked via the Command Substitution feature of bash
:
function foo()
local bashpid_of_foo=$BASHPID
local output
# desired to be shared by all Command Substitutions
# in the body of this function.
local log=/path/to/log.$BASHPID
... >> $log
output=$(bar_1 ...)
...
output=$(bar_n ...)
function bar_1()
# log only specific (and NOT all) messages
# to the shared log file of the invoking thread.
... >> /path/to/log.$BASHPID
foo &
foo &
Question: Is there an elegant way around the above limitation, without having to pass bashpid_of_foo
via adhoc environment variables or external disk files?
By elegant, I mean, being able to keep the interfaces and bodies of bar_*
functions clean by relying only on bash-provided features. (Eg BASHPID
is a bash
feature.)
If I try to override the value of BASHPID
, like this,
out_1=$(BASHPID=$BASHPID bar_1 ...)
... it (rightly) complains about BASHPID
being a readonly variable.
EDIT: (1) Added the definition of bar_1
above. (2) Added the 2nd call to foo
in the background. Each foo
invocation needs to maintain its own log file, since writing to a common file could result in garbled contents.
NOTE: Whatever logging happens in the runtime context of foo
, I want it to go into the foo
-specific log file, /path/to/log.$BASHPID
WITHOUT passing around the name of this log file or even the PID of foo
. foo
can have multiple instances running in the background.
bash process background-process
When foo
is run in the background, the BASHPID
of foo
(bashpid_of_foo
) is not available inside the bodies bar_1
to bar_n
via $BASHPID
, since they get invoked via the Command Substitution feature of bash
:
function foo()
local bashpid_of_foo=$BASHPID
local output
# desired to be shared by all Command Substitutions
# in the body of this function.
local log=/path/to/log.$BASHPID
... >> $log
output=$(bar_1 ...)
...
output=$(bar_n ...)
function bar_1()
# log only specific (and NOT all) messages
# to the shared log file of the invoking thread.
... >> /path/to/log.$BASHPID
foo &
foo &
Question: Is there an elegant way around the above limitation, without having to pass bashpid_of_foo
via adhoc environment variables or external disk files?
By elegant, I mean, being able to keep the interfaces and bodies of bar_*
functions clean by relying only on bash-provided features. (Eg BASHPID
is a bash
feature.)
If I try to override the value of BASHPID
, like this,
out_1=$(BASHPID=$BASHPID bar_1 ...)
... it (rightly) complains about BASHPID
being a readonly variable.
EDIT: (1) Added the definition of bar_1
above. (2) Added the 2nd call to foo
in the background. Each foo
invocation needs to maintain its own log file, since writing to a common file could result in garbled contents.
NOTE: Whatever logging happens in the runtime context of foo
, I want it to go into the foo
-specific log file, /path/to/log.$BASHPID
WITHOUT passing around the name of this log file or even the PID of foo
. foo
can have multiple instances running in the background.
bash process background-process
edited Jul 27 at 7:54
asked Jul 27 at 6:57
Harry
3701313
3701313
3
BASHPID
may be special, butbashpid_of_foo
is not. You should be able to use that in the command substitutions.
â Kusalananda
Jul 27 at 7:28
2
@Harry If you save$BASHPID
inbashpid
, then the only thing you have to do differently in your command substitutions is to not press shift when typingbashpid
.
â Kusalananda
Jul 27 at 8:02
2
These are the types of best practices or tricks you have to resort to @Harry as Kusalananda is saying by keeping complex software in Bash.
â slmâ¦
Jul 27 at 8:04
@Kusalananda "then the only thing you have to do differently in your command substitutions is to not press shift when typing bashpid" Lol that was astute! Ok, bro.
â Harry
Jul 27 at 8:34
My boss was pressuring me to write my script in Java (yuck!). This is a customer's server - it has Java andbash
, but no Perl, Python, Ruby, etc. I fought with him to let me do it inbash
since I'm mostly using/bin
and/usr/bin
commands - coding which in Perl, Python, and Ruby can be relatively more verbose thanbash
. And now I run into this dead-end - which I can surely workaround (like you suggested) but would've preferred not to (by relying some existing facility. Btw, I feel, this is a feature-flaw inbash
: Abash
function (and, not an external program) should be allowed +
â Harry
Jul 27 at 8:39
 |Â
show 1 more comment
3
BASHPID
may be special, butbashpid_of_foo
is not. You should be able to use that in the command substitutions.
â Kusalananda
Jul 27 at 7:28
2
@Harry If you save$BASHPID
inbashpid
, then the only thing you have to do differently in your command substitutions is to not press shift when typingbashpid
.
â Kusalananda
Jul 27 at 8:02
2
These are the types of best practices or tricks you have to resort to @Harry as Kusalananda is saying by keeping complex software in Bash.
â slmâ¦
Jul 27 at 8:04
@Kusalananda "then the only thing you have to do differently in your command substitutions is to not press shift when typing bashpid" Lol that was astute! Ok, bro.
â Harry
Jul 27 at 8:34
My boss was pressuring me to write my script in Java (yuck!). This is a customer's server - it has Java andbash
, but no Perl, Python, Ruby, etc. I fought with him to let me do it inbash
since I'm mostly using/bin
and/usr/bin
commands - coding which in Perl, Python, and Ruby can be relatively more verbose thanbash
. And now I run into this dead-end - which I can surely workaround (like you suggested) but would've preferred not to (by relying some existing facility. Btw, I feel, this is a feature-flaw inbash
: Abash
function (and, not an external program) should be allowed +
â Harry
Jul 27 at 8:39
3
3
BASHPID
may be special, but bashpid_of_foo
is not. You should be able to use that in the command substitutions.â Kusalananda
Jul 27 at 7:28
BASHPID
may be special, but bashpid_of_foo
is not. You should be able to use that in the command substitutions.â Kusalananda
Jul 27 at 7:28
2
2
@Harry If you save
$BASHPID
in bashpid
, then the only thing you have to do differently in your command substitutions is to not press shift when typing bashpid
.â Kusalananda
Jul 27 at 8:02
@Harry If you save
$BASHPID
in bashpid
, then the only thing you have to do differently in your command substitutions is to not press shift when typing bashpid
.â Kusalananda
Jul 27 at 8:02
2
2
These are the types of best practices or tricks you have to resort to @Harry as Kusalananda is saying by keeping complex software in Bash.
â slmâ¦
Jul 27 at 8:04
These are the types of best practices or tricks you have to resort to @Harry as Kusalananda is saying by keeping complex software in Bash.
â slmâ¦
Jul 27 at 8:04
@Kusalananda "then the only thing you have to do differently in your command substitutions is to not press shift when typing bashpid" Lol that was astute! Ok, bro.
â Harry
Jul 27 at 8:34
@Kusalananda "then the only thing you have to do differently in your command substitutions is to not press shift when typing bashpid" Lol that was astute! Ok, bro.
â Harry
Jul 27 at 8:34
My boss was pressuring me to write my script in Java (yuck!). This is a customer's server - it has Java and
bash
, but no Perl, Python, Ruby, etc. I fought with him to let me do it in bash
since I'm mostly using /bin
and /usr/bin
commands - coding which in Perl, Python, and Ruby can be relatively more verbose than bash
. And now I run into this dead-end - which I can surely workaround (like you suggested) but would've preferred not to (by relying some existing facility. Btw, I feel, this is a feature-flaw in bash
: A bash
function (and, not an external program) should be allowed +â Harry
Jul 27 at 8:39
My boss was pressuring me to write my script in Java (yuck!). This is a customer's server - it has Java and
bash
, but no Perl, Python, Ruby, etc. I fought with him to let me do it in bash
since I'm mostly using /bin
and /usr/bin
commands - coding which in Perl, Python, and Ruby can be relatively more verbose than bash
. And now I run into this dead-end - which I can surely workaround (like you suggested) but would've preferred not to (by relying some existing facility. Btw, I feel, this is a feature-flaw in bash
: A bash
function (and, not an external program) should be allowed +â Harry
Jul 27 at 8:39
 |Â
show 1 more comment
2 Answers
2
active
oldest
votes
up vote
1
down vote
accepted
#!/bin/bash
bar ()
# bashpid is set in our environment from the calling function
printf 'bar BASHPID = %d, bar bashpid = %dn' "$BASHPID" "$bashpid"
# in your case, you would have...
local logfile="/some/path/to/log.$bashpid"
# etc.
foo ()
local bashpid="$BASHPID"
local message
local logfile="/some/path/to/log.$BASHPID"
message=$( bashpid="$bashpid" bar ); printf 'Message from bar: %sn' "$message"
message=$( bashpid="$bashpid" bar ); printf 'Message from bar: %sn' "$message"
message=$( bashpid="$bashpid" bar ); printf 'Message from bar: %sn' "$message"
message=$( bashpid="$bashpid" bar ); printf 'Message from bar: %sn' "$message"
foo &
foo &
foo &
wait
Example run:
$ bash script.sh
Message from bar: bar BASHPID = 71979, bar bashpid = 18461
Message from bar: bar BASHPID = 7420, bar bashpid = 71036
Message from bar: bar BASHPID = 6109, bar bashpid = 18461
Message from bar: bar BASHPID = 27868, bar bashpid = 71036
Message from bar: bar BASHPID = 44547, bar bashpid = 60086
Message from bar: bar BASHPID = 69310, bar bashpid = 71036
Message from bar: bar BASHPID = 37649, bar bashpid = 60086
Message from bar: bar BASHPID = 15999, bar bashpid = 71036
Message from bar: bar BASHPID = 81520, bar bashpid = 18461
Message from bar: bar BASHPID = 92568, bar bashpid = 60086
Message from bar: bar BASHPID = 72438, bar bashpid = 18461
Message from bar: bar BASHPID = 15094, bar bashpid = 60086
For each invocation of foo
in the main part of the script, four calls to bar
will be made and four lines of output will be produced. As you see, there is only three unique bashpid
numbers, each from one of the foo
invocations.
Another way of passing $bashpid
from foo
to bar
is obviously to pass it as a command line argument and to receive it with local bashpid="$1"
in bar
or something similar, but you say you don't want to do this.
Thebashpid
approach should work for me. But ifbashpid
is the local/dynamic scope offoo
, why are you passing it as an env var when callingbar
?
â Harry
Jul 29 at 4:46
1
@Harry It allows for the case wherebar
is a script or other application (not a function).
â Kusalananda
Jul 29 at 9:13
Then, can't we justexport
it from withinfoo
so that ALL calls to functions or programs/scripts from withinfoo
automatically get it, instead of I passing it explicitly every time?
â Harry
Jul 29 at 9:26
1
@Harry Yes, of course, if you wish to do it that way. However, that would also set it infoo
and in whatever environmentfoo
is executing in. In this case, you are runningfoo
as a background job, so it doesn't affect the otherfoo
s or the main script.
â Kusalananda
Jul 29 at 9:42
add a comment |Â
up vote
1
down vote
NOTE: In regards to your general questions around $BASHPID
, this is readonly and you cannot manipulate it. This is by design.
It's typically my general advice that when you get to the level of sophistication with Bash scripts like this, it's time to move it to Python, Ruby, whatever.
Your example
I guess I don't see what your issue is, this works for me:
$ cat subby.bash
#!/bin/bash
function foo()
local bashpid_of_foo=$BASHPID
local output=blipblop
echo "foo: $bashpid_of_foo"
echo "foo: $output"
out_1=$(echo $bashpid_of_foo)
out_n=$(echo $output)
echo "out_1: $out_1"
echo "out_n: $out_n"
foo &
$ ./subby.bash
foo: 4900
foo: blipblop
out_1: 4900
out_n: blipblop
Addition of export
If we change this around by making bar_1
into a shell script:
$ cat bar_1
#!/bin/bash
echo "from bar_1: $bashpid_of_foo"
And change your original script like this:
#!/bin/bash
function foo()
export bashpid_of_foo=$BASHPID
local output=blipblop
echo "foo: $bashpid_of_foo"
echo "foo: $output"
out_1=$(echo $bashpid_of_foo)
out_2=$(./bar_1)
out_n=$(echo $output)
echo "out_1: $out_1"
echo "out_2: $out_2"
echo "out_n: $out_n"
foo &
We can see that the $bashpid_of_foo
is getting exported properly to subshells:
$ ./subby.bash
foo: 5014
foo: blipblop
out_1: 5014
out_2: from bar_1: 5014
out_n: blipblop
We need to use an export
here and not just a local
because otherwise the environment variables will not get exported to any children. The subshells are child shells here.
$ help export
...
Marks each NAME for automatic export to the environment of subsequently
executed commands. If VALUE is supplied, assign VALUE before exporting.
add a comment |Â
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
1
down vote
accepted
#!/bin/bash
bar ()
# bashpid is set in our environment from the calling function
printf 'bar BASHPID = %d, bar bashpid = %dn' "$BASHPID" "$bashpid"
# in your case, you would have...
local logfile="/some/path/to/log.$bashpid"
# etc.
foo ()
local bashpid="$BASHPID"
local message
local logfile="/some/path/to/log.$BASHPID"
message=$( bashpid="$bashpid" bar ); printf 'Message from bar: %sn' "$message"
message=$( bashpid="$bashpid" bar ); printf 'Message from bar: %sn' "$message"
message=$( bashpid="$bashpid" bar ); printf 'Message from bar: %sn' "$message"
message=$( bashpid="$bashpid" bar ); printf 'Message from bar: %sn' "$message"
foo &
foo &
foo &
wait
Example run:
$ bash script.sh
Message from bar: bar BASHPID = 71979, bar bashpid = 18461
Message from bar: bar BASHPID = 7420, bar bashpid = 71036
Message from bar: bar BASHPID = 6109, bar bashpid = 18461
Message from bar: bar BASHPID = 27868, bar bashpid = 71036
Message from bar: bar BASHPID = 44547, bar bashpid = 60086
Message from bar: bar BASHPID = 69310, bar bashpid = 71036
Message from bar: bar BASHPID = 37649, bar bashpid = 60086
Message from bar: bar BASHPID = 15999, bar bashpid = 71036
Message from bar: bar BASHPID = 81520, bar bashpid = 18461
Message from bar: bar BASHPID = 92568, bar bashpid = 60086
Message from bar: bar BASHPID = 72438, bar bashpid = 18461
Message from bar: bar BASHPID = 15094, bar bashpid = 60086
For each invocation of foo
in the main part of the script, four calls to bar
will be made and four lines of output will be produced. As you see, there is only three unique bashpid
numbers, each from one of the foo
invocations.
Another way of passing $bashpid
from foo
to bar
is obviously to pass it as a command line argument and to receive it with local bashpid="$1"
in bar
or something similar, but you say you don't want to do this.
Thebashpid
approach should work for me. But ifbashpid
is the local/dynamic scope offoo
, why are you passing it as an env var when callingbar
?
â Harry
Jul 29 at 4:46
1
@Harry It allows for the case wherebar
is a script or other application (not a function).
â Kusalananda
Jul 29 at 9:13
Then, can't we justexport
it from withinfoo
so that ALL calls to functions or programs/scripts from withinfoo
automatically get it, instead of I passing it explicitly every time?
â Harry
Jul 29 at 9:26
1
@Harry Yes, of course, if you wish to do it that way. However, that would also set it infoo
and in whatever environmentfoo
is executing in. In this case, you are runningfoo
as a background job, so it doesn't affect the otherfoo
s or the main script.
â Kusalananda
Jul 29 at 9:42
add a comment |Â
up vote
1
down vote
accepted
#!/bin/bash
bar ()
# bashpid is set in our environment from the calling function
printf 'bar BASHPID = %d, bar bashpid = %dn' "$BASHPID" "$bashpid"
# in your case, you would have...
local logfile="/some/path/to/log.$bashpid"
# etc.
foo ()
local bashpid="$BASHPID"
local message
local logfile="/some/path/to/log.$BASHPID"
message=$( bashpid="$bashpid" bar ); printf 'Message from bar: %sn' "$message"
message=$( bashpid="$bashpid" bar ); printf 'Message from bar: %sn' "$message"
message=$( bashpid="$bashpid" bar ); printf 'Message from bar: %sn' "$message"
message=$( bashpid="$bashpid" bar ); printf 'Message from bar: %sn' "$message"
foo &
foo &
foo &
wait
Example run:
$ bash script.sh
Message from bar: bar BASHPID = 71979, bar bashpid = 18461
Message from bar: bar BASHPID = 7420, bar bashpid = 71036
Message from bar: bar BASHPID = 6109, bar bashpid = 18461
Message from bar: bar BASHPID = 27868, bar bashpid = 71036
Message from bar: bar BASHPID = 44547, bar bashpid = 60086
Message from bar: bar BASHPID = 69310, bar bashpid = 71036
Message from bar: bar BASHPID = 37649, bar bashpid = 60086
Message from bar: bar BASHPID = 15999, bar bashpid = 71036
Message from bar: bar BASHPID = 81520, bar bashpid = 18461
Message from bar: bar BASHPID = 92568, bar bashpid = 60086
Message from bar: bar BASHPID = 72438, bar bashpid = 18461
Message from bar: bar BASHPID = 15094, bar bashpid = 60086
For each invocation of foo
in the main part of the script, four calls to bar
will be made and four lines of output will be produced. As you see, there is only three unique bashpid
numbers, each from one of the foo
invocations.
Another way of passing $bashpid
from foo
to bar
is obviously to pass it as a command line argument and to receive it with local bashpid="$1"
in bar
or something similar, but you say you don't want to do this.
Thebashpid
approach should work for me. But ifbashpid
is the local/dynamic scope offoo
, why are you passing it as an env var when callingbar
?
â Harry
Jul 29 at 4:46
1
@Harry It allows for the case wherebar
is a script or other application (not a function).
â Kusalananda
Jul 29 at 9:13
Then, can't we justexport
it from withinfoo
so that ALL calls to functions or programs/scripts from withinfoo
automatically get it, instead of I passing it explicitly every time?
â Harry
Jul 29 at 9:26
1
@Harry Yes, of course, if you wish to do it that way. However, that would also set it infoo
and in whatever environmentfoo
is executing in. In this case, you are runningfoo
as a background job, so it doesn't affect the otherfoo
s or the main script.
â Kusalananda
Jul 29 at 9:42
add a comment |Â
up vote
1
down vote
accepted
up vote
1
down vote
accepted
#!/bin/bash
bar ()
# bashpid is set in our environment from the calling function
printf 'bar BASHPID = %d, bar bashpid = %dn' "$BASHPID" "$bashpid"
# in your case, you would have...
local logfile="/some/path/to/log.$bashpid"
# etc.
foo ()
local bashpid="$BASHPID"
local message
local logfile="/some/path/to/log.$BASHPID"
message=$( bashpid="$bashpid" bar ); printf 'Message from bar: %sn' "$message"
message=$( bashpid="$bashpid" bar ); printf 'Message from bar: %sn' "$message"
message=$( bashpid="$bashpid" bar ); printf 'Message from bar: %sn' "$message"
message=$( bashpid="$bashpid" bar ); printf 'Message from bar: %sn' "$message"
foo &
foo &
foo &
wait
Example run:
$ bash script.sh
Message from bar: bar BASHPID = 71979, bar bashpid = 18461
Message from bar: bar BASHPID = 7420, bar bashpid = 71036
Message from bar: bar BASHPID = 6109, bar bashpid = 18461
Message from bar: bar BASHPID = 27868, bar bashpid = 71036
Message from bar: bar BASHPID = 44547, bar bashpid = 60086
Message from bar: bar BASHPID = 69310, bar bashpid = 71036
Message from bar: bar BASHPID = 37649, bar bashpid = 60086
Message from bar: bar BASHPID = 15999, bar bashpid = 71036
Message from bar: bar BASHPID = 81520, bar bashpid = 18461
Message from bar: bar BASHPID = 92568, bar bashpid = 60086
Message from bar: bar BASHPID = 72438, bar bashpid = 18461
Message from bar: bar BASHPID = 15094, bar bashpid = 60086
For each invocation of foo
in the main part of the script, four calls to bar
will be made and four lines of output will be produced. As you see, there is only three unique bashpid
numbers, each from one of the foo
invocations.
Another way of passing $bashpid
from foo
to bar
is obviously to pass it as a command line argument and to receive it with local bashpid="$1"
in bar
or something similar, but you say you don't want to do this.
#!/bin/bash
bar ()
# bashpid is set in our environment from the calling function
printf 'bar BASHPID = %d, bar bashpid = %dn' "$BASHPID" "$bashpid"
# in your case, you would have...
local logfile="/some/path/to/log.$bashpid"
# etc.
foo ()
local bashpid="$BASHPID"
local message
local logfile="/some/path/to/log.$BASHPID"
message=$( bashpid="$bashpid" bar ); printf 'Message from bar: %sn' "$message"
message=$( bashpid="$bashpid" bar ); printf 'Message from bar: %sn' "$message"
message=$( bashpid="$bashpid" bar ); printf 'Message from bar: %sn' "$message"
message=$( bashpid="$bashpid" bar ); printf 'Message from bar: %sn' "$message"
foo &
foo &
foo &
wait
Example run:
$ bash script.sh
Message from bar: bar BASHPID = 71979, bar bashpid = 18461
Message from bar: bar BASHPID = 7420, bar bashpid = 71036
Message from bar: bar BASHPID = 6109, bar bashpid = 18461
Message from bar: bar BASHPID = 27868, bar bashpid = 71036
Message from bar: bar BASHPID = 44547, bar bashpid = 60086
Message from bar: bar BASHPID = 69310, bar bashpid = 71036
Message from bar: bar BASHPID = 37649, bar bashpid = 60086
Message from bar: bar BASHPID = 15999, bar bashpid = 71036
Message from bar: bar BASHPID = 81520, bar bashpid = 18461
Message from bar: bar BASHPID = 92568, bar bashpid = 60086
Message from bar: bar BASHPID = 72438, bar bashpid = 18461
Message from bar: bar BASHPID = 15094, bar bashpid = 60086
For each invocation of foo
in the main part of the script, four calls to bar
will be made and four lines of output will be produced. As you see, there is only three unique bashpid
numbers, each from one of the foo
invocations.
Another way of passing $bashpid
from foo
to bar
is obviously to pass it as a command line argument and to receive it with local bashpid="$1"
in bar
or something similar, but you say you don't want to do this.
edited Jul 27 at 9:55
answered Jul 27 at 9:28
Kusalananda
101k13199311
101k13199311
Thebashpid
approach should work for me. But ifbashpid
is the local/dynamic scope offoo
, why are you passing it as an env var when callingbar
?
â Harry
Jul 29 at 4:46
1
@Harry It allows for the case wherebar
is a script or other application (not a function).
â Kusalananda
Jul 29 at 9:13
Then, can't we justexport
it from withinfoo
so that ALL calls to functions or programs/scripts from withinfoo
automatically get it, instead of I passing it explicitly every time?
â Harry
Jul 29 at 9:26
1
@Harry Yes, of course, if you wish to do it that way. However, that would also set it infoo
and in whatever environmentfoo
is executing in. In this case, you are runningfoo
as a background job, so it doesn't affect the otherfoo
s or the main script.
â Kusalananda
Jul 29 at 9:42
add a comment |Â
Thebashpid
approach should work for me. But ifbashpid
is the local/dynamic scope offoo
, why are you passing it as an env var when callingbar
?
â Harry
Jul 29 at 4:46
1
@Harry It allows for the case wherebar
is a script or other application (not a function).
â Kusalananda
Jul 29 at 9:13
Then, can't we justexport
it from withinfoo
so that ALL calls to functions or programs/scripts from withinfoo
automatically get it, instead of I passing it explicitly every time?
â Harry
Jul 29 at 9:26
1
@Harry Yes, of course, if you wish to do it that way. However, that would also set it infoo
and in whatever environmentfoo
is executing in. In this case, you are runningfoo
as a background job, so it doesn't affect the otherfoo
s or the main script.
â Kusalananda
Jul 29 at 9:42
The
bashpid
approach should work for me. But if bashpid
is the local/dynamic scope of foo
, why are you passing it as an env var when calling bar
?â Harry
Jul 29 at 4:46
The
bashpid
approach should work for me. But if bashpid
is the local/dynamic scope of foo
, why are you passing it as an env var when calling bar
?â Harry
Jul 29 at 4:46
1
1
@Harry It allows for the case where
bar
is a script or other application (not a function).â Kusalananda
Jul 29 at 9:13
@Harry It allows for the case where
bar
is a script or other application (not a function).â Kusalananda
Jul 29 at 9:13
Then, can't we just
export
it from within foo
so that ALL calls to functions or programs/scripts from within foo
automatically get it, instead of I passing it explicitly every time?â Harry
Jul 29 at 9:26
Then, can't we just
export
it from within foo
so that ALL calls to functions or programs/scripts from within foo
automatically get it, instead of I passing it explicitly every time?â Harry
Jul 29 at 9:26
1
1
@Harry Yes, of course, if you wish to do it that way. However, that would also set it in
foo
and in whatever environment foo
is executing in. In this case, you are running foo
as a background job, so it doesn't affect the other foo
s or the main script.â Kusalananda
Jul 29 at 9:42
@Harry Yes, of course, if you wish to do it that way. However, that would also set it in
foo
and in whatever environment foo
is executing in. In this case, you are running foo
as a background job, so it doesn't affect the other foo
s or the main script.â Kusalananda
Jul 29 at 9:42
add a comment |Â
up vote
1
down vote
NOTE: In regards to your general questions around $BASHPID
, this is readonly and you cannot manipulate it. This is by design.
It's typically my general advice that when you get to the level of sophistication with Bash scripts like this, it's time to move it to Python, Ruby, whatever.
Your example
I guess I don't see what your issue is, this works for me:
$ cat subby.bash
#!/bin/bash
function foo()
local bashpid_of_foo=$BASHPID
local output=blipblop
echo "foo: $bashpid_of_foo"
echo "foo: $output"
out_1=$(echo $bashpid_of_foo)
out_n=$(echo $output)
echo "out_1: $out_1"
echo "out_n: $out_n"
foo &
$ ./subby.bash
foo: 4900
foo: blipblop
out_1: 4900
out_n: blipblop
Addition of export
If we change this around by making bar_1
into a shell script:
$ cat bar_1
#!/bin/bash
echo "from bar_1: $bashpid_of_foo"
And change your original script like this:
#!/bin/bash
function foo()
export bashpid_of_foo=$BASHPID
local output=blipblop
echo "foo: $bashpid_of_foo"
echo "foo: $output"
out_1=$(echo $bashpid_of_foo)
out_2=$(./bar_1)
out_n=$(echo $output)
echo "out_1: $out_1"
echo "out_2: $out_2"
echo "out_n: $out_n"
foo &
We can see that the $bashpid_of_foo
is getting exported properly to subshells:
$ ./subby.bash
foo: 5014
foo: blipblop
out_1: 5014
out_2: from bar_1: 5014
out_n: blipblop
We need to use an export
here and not just a local
because otherwise the environment variables will not get exported to any children. The subshells are child shells here.
$ help export
...
Marks each NAME for automatic export to the environment of subsequently
executed commands. If VALUE is supplied, assign VALUE before exporting.
add a comment |Â
up vote
1
down vote
NOTE: In regards to your general questions around $BASHPID
, this is readonly and you cannot manipulate it. This is by design.
It's typically my general advice that when you get to the level of sophistication with Bash scripts like this, it's time to move it to Python, Ruby, whatever.
Your example
I guess I don't see what your issue is, this works for me:
$ cat subby.bash
#!/bin/bash
function foo()
local bashpid_of_foo=$BASHPID
local output=blipblop
echo "foo: $bashpid_of_foo"
echo "foo: $output"
out_1=$(echo $bashpid_of_foo)
out_n=$(echo $output)
echo "out_1: $out_1"
echo "out_n: $out_n"
foo &
$ ./subby.bash
foo: 4900
foo: blipblop
out_1: 4900
out_n: blipblop
Addition of export
If we change this around by making bar_1
into a shell script:
$ cat bar_1
#!/bin/bash
echo "from bar_1: $bashpid_of_foo"
And change your original script like this:
#!/bin/bash
function foo()
export bashpid_of_foo=$BASHPID
local output=blipblop
echo "foo: $bashpid_of_foo"
echo "foo: $output"
out_1=$(echo $bashpid_of_foo)
out_2=$(./bar_1)
out_n=$(echo $output)
echo "out_1: $out_1"
echo "out_2: $out_2"
echo "out_n: $out_n"
foo &
We can see that the $bashpid_of_foo
is getting exported properly to subshells:
$ ./subby.bash
foo: 5014
foo: blipblop
out_1: 5014
out_2: from bar_1: 5014
out_n: blipblop
We need to use an export
here and not just a local
because otherwise the environment variables will not get exported to any children. The subshells are child shells here.
$ help export
...
Marks each NAME for automatic export to the environment of subsequently
executed commands. If VALUE is supplied, assign VALUE before exporting.
add a comment |Â
up vote
1
down vote
up vote
1
down vote
NOTE: In regards to your general questions around $BASHPID
, this is readonly and you cannot manipulate it. This is by design.
It's typically my general advice that when you get to the level of sophistication with Bash scripts like this, it's time to move it to Python, Ruby, whatever.
Your example
I guess I don't see what your issue is, this works for me:
$ cat subby.bash
#!/bin/bash
function foo()
local bashpid_of_foo=$BASHPID
local output=blipblop
echo "foo: $bashpid_of_foo"
echo "foo: $output"
out_1=$(echo $bashpid_of_foo)
out_n=$(echo $output)
echo "out_1: $out_1"
echo "out_n: $out_n"
foo &
$ ./subby.bash
foo: 4900
foo: blipblop
out_1: 4900
out_n: blipblop
Addition of export
If we change this around by making bar_1
into a shell script:
$ cat bar_1
#!/bin/bash
echo "from bar_1: $bashpid_of_foo"
And change your original script like this:
#!/bin/bash
function foo()
export bashpid_of_foo=$BASHPID
local output=blipblop
echo "foo: $bashpid_of_foo"
echo "foo: $output"
out_1=$(echo $bashpid_of_foo)
out_2=$(./bar_1)
out_n=$(echo $output)
echo "out_1: $out_1"
echo "out_2: $out_2"
echo "out_n: $out_n"
foo &
We can see that the $bashpid_of_foo
is getting exported properly to subshells:
$ ./subby.bash
foo: 5014
foo: blipblop
out_1: 5014
out_2: from bar_1: 5014
out_n: blipblop
We need to use an export
here and not just a local
because otherwise the environment variables will not get exported to any children. The subshells are child shells here.
$ help export
...
Marks each NAME for automatic export to the environment of subsequently
executed commands. If VALUE is supplied, assign VALUE before exporting.
NOTE: In regards to your general questions around $BASHPID
, this is readonly and you cannot manipulate it. This is by design.
It's typically my general advice that when you get to the level of sophistication with Bash scripts like this, it's time to move it to Python, Ruby, whatever.
Your example
I guess I don't see what your issue is, this works for me:
$ cat subby.bash
#!/bin/bash
function foo()
local bashpid_of_foo=$BASHPID
local output=blipblop
echo "foo: $bashpid_of_foo"
echo "foo: $output"
out_1=$(echo $bashpid_of_foo)
out_n=$(echo $output)
echo "out_1: $out_1"
echo "out_n: $out_n"
foo &
$ ./subby.bash
foo: 4900
foo: blipblop
out_1: 4900
out_n: blipblop
Addition of export
If we change this around by making bar_1
into a shell script:
$ cat bar_1
#!/bin/bash
echo "from bar_1: $bashpid_of_foo"
And change your original script like this:
#!/bin/bash
function foo()
export bashpid_of_foo=$BASHPID
local output=blipblop
echo "foo: $bashpid_of_foo"
echo "foo: $output"
out_1=$(echo $bashpid_of_foo)
out_2=$(./bar_1)
out_n=$(echo $output)
echo "out_1: $out_1"
echo "out_2: $out_2"
echo "out_n: $out_n"
foo &
We can see that the $bashpid_of_foo
is getting exported properly to subshells:
$ ./subby.bash
foo: 5014
foo: blipblop
out_1: 5014
out_2: from bar_1: 5014
out_n: blipblop
We need to use an export
here and not just a local
because otherwise the environment variables will not get exported to any children. The subshells are child shells here.
$ help export
...
Marks each NAME for automatic export to the environment of subsequently
executed commands. If VALUE is supplied, assign VALUE before exporting.
edited Jul 27 at 8:00
answered Jul 27 at 7:31
slmâ¦
232k65479649
232k65479649
add a comment |Â
add a comment |Â
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f458760%2fpid-of-the-background-function-f-in-commands-invoked-in-subshells-inside-f%23new-answer', 'question_page');
);
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
3
BASHPID
may be special, butbashpid_of_foo
is not. You should be able to use that in the command substitutions.â Kusalananda
Jul 27 at 7:28
2
@Harry If you save
$BASHPID
inbashpid
, then the only thing you have to do differently in your command substitutions is to not press shift when typingbashpid
.â Kusalananda
Jul 27 at 8:02
2
These are the types of best practices or tricks you have to resort to @Harry as Kusalananda is saying by keeping complex software in Bash.
â slmâ¦
Jul 27 at 8:04
@Kusalananda "then the only thing you have to do differently in your command substitutions is to not press shift when typing bashpid" Lol that was astute! Ok, bro.
â Harry
Jul 27 at 8:34
My boss was pressuring me to write my script in Java (yuck!). This is a customer's server - it has Java and
bash
, but no Perl, Python, Ruby, etc. I fought with him to let me do it inbash
since I'm mostly using/bin
and/usr/bin
commands - coding which in Perl, Python, and Ruby can be relatively more verbose thanbash
. And now I run into this dead-end - which I can surely workaround (like you suggested) but would've preferred not to (by relying some existing facility. Btw, I feel, this is a feature-flaw inbash
: Abash
function (and, not an external program) should be allowed +â Harry
Jul 27 at 8:39