Skip to content
This repository was archived by the owner on Dec 19, 2024. It is now read-only.

Commit ef455a9

Browse files
author
Erwan Velu
committed
docker: Adding docker_exec.sh
When debugging containers, it's always a pain understanding why a fault occured. This is especially true since the last exec() call will make the container being stopped if the command fails. This commit is about creating a trick to catch errors and preventing the container from dying. This first implies adding some 'trap ERR' to catch errors but as per docker environment, PID 1 received the SIGTERM when 'docker stop' command occurs. So SIGTERM have to be forwarded to the exec'd process. The current implementation is split in two parts: - handling the ERR - handling exec + SIGTERM For the ERR, set_trap_err() does install the ERR trap and executes trap_error() if triggered. This function is just displaying information to the user and fall in sleep to keep the PID 1 alive for ever. As the container is in sleep, it is possible to spawn a new bash in it by using the 'docker exec' command. A special trick here, is that new bash will reimport the 'env' context of PID 1 by loading a modified ~/.bashrc. This file is also providing a override function of the built-in exec() call. It does install the SIGTERM trap, spawn the desired command in background and wait it to die before exiting with its return value. The spawned process is not PID 1 so the SIGTERM trap will forward it to the proper PID and then sucide itself with the appropriate return value. The beauty of that is that sourcing docker_exec.sh is enough to get all thoses features at once as this script is executing set_trap_err() by default and overrides the exec() built-in function. A typical usage looks like : if [ "$MY_DEBUG_CONDITION" = "what_ever_you_want" ]; then source docker_exec.sh fi Note: I'm not really happy about the NOTRAP variable to disengage the 'trap ERR' but I didn't found a way to remove it from the SIGTERM trap in an efficient way :/
1 parent c6087a6 commit ef455a9

File tree

1 file changed

+63
-0
lines changed

1 file changed

+63
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
function set_trap_err {
2+
# Let's propagate traps to all functions
3+
set -E
4+
5+
# Let's call trap_error if we catch an ERR
6+
trap 'trap_error' ERR
7+
}
8+
9+
NOTRAP=
10+
function trap_error {
11+
set +x
12+
if [ -z "$NOTRAP" ]; then
13+
echo "An issue occured and you asked me to stay alive."
14+
echo "You can connect to me with: sudo docker exec -i -t $HOSTNAME /bin/bash"
15+
echo "The current environment variables will be reloaded by this bash to be in a similar context."
16+
echo "When debugging is over stop me with: pkill sleep"
17+
echo "I'll sleep for 365 days waiting for you darling, bye bye"
18+
19+
# exporting current environement so the next bash will be in the same setup
20+
for value in $(env); do
21+
echo "export $value" >> /root/.bashrc
22+
done
23+
24+
sleep 365d
25+
else
26+
# If NOTRAP is defined, we need to return true to avoid triggering an ERR
27+
true
28+
fi
29+
}
30+
31+
child_for_exec=1
32+
function _term {
33+
echo "Sending SIGTERM to PID $child_for_exec"
34+
35+
# Disabling the ERR trap before killing the process
36+
# That's an expected failure so don't handle it
37+
# Doing "trap ERR" or "trap - ERR" didn't worked :/
38+
NOTRAP="yes"
39+
40+
kill -TERM "$child_for_exec" 2>/dev/null
41+
}
42+
43+
function exec {
44+
# This function overrides the built-in exec() call
45+
# It starts the process in background to catch ERR but
46+
# as per docker requirement, forward the SIGTERM to it.
47+
trap _term SIGTERM
48+
49+
$@ &
50+
child_for_exec=$!
51+
echo "exec: PID $child_for_exec: spawning $@"
52+
wait "$child_for_exec"
53+
return_code=$?
54+
echo "exec: PID $child_for_exec: exit $return_code"
55+
exit $return_code
56+
}
57+
58+
########
59+
# Main #
60+
########
61+
# Let's engage set_trap_err
62+
# and override the default exec() built-in
63+
set_trap_err

0 commit comments

Comments
 (0)