An atexit for Bash
up vote
7
down vote
favorite
I wrote the following atexit implementation for Bash
#! /bin/bash
set -e
ATEXIT=()
function atexit_handler
{
local EXPR
for EXPR in "${ATEXIT[@]}"; do
echo "evaluating $EXPR"
eval "$EXPR" || true
done
}
trap atexit_handler EXIT
function atexit ()
{
local EXPR
for EXPR in "$@"; do
ATEXIT+=("$EXPR")
done
}
atexit true
atexit false
atexit "echo bye"
false
I am wondering, if this is possible without the use of eval
.
bash
add a comment |
up vote
7
down vote
favorite
I wrote the following atexit implementation for Bash
#! /bin/bash
set -e
ATEXIT=()
function atexit_handler
{
local EXPR
for EXPR in "${ATEXIT[@]}"; do
echo "evaluating $EXPR"
eval "$EXPR" || true
done
}
trap atexit_handler EXIT
function atexit ()
{
local EXPR
for EXPR in "$@"; do
ATEXIT+=("$EXPR")
done
}
atexit true
atexit false
atexit "echo bye"
false
I am wondering, if this is possible without the use of eval
.
bash
add a comment |
up vote
7
down vote
favorite
up vote
7
down vote
favorite
I wrote the following atexit implementation for Bash
#! /bin/bash
set -e
ATEXIT=()
function atexit_handler
{
local EXPR
for EXPR in "${ATEXIT[@]}"; do
echo "evaluating $EXPR"
eval "$EXPR" || true
done
}
trap atexit_handler EXIT
function atexit ()
{
local EXPR
for EXPR in "$@"; do
ATEXIT+=("$EXPR")
done
}
atexit true
atexit false
atexit "echo bye"
false
I am wondering, if this is possible without the use of eval
.
bash
I wrote the following atexit implementation for Bash
#! /bin/bash
set -e
ATEXIT=()
function atexit_handler
{
local EXPR
for EXPR in "${ATEXIT[@]}"; do
echo "evaluating $EXPR"
eval "$EXPR" || true
done
}
trap atexit_handler EXIT
function atexit ()
{
local EXPR
for EXPR in "$@"; do
ATEXIT+=("$EXPR")
done
}
atexit true
atexit false
atexit "echo bye"
false
I am wondering, if this is possible without the use of eval
.
bash
bash
asked Oct 21 '14 at 9:07
ceving
23517
23517
add a comment |
add a comment |
3 Answers
3
active
oldest
votes
up vote
7
down vote
I don't think it's possible without the eval
. A close candidate might be:
atexit_handler() {
local EXPR
for EXPR in "${ATEXIT[@]}"; do
echo "evaluating $EXPR"
$EXPR || true
done
}
But this won't work with non-trivial expressions like this:
atexit 'for i in "a b" c; do echo $i; done'
Using the function
keyword in function declaration like this is an outdated practice:
function atexit_handler
{
local EXPR
for EXPR in "${ATEXIT[@]}"; do
echo "evaluating $EXPR"
eval "$EXPR" || true
done
}
Use the more modern style I wrote in the previous example above.
Instead of this:
for EXPR in "$@"; do
ATEXIT+=("$EXPR")
done
A simpler way to iterate over $@
:
for EXPR; do
ATEXIT+=("$EXPR")
done
But actually, as @etan-reisner pointed out in a comment, it's silly to loop here when you can add the entire arg list in one swift move:
ATEXIT+=("$@")
2
Why bother iterating over"$@"
at all? Why not just splat it into the()
directly?ATEXIT+=("$@")
– Etan Reisner
Oct 23 '14 at 18:45
1
Usingset -e
means it works even when the script is run "manually" (i.e.bash myscript.sh
) which the shebang does not.
– Etan Reisner
Oct 23 '14 at 18:46
@EtanReisner spot on! Thanks for that. I added the first point to my answer and removed the second.
– janos
Oct 23 '14 at 20:34
Emacs does not color the function names in sh-mode. Using thefunction
keyword adds some syntax highlighting to functions.
– ceving
Oct 27 '14 at 9:51
At the time I posted this, I didn't know whatEXIT
really meant. Thanks @TobySpeight for pointing this out, dropped that point. (I fear I may have said things like this in other old answers too. I should probably search and verify all :-/)
– janos
yesterday
add a comment |
up vote
1
down vote
Sorry for excavating this, but just found it and wanted to try.
Will offer what I can.
#! /bin/bash
This is no crime, but it's a tad more portable (if that matters at all to you) if you use
#! /bin/env bash
env
itself is virtually always in /bin
, though some installations move the interpreter binaries.
I don't personally like or use set -e
. It doesn't give me as much control over what happens. Personally, I prefer trap
s, something like this:
trap 'echo "ERROR $? at $0:$LINENO - [$BASH_COMMAND]"' err
Then I get useful feedback.
$: bogus
bash: bogus: command not found
ERROR 127 at /usr/bin/bash:73 - [bogus]
As for the eval
, how about creating a controlled file to source at exit time?
atexit_handler() {
tmp=$(mktemp)
printf "%sn" "${ATEXIT[@]}" >| $tmp
trap 'echo "Error $? in exit handler when processing [$BASH_COMMAND]"' err
. $tmp
}
This would allow for more arbitrarily complex possibilities, without really worsening the security risk of the eval
, which isn't catastrophic if your code registers all the commands going into the handler anyway. It also leaves you the option of scheduling the cleanup of the file with the handler, so that if it succeeds it leaves no mess, but if it fails will abort and let you debug the file.
atexit true
atexit "echo bye"
atexit 'sing() { for i in do re me;do echo "$i"; done; }'
atexit sing
atexit false
atexit 'rm $tmp' # defer evaluation
I love this idea, btw. I may start using it. :)
New contributor
I've never seen a/bin/env
- on Debian-based systems at least, it's always in/usr/bin
.
– Toby Speight
yesterday
As long as it's working, I wouldn't sweat it. YMMV; even where I work, across a lot of systems, they are mostly all RHEL 6 or 7 and vaguely similar in structure, so it has rarely been an issue. It's just something I have been told to cultivate as a habit, and I have (anecdotally) had fewer issues since I started doing it. shrug :D
– Paul Hodges
yesterday
So RHEL have/bin/env
instead of/usr/bin/env
? Or as well as? If it has both, then the latter would seem to be the safer choice.
– Toby Speight
yesterday
Common to have it linked in both locations just in case. :)
– Paul Hodges
yesterday
add a comment |
up vote
0
down vote
Still uses eval, but it seems cleaner to do:
atexit() {
cmd="$1"
eval set -- $(trap -p EXIT)
trap "$cmd; $3" EXIT
}
To allow semi-colons (eg, atexit "echo foo;"
) and aesthetic purity, you might like:
atexit() {
cmd="${1%;}"
eval set -- $(trap -p EXIT)
trap "$cmd${3:+; }$3" EXIT
}
You have presented an alternative solution, but haven't reviewed the code. Please edit to show what aspects of the question code prompted you to write this version, and in what ways it's an improvement over the original. It may be worth (re-)reading How to Answer.
– Toby Speight
yesterday
add a comment |
3 Answers
3
active
oldest
votes
3 Answers
3
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
7
down vote
I don't think it's possible without the eval
. A close candidate might be:
atexit_handler() {
local EXPR
for EXPR in "${ATEXIT[@]}"; do
echo "evaluating $EXPR"
$EXPR || true
done
}
But this won't work with non-trivial expressions like this:
atexit 'for i in "a b" c; do echo $i; done'
Using the function
keyword in function declaration like this is an outdated practice:
function atexit_handler
{
local EXPR
for EXPR in "${ATEXIT[@]}"; do
echo "evaluating $EXPR"
eval "$EXPR" || true
done
}
Use the more modern style I wrote in the previous example above.
Instead of this:
for EXPR in "$@"; do
ATEXIT+=("$EXPR")
done
A simpler way to iterate over $@
:
for EXPR; do
ATEXIT+=("$EXPR")
done
But actually, as @etan-reisner pointed out in a comment, it's silly to loop here when you can add the entire arg list in one swift move:
ATEXIT+=("$@")
2
Why bother iterating over"$@"
at all? Why not just splat it into the()
directly?ATEXIT+=("$@")
– Etan Reisner
Oct 23 '14 at 18:45
1
Usingset -e
means it works even when the script is run "manually" (i.e.bash myscript.sh
) which the shebang does not.
– Etan Reisner
Oct 23 '14 at 18:46
@EtanReisner spot on! Thanks for that. I added the first point to my answer and removed the second.
– janos
Oct 23 '14 at 20:34
Emacs does not color the function names in sh-mode. Using thefunction
keyword adds some syntax highlighting to functions.
– ceving
Oct 27 '14 at 9:51
At the time I posted this, I didn't know whatEXIT
really meant. Thanks @TobySpeight for pointing this out, dropped that point. (I fear I may have said things like this in other old answers too. I should probably search and verify all :-/)
– janos
yesterday
add a comment |
up vote
7
down vote
I don't think it's possible without the eval
. A close candidate might be:
atexit_handler() {
local EXPR
for EXPR in "${ATEXIT[@]}"; do
echo "evaluating $EXPR"
$EXPR || true
done
}
But this won't work with non-trivial expressions like this:
atexit 'for i in "a b" c; do echo $i; done'
Using the function
keyword in function declaration like this is an outdated practice:
function atexit_handler
{
local EXPR
for EXPR in "${ATEXIT[@]}"; do
echo "evaluating $EXPR"
eval "$EXPR" || true
done
}
Use the more modern style I wrote in the previous example above.
Instead of this:
for EXPR in "$@"; do
ATEXIT+=("$EXPR")
done
A simpler way to iterate over $@
:
for EXPR; do
ATEXIT+=("$EXPR")
done
But actually, as @etan-reisner pointed out in a comment, it's silly to loop here when you can add the entire arg list in one swift move:
ATEXIT+=("$@")
2
Why bother iterating over"$@"
at all? Why not just splat it into the()
directly?ATEXIT+=("$@")
– Etan Reisner
Oct 23 '14 at 18:45
1
Usingset -e
means it works even when the script is run "manually" (i.e.bash myscript.sh
) which the shebang does not.
– Etan Reisner
Oct 23 '14 at 18:46
@EtanReisner spot on! Thanks for that. I added the first point to my answer and removed the second.
– janos
Oct 23 '14 at 20:34
Emacs does not color the function names in sh-mode. Using thefunction
keyword adds some syntax highlighting to functions.
– ceving
Oct 27 '14 at 9:51
At the time I posted this, I didn't know whatEXIT
really meant. Thanks @TobySpeight for pointing this out, dropped that point. (I fear I may have said things like this in other old answers too. I should probably search and verify all :-/)
– janos
yesterday
add a comment |
up vote
7
down vote
up vote
7
down vote
I don't think it's possible without the eval
. A close candidate might be:
atexit_handler() {
local EXPR
for EXPR in "${ATEXIT[@]}"; do
echo "evaluating $EXPR"
$EXPR || true
done
}
But this won't work with non-trivial expressions like this:
atexit 'for i in "a b" c; do echo $i; done'
Using the function
keyword in function declaration like this is an outdated practice:
function atexit_handler
{
local EXPR
for EXPR in "${ATEXIT[@]}"; do
echo "evaluating $EXPR"
eval "$EXPR" || true
done
}
Use the more modern style I wrote in the previous example above.
Instead of this:
for EXPR in "$@"; do
ATEXIT+=("$EXPR")
done
A simpler way to iterate over $@
:
for EXPR; do
ATEXIT+=("$EXPR")
done
But actually, as @etan-reisner pointed out in a comment, it's silly to loop here when you can add the entire arg list in one swift move:
ATEXIT+=("$@")
I don't think it's possible without the eval
. A close candidate might be:
atexit_handler() {
local EXPR
for EXPR in "${ATEXIT[@]}"; do
echo "evaluating $EXPR"
$EXPR || true
done
}
But this won't work with non-trivial expressions like this:
atexit 'for i in "a b" c; do echo $i; done'
Using the function
keyword in function declaration like this is an outdated practice:
function atexit_handler
{
local EXPR
for EXPR in "${ATEXIT[@]}"; do
echo "evaluating $EXPR"
eval "$EXPR" || true
done
}
Use the more modern style I wrote in the previous example above.
Instead of this:
for EXPR in "$@"; do
ATEXIT+=("$EXPR")
done
A simpler way to iterate over $@
:
for EXPR; do
ATEXIT+=("$EXPR")
done
But actually, as @etan-reisner pointed out in a comment, it's silly to loop here when you can add the entire arg list in one swift move:
ATEXIT+=("$@")
edited yesterday
answered Oct 21 '14 at 11:37
janos
96.6k12124350
96.6k12124350
2
Why bother iterating over"$@"
at all? Why not just splat it into the()
directly?ATEXIT+=("$@")
– Etan Reisner
Oct 23 '14 at 18:45
1
Usingset -e
means it works even when the script is run "manually" (i.e.bash myscript.sh
) which the shebang does not.
– Etan Reisner
Oct 23 '14 at 18:46
@EtanReisner spot on! Thanks for that. I added the first point to my answer and removed the second.
– janos
Oct 23 '14 at 20:34
Emacs does not color the function names in sh-mode. Using thefunction
keyword adds some syntax highlighting to functions.
– ceving
Oct 27 '14 at 9:51
At the time I posted this, I didn't know whatEXIT
really meant. Thanks @TobySpeight for pointing this out, dropped that point. (I fear I may have said things like this in other old answers too. I should probably search and verify all :-/)
– janos
yesterday
add a comment |
2
Why bother iterating over"$@"
at all? Why not just splat it into the()
directly?ATEXIT+=("$@")
– Etan Reisner
Oct 23 '14 at 18:45
1
Usingset -e
means it works even when the script is run "manually" (i.e.bash myscript.sh
) which the shebang does not.
– Etan Reisner
Oct 23 '14 at 18:46
@EtanReisner spot on! Thanks for that. I added the first point to my answer and removed the second.
– janos
Oct 23 '14 at 20:34
Emacs does not color the function names in sh-mode. Using thefunction
keyword adds some syntax highlighting to functions.
– ceving
Oct 27 '14 at 9:51
At the time I posted this, I didn't know whatEXIT
really meant. Thanks @TobySpeight for pointing this out, dropped that point. (I fear I may have said things like this in other old answers too. I should probably search and verify all :-/)
– janos
yesterday
2
2
Why bother iterating over
"$@"
at all? Why not just splat it into the ()
directly? ATEXIT+=("$@")
– Etan Reisner
Oct 23 '14 at 18:45
Why bother iterating over
"$@"
at all? Why not just splat it into the ()
directly? ATEXIT+=("$@")
– Etan Reisner
Oct 23 '14 at 18:45
1
1
Using
set -e
means it works even when the script is run "manually" (i.e. bash myscript.sh
) which the shebang does not.– Etan Reisner
Oct 23 '14 at 18:46
Using
set -e
means it works even when the script is run "manually" (i.e. bash myscript.sh
) which the shebang does not.– Etan Reisner
Oct 23 '14 at 18:46
@EtanReisner spot on! Thanks for that. I added the first point to my answer and removed the second.
– janos
Oct 23 '14 at 20:34
@EtanReisner spot on! Thanks for that. I added the first point to my answer and removed the second.
– janos
Oct 23 '14 at 20:34
Emacs does not color the function names in sh-mode. Using the
function
keyword adds some syntax highlighting to functions.– ceving
Oct 27 '14 at 9:51
Emacs does not color the function names in sh-mode. Using the
function
keyword adds some syntax highlighting to functions.– ceving
Oct 27 '14 at 9:51
At the time I posted this, I didn't know what
EXIT
really meant. Thanks @TobySpeight for pointing this out, dropped that point. (I fear I may have said things like this in other old answers too. I should probably search and verify all :-/)– janos
yesterday
At the time I posted this, I didn't know what
EXIT
really meant. Thanks @TobySpeight for pointing this out, dropped that point. (I fear I may have said things like this in other old answers too. I should probably search and verify all :-/)– janos
yesterday
add a comment |
up vote
1
down vote
Sorry for excavating this, but just found it and wanted to try.
Will offer what I can.
#! /bin/bash
This is no crime, but it's a tad more portable (if that matters at all to you) if you use
#! /bin/env bash
env
itself is virtually always in /bin
, though some installations move the interpreter binaries.
I don't personally like or use set -e
. It doesn't give me as much control over what happens. Personally, I prefer trap
s, something like this:
trap 'echo "ERROR $? at $0:$LINENO - [$BASH_COMMAND]"' err
Then I get useful feedback.
$: bogus
bash: bogus: command not found
ERROR 127 at /usr/bin/bash:73 - [bogus]
As for the eval
, how about creating a controlled file to source at exit time?
atexit_handler() {
tmp=$(mktemp)
printf "%sn" "${ATEXIT[@]}" >| $tmp
trap 'echo "Error $? in exit handler when processing [$BASH_COMMAND]"' err
. $tmp
}
This would allow for more arbitrarily complex possibilities, without really worsening the security risk of the eval
, which isn't catastrophic if your code registers all the commands going into the handler anyway. It also leaves you the option of scheduling the cleanup of the file with the handler, so that if it succeeds it leaves no mess, but if it fails will abort and let you debug the file.
atexit true
atexit "echo bye"
atexit 'sing() { for i in do re me;do echo "$i"; done; }'
atexit sing
atexit false
atexit 'rm $tmp' # defer evaluation
I love this idea, btw. I may start using it. :)
New contributor
I've never seen a/bin/env
- on Debian-based systems at least, it's always in/usr/bin
.
– Toby Speight
yesterday
As long as it's working, I wouldn't sweat it. YMMV; even where I work, across a lot of systems, they are mostly all RHEL 6 or 7 and vaguely similar in structure, so it has rarely been an issue. It's just something I have been told to cultivate as a habit, and I have (anecdotally) had fewer issues since I started doing it. shrug :D
– Paul Hodges
yesterday
So RHEL have/bin/env
instead of/usr/bin/env
? Or as well as? If it has both, then the latter would seem to be the safer choice.
– Toby Speight
yesterday
Common to have it linked in both locations just in case. :)
– Paul Hodges
yesterday
add a comment |
up vote
1
down vote
Sorry for excavating this, but just found it and wanted to try.
Will offer what I can.
#! /bin/bash
This is no crime, but it's a tad more portable (if that matters at all to you) if you use
#! /bin/env bash
env
itself is virtually always in /bin
, though some installations move the interpreter binaries.
I don't personally like or use set -e
. It doesn't give me as much control over what happens. Personally, I prefer trap
s, something like this:
trap 'echo "ERROR $? at $0:$LINENO - [$BASH_COMMAND]"' err
Then I get useful feedback.
$: bogus
bash: bogus: command not found
ERROR 127 at /usr/bin/bash:73 - [bogus]
As for the eval
, how about creating a controlled file to source at exit time?
atexit_handler() {
tmp=$(mktemp)
printf "%sn" "${ATEXIT[@]}" >| $tmp
trap 'echo "Error $? in exit handler when processing [$BASH_COMMAND]"' err
. $tmp
}
This would allow for more arbitrarily complex possibilities, without really worsening the security risk of the eval
, which isn't catastrophic if your code registers all the commands going into the handler anyway. It also leaves you the option of scheduling the cleanup of the file with the handler, so that if it succeeds it leaves no mess, but if it fails will abort and let you debug the file.
atexit true
atexit "echo bye"
atexit 'sing() { for i in do re me;do echo "$i"; done; }'
atexit sing
atexit false
atexit 'rm $tmp' # defer evaluation
I love this idea, btw. I may start using it. :)
New contributor
I've never seen a/bin/env
- on Debian-based systems at least, it's always in/usr/bin
.
– Toby Speight
yesterday
As long as it's working, I wouldn't sweat it. YMMV; even where I work, across a lot of systems, they are mostly all RHEL 6 or 7 and vaguely similar in structure, so it has rarely been an issue. It's just something I have been told to cultivate as a habit, and I have (anecdotally) had fewer issues since I started doing it. shrug :D
– Paul Hodges
yesterday
So RHEL have/bin/env
instead of/usr/bin/env
? Or as well as? If it has both, then the latter would seem to be the safer choice.
– Toby Speight
yesterday
Common to have it linked in both locations just in case. :)
– Paul Hodges
yesterday
add a comment |
up vote
1
down vote
up vote
1
down vote
Sorry for excavating this, but just found it and wanted to try.
Will offer what I can.
#! /bin/bash
This is no crime, but it's a tad more portable (if that matters at all to you) if you use
#! /bin/env bash
env
itself is virtually always in /bin
, though some installations move the interpreter binaries.
I don't personally like or use set -e
. It doesn't give me as much control over what happens. Personally, I prefer trap
s, something like this:
trap 'echo "ERROR $? at $0:$LINENO - [$BASH_COMMAND]"' err
Then I get useful feedback.
$: bogus
bash: bogus: command not found
ERROR 127 at /usr/bin/bash:73 - [bogus]
As for the eval
, how about creating a controlled file to source at exit time?
atexit_handler() {
tmp=$(mktemp)
printf "%sn" "${ATEXIT[@]}" >| $tmp
trap 'echo "Error $? in exit handler when processing [$BASH_COMMAND]"' err
. $tmp
}
This would allow for more arbitrarily complex possibilities, without really worsening the security risk of the eval
, which isn't catastrophic if your code registers all the commands going into the handler anyway. It also leaves you the option of scheduling the cleanup of the file with the handler, so that if it succeeds it leaves no mess, but if it fails will abort and let you debug the file.
atexit true
atexit "echo bye"
atexit 'sing() { for i in do re me;do echo "$i"; done; }'
atexit sing
atexit false
atexit 'rm $tmp' # defer evaluation
I love this idea, btw. I may start using it. :)
New contributor
Sorry for excavating this, but just found it and wanted to try.
Will offer what I can.
#! /bin/bash
This is no crime, but it's a tad more portable (if that matters at all to you) if you use
#! /bin/env bash
env
itself is virtually always in /bin
, though some installations move the interpreter binaries.
I don't personally like or use set -e
. It doesn't give me as much control over what happens. Personally, I prefer trap
s, something like this:
trap 'echo "ERROR $? at $0:$LINENO - [$BASH_COMMAND]"' err
Then I get useful feedback.
$: bogus
bash: bogus: command not found
ERROR 127 at /usr/bin/bash:73 - [bogus]
As for the eval
, how about creating a controlled file to source at exit time?
atexit_handler() {
tmp=$(mktemp)
printf "%sn" "${ATEXIT[@]}" >| $tmp
trap 'echo "Error $? in exit handler when processing [$BASH_COMMAND]"' err
. $tmp
}
This would allow for more arbitrarily complex possibilities, without really worsening the security risk of the eval
, which isn't catastrophic if your code registers all the commands going into the handler anyway. It also leaves you the option of scheduling the cleanup of the file with the handler, so that if it succeeds it leaves no mess, but if it fails will abort and let you debug the file.
atexit true
atexit "echo bye"
atexit 'sing() { for i in do re me;do echo "$i"; done; }'
atexit sing
atexit false
atexit 'rm $tmp' # defer evaluation
I love this idea, btw. I may start using it. :)
New contributor
edited yesterday
New contributor
answered 2 days ago
Paul Hodges
1114
1114
New contributor
New contributor
I've never seen a/bin/env
- on Debian-based systems at least, it's always in/usr/bin
.
– Toby Speight
yesterday
As long as it's working, I wouldn't sweat it. YMMV; even where I work, across a lot of systems, they are mostly all RHEL 6 or 7 and vaguely similar in structure, so it has rarely been an issue. It's just something I have been told to cultivate as a habit, and I have (anecdotally) had fewer issues since I started doing it. shrug :D
– Paul Hodges
yesterday
So RHEL have/bin/env
instead of/usr/bin/env
? Or as well as? If it has both, then the latter would seem to be the safer choice.
– Toby Speight
yesterday
Common to have it linked in both locations just in case. :)
– Paul Hodges
yesterday
add a comment |
I've never seen a/bin/env
- on Debian-based systems at least, it's always in/usr/bin
.
– Toby Speight
yesterday
As long as it's working, I wouldn't sweat it. YMMV; even where I work, across a lot of systems, they are mostly all RHEL 6 or 7 and vaguely similar in structure, so it has rarely been an issue. It's just something I have been told to cultivate as a habit, and I have (anecdotally) had fewer issues since I started doing it. shrug :D
– Paul Hodges
yesterday
So RHEL have/bin/env
instead of/usr/bin/env
? Or as well as? If it has both, then the latter would seem to be the safer choice.
– Toby Speight
yesterday
Common to have it linked in both locations just in case. :)
– Paul Hodges
yesterday
I've never seen a
/bin/env
- on Debian-based systems at least, it's always in /usr/bin
.– Toby Speight
yesterday
I've never seen a
/bin/env
- on Debian-based systems at least, it's always in /usr/bin
.– Toby Speight
yesterday
As long as it's working, I wouldn't sweat it. YMMV; even where I work, across a lot of systems, they are mostly all RHEL 6 or 7 and vaguely similar in structure, so it has rarely been an issue. It's just something I have been told to cultivate as a habit, and I have (anecdotally) had fewer issues since I started doing it. shrug :D
– Paul Hodges
yesterday
As long as it's working, I wouldn't sweat it. YMMV; even where I work, across a lot of systems, they are mostly all RHEL 6 or 7 and vaguely similar in structure, so it has rarely been an issue. It's just something I have been told to cultivate as a habit, and I have (anecdotally) had fewer issues since I started doing it. shrug :D
– Paul Hodges
yesterday
So RHEL have
/bin/env
instead of /usr/bin/env
? Or as well as? If it has both, then the latter would seem to be the safer choice.– Toby Speight
yesterday
So RHEL have
/bin/env
instead of /usr/bin/env
? Or as well as? If it has both, then the latter would seem to be the safer choice.– Toby Speight
yesterday
Common to have it linked in both locations just in case. :)
– Paul Hodges
yesterday
Common to have it linked in both locations just in case. :)
– Paul Hodges
yesterday
add a comment |
up vote
0
down vote
Still uses eval, but it seems cleaner to do:
atexit() {
cmd="$1"
eval set -- $(trap -p EXIT)
trap "$cmd; $3" EXIT
}
To allow semi-colons (eg, atexit "echo foo;"
) and aesthetic purity, you might like:
atexit() {
cmd="${1%;}"
eval set -- $(trap -p EXIT)
trap "$cmd${3:+; }$3" EXIT
}
You have presented an alternative solution, but haven't reviewed the code. Please edit to show what aspects of the question code prompted you to write this version, and in what ways it's an improvement over the original. It may be worth (re-)reading How to Answer.
– Toby Speight
yesterday
add a comment |
up vote
0
down vote
Still uses eval, but it seems cleaner to do:
atexit() {
cmd="$1"
eval set -- $(trap -p EXIT)
trap "$cmd; $3" EXIT
}
To allow semi-colons (eg, atexit "echo foo;"
) and aesthetic purity, you might like:
atexit() {
cmd="${1%;}"
eval set -- $(trap -p EXIT)
trap "$cmd${3:+; }$3" EXIT
}
You have presented an alternative solution, but haven't reviewed the code. Please edit to show what aspects of the question code prompted you to write this version, and in what ways it's an improvement over the original. It may be worth (re-)reading How to Answer.
– Toby Speight
yesterday
add a comment |
up vote
0
down vote
up vote
0
down vote
Still uses eval, but it seems cleaner to do:
atexit() {
cmd="$1"
eval set -- $(trap -p EXIT)
trap "$cmd; $3" EXIT
}
To allow semi-colons (eg, atexit "echo foo;"
) and aesthetic purity, you might like:
atexit() {
cmd="${1%;}"
eval set -- $(trap -p EXIT)
trap "$cmd${3:+; }$3" EXIT
}
Still uses eval, but it seems cleaner to do:
atexit() {
cmd="$1"
eval set -- $(trap -p EXIT)
trap "$cmd; $3" EXIT
}
To allow semi-colons (eg, atexit "echo foo;"
) and aesthetic purity, you might like:
atexit() {
cmd="${1%;}"
eval set -- $(trap -p EXIT)
trap "$cmd${3:+; }$3" EXIT
}
edited Aug 29 '16 at 17:47
answered Aug 29 '16 at 17:23
William Pursell
1185
1185
You have presented an alternative solution, but haven't reviewed the code. Please edit to show what aspects of the question code prompted you to write this version, and in what ways it's an improvement over the original. It may be worth (re-)reading How to Answer.
– Toby Speight
yesterday
add a comment |
You have presented an alternative solution, but haven't reviewed the code. Please edit to show what aspects of the question code prompted you to write this version, and in what ways it's an improvement over the original. It may be worth (re-)reading How to Answer.
– Toby Speight
yesterday
You have presented an alternative solution, but haven't reviewed the code. Please edit to show what aspects of the question code prompted you to write this version, and in what ways it's an improvement over the original. It may be worth (re-)reading How to Answer.
– Toby Speight
yesterday
You have presented an alternative solution, but haven't reviewed the code. Please edit to show what aspects of the question code prompted you to write this version, and in what ways it's an improvement over the original. It may be worth (re-)reading How to Answer.
– Toby Speight
yesterday
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
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f67417%2fan-atexit-for-bash%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
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
Required, but never shown
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
Required, but never shown
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
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown