Discussion:
[Help-bash] Are all traps global to a script?
Peng Yu
2018-12-07 20:00:51 UTC
Permalink
Hi,

I see that traps seem to be all global. For example, if I set it in a
function, it will have an effect outside a function.

What is the best way to make effectively different traps for different
function? Does bash have a native support for this?

I can think of setting some special variables in each function so that
the trap can check this variable to know where the program is at, and
acts differently. Is there any better solution? Thanks.

$ ./main.sh
in f
^CHello World!
after f
$ cat ./main.sh
#!/usr/bin/env bash
# vim: set noexpandtab tabstop=2:

trap "echo 'Hello World1!'" INT
function f {
trap "echo 'Hello World!'" INT
echo 'in f'
}
f
sleep 10
echo 'after f'
--
Regards,
Peng
Eric Blake
2018-12-07 20:18:34 UTC
Permalink
Post by Peng Yu
Hi,
I see that traps seem to be all global. For example, if I set it in a
function, it will have an effect outside a function.
You're demonstrating that you may lack a fundamental understanding of
how functions work. Functions are snippets of code that run in the
context of the caller (if we disregard the special effects of 'local'),
and have an impact to the environment the same as any other code run in
that context.
Post by Peng Yu
What is the best way to make effectively different traps for different
function? Does bash have a native support for this?
The same way that you implement different traps for different portions
of a shell script that does not use functions. You can use 'trap -p' to
save off the previous trap definition, install your new trap, then when
done with your code, call trap to set things back to the value you saved
off earlier.
Post by Peng Yu
$ cat ./main.sh
#!/usr/bin/env bash
trap "echo 'Hello World1!'" INT
function f {
trap "echo 'Hello World!'" INT
echo 'in f'
}
f
sleep 10
echo 'after f'
Remember, this is EXACTLY the same as writing:

trap "echo 'Hello World1!'" INT
{
trap "echo 'Hello World!'" INT
echo 'in f'
}
sleep 10
echo 'after f'

(that is, instead of defining 'f' to be a snippet of shell code, then
invoking 'f' to run that snippet of code, just run that snippet of code
directly)

And if you can solve the problem of restoring the original trap without
a shell function (which you can thanks to 'trap -p'), then you can solve
it when shell functions are involved.
--
Eric Blake, Principal Software Engineer
Red Hat, Inc. +1-919-301-3266
Virtualization: qemu.org | libvirt.org
Eric Blake
2018-12-07 20:21:23 UTC
Permalink
Post by Eric Blake
The same way that you implement different traps for different portions
of a shell script that does not use functions. You can use 'trap -p' to
save off the previous trap definition, install your new trap, then when
done with your code, call trap to set things back to the value you saved
off earlier.
Or, by creating a subshell within the body of your function, and
changing the traps local to that subshell.
--
Eric Blake, Principal Software Engineer
Red Hat, Inc. +1-919-301-3266
Virtualization: qemu.org | libvirt.org
Loading...