├── .github
└── FUNDING.yml
├── .travis.yml
├── LICENSE
├── README.md
├── etc
└── init.d
│ └── strace-docker
├── extract
├── install
└── strace-docker
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | github: amrabed
2 | patreon: amrabed
3 | custom: ["https://paypal.me/AmrAbed"]
4 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: bash
2 |
3 | install: sudo ./install
4 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2018 Amr Abed
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | [](https://travis-ci.org/amrabed/strace-docker)
2 | [](https://github.com/amrabed/strace-docker/issues)
3 | [](https://github.com/amrabed/strace-docker/releases)
4 | [](LICENSE)
5 |
6 | # strace-docker
7 | Trace system calls from Docker containers running on the system*
8 |
9 |
10 | ## Usage
11 | ### Install
12 | git clone https://github.com/amrabed/strace-docker && sudo ./strace-docker/install
13 |
14 | To check if `strace-docker` is successfully installed and running, use `service strace-docker status`
15 |
16 | ### Tracing
17 | `strace-docker` is automatically triggered by [`docker events`](https://docs.docker.com/engine/reference/commandline/events) to monitor any new Docker container. The resulting trace of system calls is written to a new file at `/var/log/strace-docker/`. File name will be `$id-$image-$timestamp` where `$id` is the container ID, `$image` is the container image, and `$timestamp` is the time the container started. You can see full log of monitored containers at `/var/log/strace-docker/log`.
18 |
19 | [](https://www.youtube.com/watch?v=iWywV_4Y34E)
20 |
21 |
22 | ## Known Issues
23 | - `strace-docker` does not currently stop tracing process automatically when container is stopped.
24 | - `strace-docker` does not resume tracing to the same file on container restart.
25 | - `strace-docker` relies internally on [`Sysdig`](https://sysdig.com) which limits the number of monitoring processes to 5 by default. Due to `strace-docker` not killing/stopping monitoring processes automatically, `strace-docker` stops montioring new containers when 5 containrs are currently monitored. The user then needs to manually stop any `strace-docker` processes that are no longer needed (i.e., whose containers are not running anymore).
26 |
27 | All contributions are welcome :)
28 |
29 |
30 | Implemented as part of my Ph.D. dissertation research. See [this paper](https://arxiv.org/abs/1611.03056) for more details
31 |
--------------------------------------------------------------------------------
/etc/init.d/strace-docker:
--------------------------------------------------------------------------------
1 | #! /bin/sh
2 | ### BEGIN INIT INFO
3 | # Provides: skeleton
4 | # Required-Start: $remote_fs $syslog
5 | # Required-Stop: $remote_fs $syslog
6 | # Default-Start: 2 3 4 5
7 | # Default-Stop: 0 1 6
8 | # Short-Description: Run strace on any running Docker container
9 | ### END INIT INFO
10 |
11 | # Author: Amr Abed
12 |
13 | NAME=strace-docker
14 | DAEMON=/usr/bin/$NAME
15 | #DAEMON_ARGS="--options args"
16 | PIDFILE=/var/run/$NAME.pid
17 | SCRIPTNAME=/etc/init.d/$NAME
18 |
19 | # Exit if the package is not installed
20 | [ -x "$DAEMON" ] || exit 0
21 |
22 | # Read configuration variable file if it is present
23 | [ -r /etc/default/$NAME ] && . /etc/default/$NAME
24 |
25 | # Load the VERBOSE setting and other rcS variables
26 | # . /lib/init/vars.sh
27 |
28 | # Define LSB log_* functions.
29 | # Depend on lsb-base (>= 3.2-14) to ensure that this file is present
30 | # and status_of_proc is working.
31 | . /lib/lsb/init-functions
32 |
33 | #
34 | # Function that starts the daemon/service
35 | #
36 | do_start()
37 | {
38 | # Return
39 | # 0 if daemon has been started
40 | # 1 if daemon was already running
41 | # 2 if daemon could not be started
42 | start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON --test > /dev/null \
43 | || return 1
44 | start-stop-daemon --start --quiet --background --make-pidfile --pidfile $PIDFILE --exec $DAEMON -- $DAEMON_ARGS \
45 | || return 2
46 | # Add code here, if necessary, that waits for the process to be ready
47 | # to handle requests from services started subsequently which depend
48 | # on this one. As a last resort, sleep for some time.
49 | }
50 |
51 | #
52 | # Function that stops the daemon/service
53 | #
54 | do_stop()
55 | {
56 | # Kill children first (not killed by start-stop-daemon)
57 | pkill -P $(cat $PIDFILE)
58 | # Return
59 | # 0 if daemon has been stopped
60 | # 1 if daemon was already stopped
61 | # 2 if daemon could not be stopped
62 | # other if a failure occurred
63 | start-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 --pidfile $PIDFILE --name $NAME
64 | RETVAL="$?"
65 | [ "$RETVAL" = 2 ] && return 2
66 | # Wait for children to finish too if this is a daemon that forks
67 | # and if the daemon is only ever run from this initscript.
68 | # If the above conditions are not satisfied then add some other code
69 | # that waits for the process to drop all resources that could be
70 | # needed by services started subsequently. A last resort is to
71 | # sleep for some time.
72 | start-stop-daemon --stop --quiet --oknodo --retry=0/30/KILL/5 --exec $DAEMON
73 | [ "$?" = 2 ] && return 2
74 | # Many daemons don't delete their pidfiles when they exit.
75 | rm -f $PIDFILE
76 | return "$RETVAL"
77 | }
78 |
79 | #
80 | # Function that sends a SIGHUP to the daemon/service
81 | #
82 | do_reload() {
83 | #
84 | # If the daemon can reload its configuration without
85 | # restarting (for example, when it is sent a SIGHUP),
86 | # then implement that here.
87 | #
88 | start-stop-daemon --stop --signal 1 --quiet --pidfile $PIDFILE --name $NAME
89 | return 0
90 | }
91 |
92 | case "$1" in
93 | start)
94 | [ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC" "$NAME"
95 | do_start
96 | case "$?" in
97 | 0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
98 | 2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
99 | esac
100 | ;;
101 | stop)
102 | [ "$VERBOSE" != no ] && log_daemon_msg "Stopping $DESC" "$NAME"
103 | do_stop
104 | case "$?" in
105 | 0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
106 | 2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
107 | esac
108 | ;;
109 | status)
110 | status_of_proc "$DAEMON" "$NAME" && exit 0 || exit $?
111 | ;;
112 | #reload|force-reload)
113 | #
114 | # If do_reload() is not implemented then leave this commented out
115 | # and leave 'force-reload' as an alias for 'restart'.
116 | #
117 | #log_daemon_msg "Reloading $DESC" "$NAME"
118 | #do_reload
119 | #log_end_msg $?
120 | #;;
121 | restart|force-reload)
122 | #
123 | # If the "reload" option is implemented then remove the
124 | # 'force-reload' alias
125 | #
126 | log_daemon_msg "Restarting $DESC" "$NAME"
127 | do_stop
128 | case "$?" in
129 | 0|1)
130 | do_start
131 | case "$?" in
132 | 0) log_end_msg 0 ;;
133 | 1) log_end_msg 1 ;; # Old process is still running
134 | *) log_end_msg 1 ;; # Failed to start
135 | esac
136 | ;;
137 | *)
138 | # Failed to stop
139 | log_end_msg 1
140 | ;;
141 | esac
142 | ;;
143 | *)
144 | #echo "Usage: $SCRIPTNAME {start|stop|restart|reload|force-reload}" >&2
145 | echo "Usage: $SCRIPTNAME {start|stop|status|restart|force-reload}" >&2
146 | exit 3
147 | ;;
148 | esac
149 |
150 | :
151 |
--------------------------------------------------------------------------------
/extract:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | INPUT=./data
4 | OUTPUT=../output
5 |
6 | cd $INPUT
7 |
8 | [ -d $OUTPUT ] && rm -r $OUTPUT
9 |
10 | mkdir $OUTPUT
11 |
12 | for file in *; do
13 | [ $file == log ] && continue
14 | echo -n Extracting data from $file ...
15 | gawk '1{p=1} /% time/{p=0} p{match($2, "[a-z_]+", a)}{if(a[0]) print a[0]}' $file > $OUTPUT/"$file"_trace
16 | gawk -v n=$(($(wc -l < $file) - 1)) '/% time/{l=NR} l && NR>=l+2 && NR $OUTPUT/"$file"_count
17 | echo " done"
18 | done
19 |
--------------------------------------------------------------------------------
/install:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | cd "$(dirname "$0")"
4 |
5 | # Install inotifywait
6 | if ! type inotifywait > /dev/null; then
7 | apt-get install -y inotify-tools
8 | fi
9 |
10 | # Install Docker
11 | if ! type docker > /dev/null; then
12 | wget -qO- https://get.docker.com/ | sh && usermod -aG docker $USER
13 | fi
14 |
15 | # Install Gawk
16 | if ! type gawk > /dev/null; then
17 | apt-get install -y gawk
18 | fi
19 |
20 | # Install Sysdig
21 | if ! type sysdig > /dev/null; then
22 | curl -s https://s3.amazonaws.com/download.draios.com/stable/install-sysdig | bash
23 | fi
24 |
25 | cp strace-docker /usr/bin
26 | cp etc/init.d/strace-docker /etc/init.d
27 | update-rc.d strace-docker defaults
28 | service strace-docker start
29 |
30 |
--------------------------------------------------------------------------------
/strace-docker:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | #
3 | # This script runs strace on any newly-started Docker container
4 | #
5 | # Written by Amr S. Abed
6 | #
7 | # Last updated June 8, 2015
8 |
9 | cd "$(dirname "$0")"
10 |
11 | WORKDIR=/var/log/strace-docker
12 |
13 | [ ! -d $WORKDIR ] && mkdir $WORKDIR
14 |
15 | cd $WORKDIR && touch log
16 |
17 | docker events -f event=start >> log &
18 |
19 | while inotifywait -qq -e modify log; do
20 | new_line=$(tail -1 log)
21 | timestamp=$(echo $new_line | gawk '{tmp=substr($1, 0, 19)}{gsub(/:|-|T/,"",tmp)}{print tmp}')
22 | id=$(echo $new_line | gawk '{print substr($4, 0, 12)}')
23 | image=$(echo $new_line | gawk '{match($0, "image=([a-z/]+)", a)}{gsub(/\//, "_", a[1])}{print a[1]}')
24 | out_file=$id-$image-$timestamp
25 | sysdig -p"%thread.tid %evt.type" container.id=$id and evt.type!=switch > $out_file &
26 | done
27 |
--------------------------------------------------------------------------------