在 Linux 上允許產生 core dump

man 5 core 上有詳細說明,踩了許多雷才發現文件有寫 …。這裡簡記一下。

測試

若執行的程式有讀 terminal input,直接輸入 ctrl + \ 送出 SIGQUIT。或用指令 kill -QUIT PID 或 kill -ABRT PID,要求程式產生 core dump,藉此測試目前的設定是否 ok。

參考《從 /proc/PID/status 了解執行中程式處理 signal 的方式》,先確認 signal handler 沒有被覆蓋掉,才可放心測試。

ulimit / setrlimit(RLIMIT_CORE, …)

Ubuntu 預設為 ulimit -c 0,表示不產生 core dump,所以要先執行 ulimit -c unlimited 允許產生 core dump。可以將這行寫到 ~/.bashrc 裡,以後就預設會產生 core dump。或在程式裡呼叫 setrlimit(RLIMIT_CORE, &limit) 也可以。若 ulimit -c unlimited 設好了,執行後還是不行,可能程式執行時又覆寫了,可以在執行程式後檢查 /proc/PID/limits,確認沒有被覆寫:

$ cat /proc/21345/limits | grep core
Max core file size unlimited unlimited bytes

如果被覆寫了,再用 gdb 設中斷點在 setrlimit 找出那段程式改了,再改回去。

/proc/sys/kernel/core_pattern

預設 core dump 的檔名可能不合使用, 參考《setting the core dump name schema》, 可用

$ echo "core.%e.%p.%t" | sudo tee /proc/sys/kernel/core_pattern

改變 core dump 的檔名, 這樣檔名會記錄是程式名稱、PID、發生的時間。在 multi-process 或 multi-thread 時特別有用。若希望每次開機都會生效, 則要在 /etc/sysctl.conf 加入 kernel.core_pattern = core.%e.%p.%t。

core pattern 可以是 “|PROGRAM”, 這樣會將 core dump 導到 PROGRAM 的標準輸入, 可以自己寫 PROGRAM 做控制。像是 core dump 太頻繁時, 取樣留下幾個就好, 以免一下就塞爆硬碟。同樣的, %e 那些參數也可以接在 PROGRAM 後當參數用, 像是 “|PROGRAM core.%e.%p.%t”, 自己的 PROGRAM 就能從 argv[1] 裡取得適合的檔名。需要特別注意的是, | 和 PROGRAM 之間不可以有空白。

裝 Ubuntu 12.04 後,/etc/sysctl.conf 的設定不會生效,查了一下發覺 apport 覆寫了 /proc/sys/kernel/core_pattern。關掉它不會有害,關掉的方法如下

$ vi /etc/default/apport  # 更新成 "enabled=0"

setuid / setgid

若確認 ulimit -c 有設好,core_pattern 沒寫到奇怪的地方 (像是 /dev/null), 硬碟也仍有空間,卻仍無法產生 core dump,可能是用到 setuid。用 ls -l 檢查一下,或用 strace -esetuid 檢查。Linux 為了安全考量, 在使用 setuid/setgid 後, 會自動禁用 core dump。

若確實有觸發 setuid 的話,在 setuid 後執行:

prctl(PR_SET_DUMPABLE, 1);

重新允許產生 core dump,應該就 ok 了。

Like what you read? Give fcamel a round of applause.

From a quick cheer to a standing ovation, clap to show how much you enjoyed this story.