Inspecting a live Ruby process
How to get a backtrace from a running Ruby process:
TL;DR to get the backtrace of a live process (sudo required):
# First, find out the PID of your Ruby process (e.g. passenger-status) $ sudo gdb -p PID (gdb) generate-core-file # generate a core.PID file for later inspection (gdb) t a a bt # thread apply all backtrace (gdb) call (void) close(1) # close the existing file descriptors for stdout (gdb) call (void) close(2) # close the existing file descriptors for stderr (gdb) shell tty # we need to figure out the device name for the current TTY: /dev/pts/X # X is an integer, adjust for your shell (gdb) call (int) open("/dev/pts/X", 2, 0) # attach stdout to current TTY (gdb) call (int) open("/dev/pts/X", 2, 0) # attach stderr to current TTY call (void) rb_backtrace() # print the Ruby backtrace to the current shell (gdb) detach # detach from the Ruby process (PID) (gdb) quit # exit gdb
- You are irreversibly redirecting STDOUT/STDERR of a running process. Restart the ruby process after you are done!
- While the above worked like a charm locally, we were not able to attach STDOUT/STDERR to the current TTY of a remote passenger worker. Please update the card accordingly if you solve that issue.
- If your server is running passenger enterprise, rather use that tool to inspect your process.
You can use the core-file for an inspection that is not attached to the live process:
$ gdb ruby core.PID