digoal
2023-10-08
PostgreSQL , PolarDB , DuckDB , pstack , gdb , strace , debian
https://blog.csdn.net/JiekeXu/article/details/107479167
http://www.manongjc.com/detail/57-exyaiyhanljwsoz.html
rhel/centos支持pstack, 在Debian上却没有, 原来是这个原因:
yum install -y strace gdb pstack
因为实际上pstack是个脚本, 指向gstack, 最终还是调用gdb.
[root@JiekeXu ~]# cat /usr/bin/gstack
#!/bin/sh
if test $# -ne 1; then
echo "Usage: `basename $0 .sh` <process-id>" 1>&2
exit 1
fi
if test ! -r /proc/$1; then
echo "Process $1 not found." 1>&2
exit 1
fi
# GDB doesn't allow "thread apply all bt" when the process isn't
# threaded; need to peek at the process to determine if that or the
# simpler "bt" should be used.
backtrace="bt"
if test -d /proc/$1/task ; then
# Newer kernel; has a task/ directory.
if test `/bin/ls /proc/$1/task | /usr/bin/wc -l` -gt 1 2>/dev/null ; then
backtrace="thread apply all bt"
fi
elif test -f /proc/$1/maps ; then
# Older kernel; go by it loading libpthread.
if /bin/grep -e libpthread /proc/$1/maps > /dev/null 2>&1 ; then
backtrace="thread apply all bt"
fi
fi
GDB=${GDB:-/usr/bin/gdb}
# Run GDB, strip out unwanted noise.
# --readnever is no longer used since .gdb_index is now in use.
$GDB --quiet -nx $GDBARGS /proc/$1/exe $1 <<EOF 2>&1 |
set width 0
set height 0
set pagination no
$backtrace
EOF
/bin/sed -n
-e 's/^((gdb) )*//'
-e '/^#/p'
-e '/^Thread/p'
- 脚本要求一个参数:进程 ID。
- 然后通过检测 /proc 目录下进程子目录是否可读,来查看相应进程是否存在。
- 如果进程只有一个线程,那么使用 gdb 的 “bt” 命令打印线程堆栈信息,否则使用 “thread apply all bt” 命令。
- 最后调用 gdb,使用 “bt” 或 “thread apply all bt” 命令,并把输出重定向到 sed 工具,由 sed 工具打印出线程堆栈信息。
了解pstack真相后, debian可以安装strace和gdb, 直接调用gdb即可:
apt-get install -y strace gdb
例如:
gdb -p 8089 --batch -ex "bt"
gdb -p 8089 --batch -ex "thread apply all bt full"
root@d40da947f60f:~# gdb -p 8089 --batch -ex "thread apply all bt full"
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/aarch64-linux-gnu/libthread_db.so.1".
0x0000ffffa566011c in __GI_epoll_pwait (epfd=4, events=0xaaaafe49b300, maxevents=1, timeout=-1, set=0x0) at ../sysdeps/unix/sysv/linux/epoll_pwait.c:42
42 ../sysdeps/unix/sysv/linux/epoll_pwait.c: No such file or directory.
Thread 1 (Thread 0xffffa2d66010 (LWP 8089) "postgres"):
#0 0x0000ffffa566011c in __GI_epoll_pwait (epfd=4, events=0xaaaafe49b300, maxevents=1, timeout=-1, set=0x0) at ../sysdeps/unix/sysv/linux/epoll_pwait.c:42
_sys_result = 18446744073709551612
sc_ret = <optimized out>
#1 0x0000aaaae7961e74 in WaitEventSetWait ()
No symbol table info available.
#2 0x0000aaaae784d9fc in secure_read ()
No symbol table info available.
#3 0x0000aaaae7854d04 in ?? ()
No symbol table info available.
#4 0x0000aaaae785593c in pq_getbyte ()
No symbol table info available.
#5 0x0000aaaae798bff4 in PostgresMain ()
No symbol table info available.
#6 0x0000aaaae78fd180 in ?? ()
No symbol table info available.
#7 0x0000aaaae78fe060 in PostmasterMain ()
No symbol table info available.
#8 0x0000aaaae764fb70 in main ()
No symbol table info available.
[Inferior 1 (process 8089) detached]
root@d40da947f60f:~# gdb -p 8089 --batch -ex "thread apply all bt"
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/aarch64-linux-gnu/libthread_db.so.1".
0x0000ffffa566011c in __GI_epoll_pwait (epfd=4, events=0xaaaafe49b300, maxevents=1, timeout=-1, set=0x0) at ../sysdeps/unix/sysv/linux/epoll_pwait.c:42
42 ../sysdeps/unix/sysv/linux/epoll_pwait.c: No such file or directory.
Thread 1 (Thread 0xffffa2d66010 (LWP 8089) "postgres"):
#0 0x0000ffffa566011c in __GI_epoll_pwait (epfd=4, events=0xaaaafe49b300, maxevents=1, timeout=-1, set=0x0) at ../sysdeps/unix/sysv/linux/epoll_pwait.c:42
#1 0x0000aaaae7961e74 in WaitEventSetWait ()
#2 0x0000aaaae784d9fc in secure_read ()
#3 0x0000aaaae7854d04 in ?? ()
#4 0x0000aaaae785593c in pq_getbyte ()
#5 0x0000aaaae798bff4 in PostgresMain ()
#6 0x0000aaaae78fd180 in ?? ()
#7 0x0000aaaae78fe060 in PostmasterMain ()
#8 0x0000aaaae764fb70 in main ()
[Inferior 1 (process 8089) detached]
root@d40da947f60f:~# gdb -p 8089 --batch -ex "bt"
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/aarch64-linux-gnu/libthread_db.so.1".
0x0000ffffa566011c in __GI_epoll_pwait (epfd=4, events=0xaaaafe49b300, maxevents=1, timeout=-1, set=0x0) at ../sysdeps/unix/sysv/linux/epoll_pwait.c:42
42 ../sysdeps/unix/sysv/linux/epoll_pwait.c: No such file or directory.
#0 0x0000ffffa566011c in __GI_epoll_pwait (epfd=4, events=0xaaaafe49b300, maxevents=1, timeout=-1, set=0x0) at ../sysdeps/unix/sysv/linux/epoll_pwait.c:42
#1 0x0000aaaae7961e74 in WaitEventSetWait ()
#2 0x0000aaaae784d9fc in secure_read ()
#3 0x0000aaaae7854d04 in ?? ()
#4 0x0000aaaae785593c in pq_getbyte ()
#5 0x0000aaaae798bff4 in PostgresMain ()
#6 0x0000aaaae78fd180 in ?? ()
#7 0x0000aaaae78fe060 in PostmasterMain ()
#8 0x0000aaaae764fb70 in main ()
[Inferior 1 (process 8089) detached]
以下是chatgpt回复, 未验证.
在使用 GDB 进行调试时,你可以通过设置断点并使用 GDB 的 print 命令来打印每个变量的值。以下是一个示例:
在终端中,使用以下命令启动 GDB,将可执行文件和相关的符号文件传递给它:
gdb /path/to/your/program
在 GDB 中,使用 break 命令在你希望检查变量的位置设置一个断点:
break function_name
继续执行程序:
run
当程序达到断点时,可以使用 print 命令来打印变量的值:
print variable_name
将 variable_name 替换为要打印的变量名。
继续执行程序,直到下一个断点或程序结束:
continue
通过重复以上步骤,在程序运行过程中你可以设置多个断点,然后使用 print 命令来打印想要检查的变量的值。
除了 print 命令之外,GDB 还提供了其他一些有用的命令来帮助你调试程序,例如 backtrace(打印函数调用堆栈)和 step(单步执行)等。
请注意,使用 GDB 进行调试需要一些调试知识和技巧。你可能需要了解如何设置断点、单步执行、查看变量的内存地址等。
希望这个解答对你有帮助。如果你有任何其他问题,请随时提问。