Gcore: Generating Non-Destructive Core Dumps, Capturing Live Process Memory Snapshots, and Triaging Ephemeral Deadlocks in Production
Every system administrator recognises the immediate urge of that moment: restart the service, clear the bottleneck, go back to sleep, and hope it was a one-off glitch. But deep down, you know the cost. If you restart the server, you wipe the slate clean, destroying the volatile memory state and execution stacks that hold the only clues to why the failure occurred. You destroy the crime scene just to clear the road. Conversely, if you leave the service frozen while you attach an interactive debugger to inspect it, the outage drags on, active connections drop, and customer frustration mounts.
The Linux gcore(1) command resolves this operational dilemma. Think of it as a high-speed forensic camera for running software. It temporarily freezes a target application for a fraction of a second, takes an exact, byte-for-byte snapshot of its entire memory space, CPU registers, and thread states, writes that snapshot safely to disk, and immediately lets the program resume runningβall without terminating the process or dropping active user network connections.
To capture an immediate, non-destructive memory snapshot of a troubled application (for example, a process running under process ID 4192), you only need a single command:
# Capture an immediate memory dump with a custom output prefix
sudo gcore -o /var/dumps/snapshot_daemon 4192
Within a few hundred milliseconds, gcore writes a complete snapshot file to /var/dumps/snapshot_daemon.4192 and detaches cleanly. The live service continues processing traffic, while you can copy the dump file to an offline workstation and calmly dissect the root cause using standard debugging tools over a cup of coffee.
What It Does in Plain English
In standard Linux operations, a "core dump" is a digital autopsy. When a program encounters a catastrophic errorβsuch as trying to read memory it does not ownβthe operating system terminates the program immediately and dumps its entire memory contents to a file on disk so developers can inspect what went wrong. The drawback is fatal: by the time you get the file, the program is already dead, and all active user connections are severed.
The gcore utility changes this dynamic entirely by providing an in situ, non-destructive core dump. Rather than waiting for a fatal crash, you invoke gcore against a healthy or hung process while it is still running. The utility momentarily pauses the application's threads, writes an exact copy of its heap allocations, thread execution stacks, and processor register values into a standard Executable and Linkable Format (ELF) core file, and immediately resumes the process. This allows teams to extract complete diagnostic images from production environments without causing downtime or disturbing live network traffic.
How It Works Under the Hood
To understand why gcore is so effective, it helps to contrast its userspace mechanism with traditional kernel-level crash dumping.
When a program experiences a fatal segmentation fault (SIGSEGV) or abort signal (SIGABRT), the Linux kernel takes control. The kernel halts the process permanently, traverses its internal memory structures (mm_struct), streams the memory contents to disk according to the system's /proc/sys/kernel/core_pattern, and closes all network sockets and file descriptors. The application ceases to exist.
In contrast, gcore operates in userspace as a specialised interface leveraging the GNU Debugger (gdb(1)) engine and the Linux process trace (ptrace(2)) system call.
The Virtual Memory Traversal and Serialization Lifecycle
- Process Seizure via
ptrace: When invoked,gcoreattaches to all lightweight processes (kernel threads) belonging to the target process usingptrace(PTRACE_ATTACH, pid, ...)orptrace(PTRACE_SEIZE, pid, ...). The Linux kernel transitions each thread into a paused state (TASK_TRACED), halting the progression of instruction pointers while preserving the exact CPU register states (including%rip,%rsp, and general-purpose registers). - Address Space Mapping Introspection: Once the application is paused,
gcorereads the process's virtual memory layout via the/proc/[pid]/mapsand/proc/[pid]/smapspseudo-filesystem interfaces. These files provide a detailed roadmap of every contiguous Virtual Memory Area (VMA), listing read, write, and execute permissions (rwxsp) along with links to loaded shared libraries (.sofiles). - Application of Memory Dumping Filters: The utility cross-references mapped memory areas against the process's
/proc/[pid]/coredump_filterconfiguration bitmask. This allows the system to omit unnecessary data (such as read-only shared library code) and capture only the essential dynamic memory, drastically reducing write time. - ELF Segment Construction (
PT_NOTEandPT_LOAD): -gcorebuilds a standard ELF header structure (Elf64_Ehdr), tagging the file asET_CORE. - It synthesises a diagnosticPT_NOTEsegment containing structured metadata: thread execution registers (NT_PRSTATUS), command-line arguments and process status (NT_PRPSINFO), runtime linker configurations (NT_AUXV), and mapped file locations (NT_FILE). - Selected memory pages are grouped intoPT_LOADsegments.gcorereads the raw byte payloads directly from the process memory device (/proc/[pid]/mem) or viaprocess_vm_readv(2)calls and writes them sequentially to disk. - Clean Detachment and State Resumption: Once the memory data is safely recorded,
gcoreissuesptrace(PTRACE_DETACH, pid, ...). The kernel immediately restores all threads to theTASK_RUNNINGstate. The application picks up execution at the exact instruction where it was paused, with all TCP sockets, database connections, and file handles completely intact.
Kernel Memory Dumping Filtering Mechanics
The physical size of the snapshot generated by gcore is controlled by the bitmask residing at /proc/[pid]/coredump_filter. Defined in core(5), this bitmask specifies which types of memory mappings should be included in the dump file:
| Bit Position | Hex Mask | Memory Segment Classification Filtered |
|---|---|---|
| Bit 0 | 0x01 |
Anonymous private memory regions (heap allocations, malloc, standard variables). |
| Bit 1 | 0x02 |
Anonymous shared memory regions (mmap with shared flags). |
| Bit 2 | 0x04 |
File-backed private memory regions (copy-on-write mappings). |
| Bit 3 | 0x08 |
File-backed shared memory regions (shared memory blocks, mapped database files). |
| Bit 4 | 0x10 |
ELF header pages of binary files and mapped dynamic libraries. |
| Bit 5 | 0x20 |
Private Direct Access (DAX) pages. |
| Bit 6 | 0x40 |
Shared Direct Access (DAX) pages. |
| Bit 7 | 0x80 |
Private huge pages (Transparent Huge Pages / THP). |
| Bit 8 | 0x100 |
Shared huge pages (hugetlbfs). |
The default Linux kernel bitmask is typically 0x33 (bits 0, 1, 4, and 5 enabled), which captures anonymous private memory, anonymous shared memory, binary ELF headers, and private DAX memory.
Core Flags and Quick Start
The invocation syntax for gcore is straightforward:
-o <prefix>: Specifies the custom file path prefix for the output file. The process ID (<pid>) is automatically appended as a suffix.-a: Dumps all virtual memory mappings, bypassing the/proc/[pid]/coredump_filtersettings to capture everything, including shared read-only code segments.<pid>: Specifies the process ID (or list of IDs) to capture.
Quick Start: Basic Process Snapshot
To capture an immediate memory snapshot of a background process with PID 4192:
# Capture an immediate memory dump with a custom output prefix
sudo gcore -o /var/dumps/snapshot_daemon 4192
Realistic Terminal Output:
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
0x00007f8b9a3e21a7 in __futex_abstimed_wait_common64 () from /lib/x86_64-linux-gnu/libc.so.6
Saved corefile /var/dumps/snapshot_daemon.4192
[Inferior 1 (process 4192) detached]
Line-by-Line Explanation:
1. [Thread debugging using libthread_db enabled]: gcore connects to the Linux thread library to discover and index all running threads inside the target process.
2. 0x00007f8b9a3e21a7 in __futex_abstimed_wait_common64 (): Shows the current instruction executed by the main thread at the moment of capture (here waiting on a system futex lock).
3. Saved corefile /var/dumps/snapshot_daemon.4192: Confirms the binary core dump file has been successfully written to disk.
4. [Inferior 1 (process 4192) detached]: Confirms the debugger has released its hold, allowing the application to resume execution without interruption.
Five Production-Grade Real-World Use Cases
The following five practical implementations demonstrate how gcore is used in mission-critical and high-availability enterprise environments.
Use Case 1: Capturing a Snapshot of a Hung Database Without Dropping Active TCP Connections
Scenario
A high-concurrency database daemon (PID 18492) with over 3,000 active client connections encounters internal lock contention. Queries have stopped processing, but restarting the daemon would drop all open connections, triggering connection storms and service outages across the entire web tier. We need to capture the process state while verifying that client network sockets remain open.
Execution Command
# Execute gcore while capturing real-time telemetry of socket persistence
sudo gcore -o /var/log/dumps/db_hung_state 18492 && \
sudo ss -tp | grep 18492 | head -n 5
Realistic Terminal Output
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
[New Thread 0x7f10b2ffd700 (LWP 18493)]
[New Thread 0x7f10b27fc700 (LWP 18494)]
[New Thread 0x7f10b1ffb700 (LWP 18495)]
0x00007f10b401289c in pthread_rwlock_wrlock () from /lib/x86_64-linux-gnu/libc.so.6
Saved corefile /var/log/dumps/db_hung_state.18492
[Inferior 1 (process 18492) detached]
ESTAB 0 0 10.0.1.15:3306 10.0.2.84:51240 users:(("dbdaemon",pid=18492,fd=42))
ESTAB 0 0 10.0.1.15:3306 10.0.2.85:51242 users:(("dbdaemon",pid=18492,fd=43))
ESTAB 0 0 10.0.1.15:3306 10.0.2.86:51244 users:(("dbdaemon",pid=18492,fd=44))
ESTAB 0 0 10.0.1.15:3306 10.0.2.87:51246 users:(("dbdaemon",pid=18492,fd=45))
ESTAB 0 0 10.0.1.15:3306 10.0.2.88:51248 users:(("dbdaemon",pid=18492,fd=46))
Line-by-Line Explanation
[New Thread ... (LWP 18493)]:gcorepauses and enumerates all secondary worker threads.0x00007f10b401289c in pthread_rwlock_wrlock (): Identifies that the main thread was waiting to acquire a read-write lock when captured.Saved corefile ...: Confirms the binary core file has been saved.[Inferior 1 ... detached]: Confirms the target process was safely released and returned to running state.ESTAB ... users:(("dbdaemon",pid=18492,fd=42)): The subsequent socket check proves that all TCP connections remained in theESTABLISHEDstate without any connection resets (RST).
What the Admin Does Next
Copy the dump file /var/log/dumps/db_hung_state.18492 to a development machine with matching debug symbols and generate a full thread stack trace:
gdb /usr/sbin/dbdaemon /var/log/dumps/db_hung_state.18492 -ex "thread apply all bt" -ex "quit" > thread_traces.log
Use Case 2: Automating Threshold-Triggered Dumps Before the Linux OOM Killer Strikes
Scenario
A background worker process suffers from an intermittent memory leak. When physical memory is exhausted, the Linux Out-Of-Memory (OOM) killer terminates the process abruptly with a fatal SIGKILL (kill -9), leaving no crash logs behind. We deploy an automated watchdog script that monitors the process's Resident Set Size (RSS) and triggers gcore when memory usage exceeds an 85% safety threshold, securing a full memory snapshot before an ungraceful crash occurs.
Execution Script
#!/usr/bin/env bash
set -euo pipefail
TARGET_PID="$(pgrep -f "worker_processor")"
MEMORY_THRESHOLD_PAGES=2097152 # 8 GiB in 4 KiB memory pages
CORE_OUTPUT_DIR="/var/dumps/oom_prevention"
mkdir -p "${CORE_OUTPUT_DIR}"
while kill -0 "${TARGET_PID}" 2>/dev/null; do
# Extract Resident Set Size (RSS) pages from /proc/[pid]/statm (Field 2)
CURRENT_RSS_PAGES="$(awk '{print $2}' "/proc/${TARGET_PID}/statm")"
if [ "${CURRENT_RSS_PAGES}" -gt "${MEMORY_THRESHOLD_PAGES}" ]; then
echo "[ALERT] Process ${TARGET_PID} exceeded threshold (${CURRENT_RSS_PAGES} pages). Generating emergency gcore..."
# Enforce private memory filtering to maximize snapshot speed
echo 0x01 > "/proc/${TARGET_PID}/coredump_filter"
# Execute gcore
gcore -o "${CORE_OUTPUT_DIR}/oom_snapshot_${TARGET_PID}" "${TARGET_PID}"
echo "[SUCCESS] Emergency snapshot generated. Terminating process safely."
kill -15 "${TARGET_PID}"
break
fi
sleep 0.5
done
Realistic Terminal Output
[ALERT] Process 31082 exceeded threshold (2148900 pages). Generating emergency gcore...
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
0x00007f90e11894b4 in __GI___libc_malloc (bytes=1048576) at malloc.c:3078
Saved corefile /var/dumps/oom_prevention/oom_snapshot_31082.31082
[Inferior 1 (process 31082) detached]
[SUCCESS] Emergency snapshot generated. Terminating process safely.
Line-by-Line Explanation
CURRENT_RSS_PAGES="$(awk '{print $2}' "/proc/${TARGET_PID}/statm")": Reads the active physical memory page count from the process status file.echo 0x01 > "/proc/${TARGET_PID}/coredump_filter": Limits the dump strictly to anonymous private memory, skipping read-only library mappings to make the dump as fast as possible.0x00007f90e11894b4 in __GI___libc_malloc: Shows that the application was actively allocating a 1 MiB chunk viamallocwhen captured.kill -15 "${TARGET_PID}": Sends a cleanSIGTERMsignal, allowing the application to shut down gracefully and flush its remaining work.
What the Admin Does Next
Inspect the captured heap state using GDB equipped with heap-profiling plugins to trace which data structures leaked memory:
gdb /opt/worker/bin/worker_processor /var/dumps/oom_prevention/oom_snapshot_31082.31082
Use Case 3: Applying Selective Memory Filtering to Exclude Massive Shared Memory Caches
Scenario
A high-frequency trading engine (PID 9102) uses a 128 GiB shared memory cache (/dev/shm/orderbook_matrix.mmap). Dumping the entire 128 GiB space would take 40 seconds over disk storage, freezing the trading engine and violating strict latency service-level agreements. By tuning the coredump_filter bitmask immediately before invocation, we exclude shared memory mappings (0x02 and 0x08) and capture only private application heap and stack memory (0x01), reducing the dump size from 130 GiB to 180 MiB and completing the operation in under 300 milliseconds.
Execution Command
# Verify initial coredump_filter, apply anonymous private filter, execute gcore, and restore filter
ORIGINAL_FILTER="$(cat /proc/9102/coredump_filter)" && \
echo "Original Filter: 0x${ORIGINAL_FILTER}" && \
echo 0x01 > /proc/9102/coredump_filter && \
echo "Modified Filter: 0x$(cat /proc/9102/coredump_filter)" && \
time sudo gcore -o /tmp/fast_trading_core 9102 && \
echo "${ORIGINAL_FILTER}" > /proc/9102/coredump_filter
Realistic Terminal Output
Original Filter: 0x00000033
Modified Filter: 0x00000001
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
0x00007f3b890a12e8 in epoll_wait () from /lib/x86_64-linux-gnu/libc.so.6
Saved corefile /tmp/fast_trading_core.9102
[Inferior 1 (process 9102) detached]
real 0m0.284s
user 0m0.042s
sys 0m0.241s
Line-by-Line Explanation
ORIGINAL_FILTER="$(cat /proc/9102/coredump_filter)": Stores the default filter setting (0x33) for safe restoration later.echo 0x01 > /proc/9102/coredump_filter: Overwrites the bitmask to filter out all shared memory regions, retaining only private heap and execution stacks.time sudo gcore ...: Measures the exact execution duration of the command.real 0m0.284s: Confirms the entire pause-and-capture cycle finished in just 284 milliseconds.echo "${ORIGINAL_FILTER}" > ...: Restores the system's original debugging settings.
What the Admin Does Next
Verify that the output file contains the necessary thread states while successfully omitting the multi-gigabyte shared memory segments using readelf:
readelf -l /tmp/fast_trading_core.9102 | grep -A 2 LOAD
Use Case 4: Diagnosing Multi-Threaded Deadlocks Offline with GDB Batch Mode
Scenario
An order processing service (PID 5541) experiences sudden transaction starvation while CPU usage drops to zero. Developers suspect a classic circular wait deadlock between two worker threads competing for two mutex locks (mutex_a and mutex_b). We extract an instantaneous snapshot using gcore and immediately parse the call stacks offline using GDB in automated batch mode.
Execution Command
# Capture the snapshot and execute automated non-interactive GDB analysis
sudo gcore -o /var/dumps/deadlock_investigation 5541 && \
gdb --batch \
--core=/var/dumps/deadlock_investigation.5541 \
--eval-command="info threads" \
--eval-command="thread apply all bt 5"
Realistic Terminal Output
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
0x00007fa12c980306 in futex_wait () from /lib/x86_64-linux-gnu/libc.so.6
Saved corefile /var/dumps/deadlock_investigation.5541
[Inferior 1 (process 5541) detached]
[New LWP 5541]
[New LWP 5542]
Id Target Id Frame
* 1 LWP 5541 0x00007fa12c980306 in futex_wait () from /lib/x86_64-linux-gnu/libc.so.6
2 LWP 5542 0x00007fa12c980306 in futex_wait () from /lib/x86_64-linux-gnu/libc.so.6
Thread 2 (LWP 5542):
#0 0x00007fa12c980306 in futex_wait () from /lib/x86_64-linux-gnu/libc.so.6
#1 0x00007fa12c984218 in __pthread_mutex_lock_wait (mutex=0x55d8e2098040 <mutex_b>) at mutex.c:115
#2 0x000055d8e1f02194 in process_order_b () at /opt/src/order.c:89
#3 0x00007fa12ca01609 in start_thread (arg=<optimized out>) at pthread_create.c:477
Thread 1 (LWP 5541):
#0 0x00007fa12c980306 in futex_wait () from /lib/x86_64-linux-gnu/libc.so.6
#1 0x00007fa12c984218 in __pthread_mutex_lock_wait (mutex=0x55d8e2098000 <mutex_a>) at mutex.c:115
#2 0x000055d8e1f01f82 in process_order_a () at /opt/src/order.c:45
#3 0x000055d8e1f0250a in main (argc=1, argv=0x7ffe9a8a18a8) at /opt/src/main.c:120
Line-by-Line Explanation
Id Target Id Frame: Lists the two active kernel threads captured in the core file notes.Thread 2 (LWP 5542): Frame#1shows Thread 2 is blocked infutex_waitwaiting to acquiremutex_bat address0x55d8e2098040.Thread 1 (LWP 5541): Frame#1shows Thread 1 is blocked infutex_waitwaiting to acquiremutex_aat address0x55d8e2098000.- The backtrace provides clear evidence of a circular deadlock: Thread 1 holds
mutex_bwhile waiting formutex_a, whereas Thread 2 holdsmutex_awhile waiting formutex_b.
What the Admin Does Next
Inspect the mutex objects in GDB to confirm the specific thread ownership IDs and notify the development team to enforce consistent lock ordering in code:
gdb --batch --core=/var/dumps/deadlock_investigation.5541 \
-ex "print *(pthread_mutex_t*)0x55d8e2098040" \
-ex "print *(pthread_mutex_t*)0x55d8e2098000"
Use Case 5: Streaming Compressed Snapshots from Containerized Services to Remote Storage
Scenario
A microservice running inside a Kubernetes container encounters memory corruption. The container has a read-only root filesystem (readOnlyRootFilesystem: true) and only 500 MiB of local ephemeral storage, making it impossible to write a 4 GiB core dump locally without triggering an out-of-disk error (ENOSPC). By targeting the container's host PID, we stream the output through a Named Pipe (FIFO) into a high-speed compression pipeline (zstd) and transfer it directly to a remote diagnostic server over SSH.
Execution Pipeline
#!/usr/bin/env bash
set -euo pipefail
# Discover the global host PID for a container named 'payment-processor'
CONTAINER_ID="$(docker ps -q -f "name=payment-processor")"
HOST_PID="$(docker inspect --format '{{ .State.Pid }}' "${CONTAINER_ID}")"
REMOTE_STORAGE_HOST="diag-storage.internal.infra"
DUMP_TIMESTAMP="$(date +%s)"
TARGET_FILE="core_payment_${CONTAINER_ID}_${DUMP_TIMESTAMP}.zst"
echo "[INFO] Targeting Container ${CONTAINER_ID} via Host PID ${HOST_PID}"
# Create a temporary Named Pipe (FIFO) in memory
FIFO_PIPE="/tmp/gcore_stream_${HOST_PID}.fifo"
rm -f "${FIFO_PIPE}"
mkfifo "${FIFO_PIPE}"
# Start background compression and network streaming pipeline
zstd -3 -T0 < "${FIFO_PIPE}" | ssh -o Compression=no "dumpuser@${REMOTE_STORAGE_HOST}" \
"cat > /storage/cores/${TARGET_FILE}" &
PIPELINE_PID=$!
# Run gcore directed into the named pipe
sudo gcore -o "/tmp/gcore_stream_${HOST_PID}.fifo" "${HOST_PID}" > /dev/null
# Clean up resources
wait "${PIPELINE_PID}"
rm -f "${FIFO_PIPE}"
echo "[SUCCESS] Successfully streamed compressed core to ${REMOTE_STORAGE_HOST}:/storage/cores/${TARGET_FILE}"
Realistic Terminal Output
[INFO] Targeting Container c84f8812a10e via Host PID 44109
[SUCCESS] Successfully streamed compressed core to diag-storage.internal.infra:/storage/cores/core_payment_c84f8812a10e_1718874163.zst
Line-by-Line Explanation
HOST_PID="$(docker inspect ...)": Finds the host-level process ID for the container, allowing host-level debugging tools to interact across container boundaries.mkfifo "${FIFO_PIPE}": Creates a First-In, First-Out memory buffer, ensuring no uncompressed data touches the local disk.zstd -3 -T0 < "${FIFO_PIPE}" | ssh ...: Reads bytes directly from the FIFO, compresses them using all available CPU cores (-T0), and streams the archive over SSH.sudo gcore -o ...: Instructsgcoreto write directly into the pipe buffer, bypassing local disk storage completely.
What the Admin Does Next
Decompress the diagnostic file on the storage server and load it alongside the container's debug symbols in GDB:
zstd -d /storage/cores/core_payment_c84f8812a10e_1718874163.zst -o /tmp/uncompressed_core.44109
gdb /opt/app/payment-processor /tmp/uncompressed_core.44109
What Can Go Wrong: Operational Pitfalls and Prevention
While gcore is non-destructive, taking a live memory dump of a busy production system requires careful management of system resources.
| Operational Threat | Root Cause | Recommended Remediation Strategy |
|---|---|---|
| Application Latency Spikes / Timeouts | Prolonged ptrace freeze during heavy disk I/O writes. |
Set coredump_filter to 0x01; dump directly to tmpfs (/dev/shm). |
Disk Space Exhaustion (ENOSPC) |
Core dump size exceeds remaining filesystem capacity. | Run automated pre-flight disk capacity checks; stream via FIFO. |
| Sensitive Data Exposure | Plaintext credentials or tokens stored in unencrypted dumps. | Enforce 0600 file permissions; encrypt dump files with GPG. |
1. Process Latency Spikes and ptrace Stalls
The Risk: When gcore attaches to a target process, the kernel pauses every thread. If the application has hundreds of gigabytes of heap memory and the output is directed to a slow disk array, the freeze can last several seconds. During this window, the application cannot respond to network heartbeats or health probes, which can cause load balancers to mark the instance as dead and trigger accidental failovers.
The Solution:
* Exclude large shared memory segments by setting /proc/[pid]/coredump_filter to 0x01.
* Direct the dump to a memory-backed filesystem (tmpfs) like /dev/shm, writing at RAM bandwidth speeds (10β50 GB/s) rather than disk speeds.
# Verify available space in RAM disk and dump directly to /dev/shm
df -h /dev/shm
sudo gcore -o /dev/shm/ephemeral_fast_dump $TARGET_PID
2. Cascading Storage Depletion (Disk Full ENOSPC)
The Risk: Taking a core dump of a large memory-heavy application (such as Redis or Elasticsearch) onto the root (/) or logging (/var/log) partition can instantly consume all free disk space, crashing adjacent services and halting system logging.
The Solution: Use a pre-flight verification script to check the process's Virtual Memory Size (VmSize) against available disk space before initiating the dump:
# Pre-flight disk verification script
SAFE_TARGET_PID=1234
REQUIRED_KB="$(awk '/VmSize/{print $2}' "/proc/${SAFE_TARGET_PID}/status")"
AVAILABLE_KB="$(df --output=avail -k /var/dumps | tail -n 1)"
if [ "${AVAILABLE_KB}" -lt "${REQUIRED_KB}" ]; then
echo "[ERROR] Insufficient disk space! Required: ${REQUIRED_KB} KB, Available: ${AVAILABLE_KB} KB" >&2
exit 1
fi
sudo gcore -o /var/dumps/safe_core "${SAFE_TARGET_PID}"
3. Exposure of Sensitive Data in Plaintext
The Risk: Memory dumps contain complete images of runtime memory, including plaintext database passwords, API keys, private cryptographic keys, and customer records. Leaving world-readable core files in public directories like /tmp can lead to severe security compliance violations.
The Solution: Restrict directory permissions before dumping and encrypt diagnostic artifacts immediately:
# Dump inside a restricted directory with 0700 permissions
mkdir -m 0700 /var/dumps/secure_zone
sudo gcore -o /var/dumps/secure_zone/sec_dump 5678
sudo chmod 0600 /var/dumps/secure_zone/sec_dump.*
Today's Takeaway
The gcore utility bridges the gap between deep forensic post-mortem analysis and 24/7 service availability, letting you capture live memory states without taking production offline. To see it in action on your own machine in the next five minutes, start a simple background task with sleep 1000 &, take a non-destructive snapshot using sudo gcore -o /tmp/sleep_test $!, inspect the generated ELF structure with readelf -h /tmp/sleep_test.$!, and run ps aux | grep sleep to confirm that your original program continues running happily in the background.
Authoritative Technical References
- Linux Manual Pages:
gcore(1)β Generate a Core File of a Running Process - Linux Manual Pages:
ptrace(2)β Process Trace System Calls - Linux Manual Pages:
core(5)β Core Dump File Formats and Filter Bitmasks - Linux Manual Pages:
proc(5)β Process Information Pseudo-Filesystem Architecture - GNU Project: GDB Documentation on Offline Core File Generation
- ArchWiki: Advanced Core Dump Debugging and Analysis Methodologies