Compile and execute code in the course Docker sandbox
Executes code files in an isolated Docker sandbox with compilation, runtime analysis, and error detection.
/plugin marketplace add NathanJGaul/plugins/plugin install dev-course-builder@njg-marketplace[file] [args] - File to run and optional arguments (e.g., 'example.cpp' or 'main.rs --verbose')Compile (if needed) and execute code files within the course's isolated Docker sandbox environment.
/setup-sandbox if not)Detect the current course from the working directory or ask:
Which course sandbox should execute this code?
[1] cpp-fundamentals (course-sandbox-cpp-fundamentals)
[2] rust-intro (course-sandbox-rust-intro)
[3] Specify container name
Please select an option:
What code should be executed?
[1] Specific file (provide path)
[2] Code from current context (paste or reference)
[3] All code in current chapter/exercise
Please select an option:
Execution options:
Compiler flags: [1] Default [2] Debug (-g) [3] Optimized (-O2) [4] Custom
Timeout: [1] 10s [2] 30s [3] 60s [4] No timeout (dangerous)
Input: [1] None [2] Provide stdin [3] Input file
Please select options:
# Check if container exists and is running
container_status=$(docker inspect -f '{{.State.Running}}' course-sandbox-{course-id} 2>/dev/null)
if [ "$container_status" != "true" ]; then
echo "Container not running. Starting..."
docker start course-sandbox-{course-id}
fi
Determine the language from file extension:
| Extension | Language | Compiler/Interpreter |
|---|---|---|
.cpp, .cc, .cxx | C++ | g++ / clang++ |
.c | C | gcc / clang |
.rs | Rust | rustc / cargo |
.py | Python | python3 |
.go | Go | go run |
.java | Java | javac + java |
.js, .mjs | JavaScript | node |
.ts | TypeScript | ts-node |
For compiled languages, compile first:
C++:
docker exec course-sandbox-{course-id} \
g++ -std=c++20 -Wall -Wextra -o /tmp/prog /workspace/{file}
Rust:
docker exec course-sandbox-{course-id} \
rustc -o /tmp/prog /workspace/{file}
C:
docker exec course-sandbox-{course-id} \
gcc -std=c17 -Wall -Wextra -o /tmp/prog /workspace/{file}
Go:
docker exec course-sandbox-{course-id} \
go build -o /tmp/prog /workspace/{file}
Run with timeout to prevent infinite loops:
Compiled programs:
docker exec course-sandbox-{course-id} \
timeout {timeout}s /tmp/prog {args}
Python:
docker exec course-sandbox-{course-id} \
timeout {timeout}s python3 /workspace/{file} {args}
Node.js:
docker exec course-sandbox-{course-id} \
timeout {timeout}s node /workspace/{file} {args}
# Capture both stdout and stderr
output=$(docker exec course-sandbox-{course-id} \
timeout {timeout}s /tmp/prog 2>&1)
exit_code=$?
echo "Exit code: $exit_code"
echo "Output:"
echo "$output"
=== Running: example.cpp ===
Compiled with: g++ -std=c++20 -Wall -Wextra
--- Output ---
Hello, World!
The answer is: 42
--- Execution Summary ---
Exit code: 0
Runtime: 0.003s
=== Running: example.cpp ===
Compiling with: g++ -std=c++20 -Wall -Wextra
--- Compilation Failed ---
example.cpp:5:10: error: expected ';' after expression
int x = 5
^
;
1 error generated.
Exit code: 1
=== Running: example.cpp ===
Compiled successfully
--- Output ---
Starting program...
--- Runtime Error ---
Segmentation fault (core dumped)
Exit code: 139 (SIGSEGV)
=== Running: infinite_loop.cpp ===
Compiled successfully
--- Execution Timeout ---
Program did not complete within 10 seconds.
Possible infinite loop detected.
Exit code: 124 (TIMEOUT)
| Flag | Purpose |
|---|---|
-std=c++20 | Use C++20 standard |
-Wall -Wextra | Enable all warnings |
-Werror | Treat warnings as errors |
-g | Include debug symbols |
-O2 | Optimize for speed |
-fsanitize=address | Enable AddressSanitizer |
-fsanitize=undefined | Enable UndefinedBehaviorSanitizer |
| Flag | Purpose |
|---|---|
--edition 2021 | Use Rust 2021 edition |
-g | Include debug symbols |
-O | Optimize |
-W warnings | Enable warnings |
| Flag | Purpose |
|---|---|
-u | Unbuffered output |
-B | Don't write .pyc files |
-O | Optimize (remove asserts) |
echo "input data" | docker exec -i course-sandbox-{course-id} /tmp/prog
docker exec course-sandbox-{course-id} /tmp/prog < /workspace/input.txt
docker exec -it course-sandbox-{course-id} /tmp/prog
For debugging memory issues:
docker exec course-sandbox-{course-id} \
g++ -std=c++20 -fsanitize=address -g -o /tmp/prog /workspace/{file}
docker exec course-sandbox-{course-id} /tmp/prog
docker exec course-sandbox-{course-id} \
g++ -std=c++20 -fsanitize=undefined -g -o /tmp/prog /workspace/{file}
docker exec course-sandbox-{course-id} /tmp/prog
docker exec course-sandbox-{course-id} \
g++ -std=c++20 -fsanitize=thread -g -o /tmp/prog /workspace/{file}
docker exec course-sandbox-{course-id} /tmp/prog
docker exec course-sandbox-{course-id} \
bash -c "cd /workspace/{project-dir} && cargo run"
docker exec course-sandbox-{course-id} \
bash -c "cd /workspace/{project-dir} && cmake -B build && cmake --build build && ./build/{executable}"
Compare actual output against expected:
expected="Hello, World!"
actual=$(docker exec course-sandbox-{course-id} /tmp/prog 2>&1)
if [ "$actual" = "$expected" ]; then
echo "PASS: Output matches expected"
else
echo "FAIL: Output mismatch"
echo "Expected: $expected"
echo "Actual: $actual"
fi
| Code | Meaning |
|---|---|
| 0 | Success |
| 1 | General error |
| 124 | Timeout (killed by timeout command) |
| 126 | Permission denied |
| 127 | Command not found |
| 134 | Abort (SIGABRT) |
| 136 | Floating point exception (SIGFPE) |
| 139 | Segmentation fault (SIGSEGV) |
| 137 | Killed (SIGKILL, usually OOM) |
After execution, compiled binaries remain in /tmp inside the container. To clean up:
docker exec course-sandbox-{course-id} rm -f /tmp/prog
Or clean all temporary files:
docker exec course-sandbox-{course-id} rm -rf /tmp/*