linux 调试&各种知识收集2(持续更新)
1、查看netlink socket 丢包
cat /proc/net/netlink sk Eth Pid Groups Rmem Wmem Dump Locks Drops Inode c91eda00 0 1172 00000001 0 0 00000000 2 0 27767 c43eee00 0 -4099 00000000 0 0 00000000 2 0 41200 c9266e00 0 1186 00000000 0 0 00000000 2 0 28922 c1af5800 0 -4100 00000000 0 0 00000000 2 0 71681358 c9126a00 0 1103 00000004 0 0 00000000 2 0 18618 c1af5e00 0 1957 00000111 0 0 00000000 2 0 71681357
2、gdb设置搜索文件路径(查coredump可以使用):
set substitute-path
3、
linux 中输出 到指定
有cat tac (从最后一行显示)
more (一页一页的显示文档内容)
less(和 more类似 但是可以往前翻)
head(只看头几行)
tail (只看后几行)
nl(显示时会输出行号)
sync
sync命令用于强制被改变的内容立刻写入磁盘,更新超块信息。 在Linux/Unix系统中,在文件或数据处理过程中一般先放到内存缓冲区中,等到适当的时候再写入磁盘,以提高系统的运行效率。sync命令则可用来强制将内存缓冲区中的数据立即写入磁盘中。用户通常不需执行sync命令,系统会自动执行update或bdflush操作,将缓冲区的数据写 入磁盘。只有在update或bdflush无法执行或用户需要非正常关机时,才需手动执行sync命令。
4、
ldd <可执行文件名> 查看可执行文件链接了哪些 系统动态链接库
nm <可执行文件名> 查看可执行文件里面有哪些符号
strip <可执行文件名> 去除符号表可以给可执行文件瘦身
如果我们想从可执行程序里面提取出来一点什么文本信息的话,还可以用strings命令
strings <可执行文件名>
或者 nm readlef 查看库里面有哪些函数
file 查看文件信息
readelf 查看elf文件的文件信息
ldconfig是一个动态链接库管理命令。为了让动态链接库为系统所共享,需运行动态链接库的管理命令--ldconfig。 ldconfig命令的用途,主要是在默认搜寻目录(/lib和/usr/lib)以及动态库配置文件/etc/ld.so.conf内所列的目录下,搜索出可共享的动态链接库(格式lib*.so*),进而创建出动态装入程序(ld.so)所需的连接和缓存文件。缓存文件默认为 /etc/ld.so.cache,此文件保存已排好序的动态链接库名字列表,为了让动态链接库为系统所共享,需运行动态链接库的管理命令ldconfig,此执行程序存放在/sbin目录下。ldconfig通常在系统启动时运行,而当用户安装了一个新的动态链接库,修改了ld.so.conf时,就需要手工运行这个命令。
linux下的共享库机制采用了类似于高速缓存的机制,将库信息保存在/etc/ld.so.cache里边。程序连接的时候首先从这个文件里边查找,然后再到ld.so.conf的路径里边去详细找
ldconfig几个需要注意的地方
1. 往/lib和/usr/lib里面加东西,是不用修改/etc/ld.so.conf的,但是完了之后要调一下ldconfig,不然这个library会找不到
2. 想往上面两个目录以外加东西的时候,一定要修改/etc/ld.so.conf,然后再调用ldconfig,不然也会找不到
比如安装了一个MySQL到/usr/local/mysql,mysql有一大堆library在/usr/local/mysql/lib下面,这时 就需要在/etc/ld.so.conf下面加一行/usr/local/mysql/lib,保存过后ldconfig一下,新的library才能在 程序运行时被找到。
3. 如果想在这两个目录以外放lib,但是又不想在/etc/ld.so.conf中加东西(或者是没有权限加东西)。那也可以,就是export一个全局变 量LD_LIBRARY_PATH,然后运行程序的时候就会去这个目录中找library。一般来讲这只是一种临时的解决方案,在没有权限或临时需要的时 候使用。
4. ldconfig做的这些东西都与运行程序时有关,跟编译时一点关系都没有。编译的时候还是该加-L就得加,不要混淆了。
5. 总之,就是不管做了什么关于library的变动后,最好都ldconfig一下,不然会出现一些意想不到的结果。不会花太多的时间,但是会省很多的事。
Linux共享库的搜索路径先后顺序:
1、编译目标代码时指定的动态库搜索路径:在编译的时候指定-Wl,-rpath=路径
2、环境变量LD_LIBRARY_PATH指定的动态库搜索路径
3、配置文件/etc/ld.so.conf中指定的动态库搜索路径
4、默认的动态库搜索路径/lib
5、默认的动态库搜索路径 /usr/lib
二、概括GCC运行时库的搜索库先后顺序:
1、程序自身的RPATH(Library rpath), readelf -d bin可查看,在链接时通过-rpath参数写入程序ELF结构信息中,
而传入链接器中默认的-rpath参数是来自安装gcc时配置的文件specs(其中的配置项linker)。
2、编译时LDFLAGS选项 -L 参数指定的路径。
3、系统环境变量LD_LIBRARY_PATH。
4、在 /etc/ld.so.conf.d/ 目录下的配置文件指定的动态库绝对路径(通过ldconfig生效,一般是非root用户时使用)。
5、gcc安装时自身配置的搜索路径,gcc --print-search-dir | grep libraries 可查看,一般会包含该版本gcc必需的库
而不一定包含当前系统库路径。
三、补充说明:
1、在链接和运行查找库的过程中,只要找到同名的库则不管该库是否兼容均停止查找,
即便兼容的库可能出现在靠后的搜索路径中。
2、安装高版本gcc时一般是直接解压已经编译好的gcc,然后直接复制一份至新的路径下,
bcloud就是这么做的,可能是为了便于恢复编译环境吧。
3、如果系统自带的是低版本gcc,而需要使用高版本gcc编译程序,如果该程序依赖了非系统库(低版本gcc编译),
如果这个非系统库的安装目录下恰好有和高版本gcc依赖的库同名的库,那么为了能够使用这个非系统库,
这时高版本gcc编译时很可能会出现问题,必需保证链接器在查找库时,查找高版本gcc自身库一定要先于任意系统库(或任意库)所在的目录。
原因是高版本gcc应该是改进了相当一部分系统库,和当前低版本系统库并不兼容,而对于兼容的那些库,高版本gcc库可以直接使用当前系统库。
---------------------
gcc -L选项在链接时指定动态库路径,编译通过,但是执行时会找不到路径;
gcc -Wl -rpath选项在运行时指定路径,运行时按照指定路径寻找动态库;
使用-###选项可以打印出gcc所执行的各个子命令,分别为,
使用-v选项可以打印出gcc搜索头文件的路径和顺序。当然,也可以使用-###选项
避免 运行时才发现so库中函数未定义符号的错误undefined symbol
ldd 查看 elf文件依赖的 so 动态链接库 可以 export LD_LIBRARY_PATH=/path 设置 so文件的路径, nm -u *.so 或者 nm |grep U 查看 那些在 动态链接库中的符号。 ldd 查看 elf文件依赖的 so 动态链接库 可以 export LD_LIBRARY_PATH=/path 设置 so文件的路径, nm -u *.so 或者 nm |grep U 查看 那些在 动态链接库中的符号。 "U" The symbol is undefinedundefined的 symbol 这种就是表示 在其他 so动态链接库里面定义的。但是如果你的编译的 是so; 所以我觉得编译的动态链接库的时候最好加上 --unresolved-symbols=ignore-in-shared-libs 或者 --no-undefined 来检查一下。这样如果是自己的疏忽在 .c 源文件里面忘记的 某函数的定义,,编译的时候就可以提示错误了。 这里有3个参数可以使用--undefined symbols 和 --no-allow-shlib-undefined 参数的作用范围不一样而已,
--undefined symbols 针对常规object文件,
--no-allow-shlib-undefined针对的是符号在外部的未定义的shared object里面。
--unresolved-symbols和--undefined symbols 作用差不多,不过更具体一些。 我们的目的主要是编译一个so动态链接库时,把自己object里面未定义的符号report出来就可以了,用--no-undefined就可以了。
gcc -shared -Wl,-soname,libb.so.1,--no-undefined -o libb.so.1.2 xxxxxx
网卡名对应RX字节数: ifconfig | sed -n '/^[^ ]/{s/^\([^ ]*\) .*/\1/g;h;: top;n;/^$/b;s/^.*RX bytes:\([0-9]\{1,\}\).*/\1/g;T top;H;x;s/\n/:/g;p}' 网卡名对应的ip地址: ifconfig | sed -n '/^[^ ]/{s/^\([^ ]*\) .*/\1/g;h;: top;n;/^$/b;s/^.*inet addr:\([0-9]\{1,\}\.[0-9]\{1,\}\.[0-9]\{1,\}\.[0-9]\{1,\}\).*/\1/g;T top;H;x;s/\n/:/g;p}'
网络字节序和主机序跨平台的实现
/* * linux/byteorder/generic.h * Generic Byte-reordering support * * The "... p" macros, like le64_to_cpup, can be used with pointers * to unaligned data, but there will be a performance penalty on * some architectures. Use get_unaligned for unaligned data. * * Francois-Rene Rideau <fare@tunes.org> 19970707 * gathered all the good ideas from all asm-foo/byteorder.h into one file, * cleaned them up. * I hope it is compliant with non-GCC compilers. * I decided to put __BYTEORDER_HAS_U64__ in byteorder.h, * because I wasn't sure it would be ok to put it in types.h * Upgraded it to 2.1.43 * Francois-Rene Rideau <fare@tunes.org> 19971012 * Upgraded it to 2.1.57 * to please Linus T., replaced huge #ifdef's between little/big endian * by nestedly #include'd files. * Francois-Rene Rideau <fare@tunes.org> 19971205 * Made it to 2.1.71; now a facelift: * Put files under include/linux/byteorder/ * Split swab from generic support. * * TODO: * = Regular kernel maintainers could also replace all these manual * byteswap macros that remain, disseminated among drivers, * after some grep or the sources... * = Linus might want to rename all these macros and files to fit his taste, * to fit his personal naming scheme. * = it seems that a few drivers would also appreciate * nybble swapping support... * = every architecture could add their byteswap macro in asm/byteorder.h * see how some architectures already do (i386, alpha, ppc, etc) * = cpu_to_beXX and beXX_to_cpu might some day need to be well * distinguished throughout the kernel. This is not the case currently, * since little endian, big endian, and pdp endian machines needn't it. * But this might be the case for, say, a port of Linux to 20/21 bit * architectures (and F21 Linux addict around?). */ /* * The following macros are to be defined by <asm/byteorder.h>: * * Conversion of long and short int between network and host format * ntohl(__u32 x) * ntohs(__u16 x) * htonl(__u32 x) * htons(__u16 x) * It seems that some programs (which? where? or perhaps a standard? POSIX?) * might like the above to be functions, not macros (why?). * if that's true, then detect them, and take measures. * Anyway, the measure is: define only ___ntohl as a macro instead, * and in a separate file, have * unsigned long inline ntohl(x){return ___ntohl(x);} * * The same for constant arguments * __constant_ntohl(__u32 x) * __constant_ntohs(__u16 x) * __constant_htonl(__u32 x) * __constant_htons(__u16 x) * * Conversion of XX-bit integers (16- 32- or 64-) * between native CPU format and little/big endian format * 64-bit stuff only defined for proper architectures * cpu_to_[bl]eXX(__uXX x) * [bl]eXX_to_cpu(__uXX x) * * The same, but takes a pointer to the value to convert * cpu_to_[bl]eXXp(__uXX x) * [bl]eXX_to_cpup(__uXX x) * * The same, but change in situ * cpu_to_[bl]eXXs(__uXX x) * [bl]eXX_to_cpus(__uXX x) * * See asm-foo/byteorder.h for examples of how to provide * architecture-optimized versions * */ #define cpu_to_le64 __cpu_to_le64 #define le64_to_cpu __le64_to_cpu #define cpu_to_le32 __cpu_to_le32 #define le32_to_cpu __le32_to_cpu #define cpu_to_le16 __cpu_to_le16 #define le16_to_cpu __le16_to_cpu #define cpu_to_be64 __cpu_to_be64 #define be64_to_cpu __be64_to_cpu #define cpu_to_be32 __cpu_to_be32 #define be32_to_cpu __be32_to_cpu #define cpu_to_be16 __cpu_to_be16 #define be16_to_cpu __be16_to_cpu #define cpu_to_le64p __cpu_to_le64p #define le64_to_cpup __le64_to_cpup #define cpu_to_le32p __cpu_to_le32p #define le32_to_cpup __le32_to_cpup #define cpu_to_le16p __cpu_to_le16p #define le16_to_cpup __le16_to_cpup #define cpu_to_be64p __cpu_to_be64p #define be64_to_cpup __be64_to_cpup #define cpu_to_be32p __cpu_to_be32p #define be32_to_cpup __be32_to_cpup #define cpu_to_be16p __cpu_to_be16p #define be16_to_cpup __be16_to_cpup #define cpu_to_le64s __cpu_to_le64s #define le64_to_cpus __le64_to_cpus #define cpu_to_le32s __cpu_to_le32s #define le32_to_cpus __le32_to_cpus #define cpu_to_le16s __cpu_to_le16s #define le16_to_cpus __le16_to_cpus #define cpu_to_be64s __cpu_to_be64s #define be64_to_cpus __be64_to_cpus #define cpu_to_be32s __cpu_to_be32s #define be32_to_cpus __be32_to_cpus #define cpu_to_be16s __cpu_to_be16s #define be16_to_cpus __be16_to_cpus /* * They have to be macros in order to do the constant folding * correctly - if the argument passed into a inline function * it is no longer constant according to gcc.. */ #undef ntohl #undef ntohs #undef htonl #undef htons #define ___htonl(x) __cpu_to_be32(x) #define ___htons(x) __cpu_to_be16(x) #define ___ntohl(x) __be32_to_cpu(x) #define ___ntohs(x) __be16_to_cpu(x) #define htonl(x) ___htonl(x) #define ntohl(x) ___ntohl(x) #define htons(x) ___htons(x) #define ntohs(x) ___ntohs(x) #define ___htonllong(x) __cpu_to_be64(x) #define ___ntohllong(x) __be64_to_cpu(x) #define htonllong(x) ___htonlong(x) #define ntohllong(x) ___ntohllong(x)
开启VMCORE:
- 通过/sys/kernel/kexec_crash_loaded 的值,判断Kdump功能是否加载;
- 内核配置:
CONFIG_KEXEC=y Boot options --->[*] Kexec system call (EXPERIMENTAL) //此参数告诉系统使用Kexec跳过BIOS和引导(新)内核。(提供内核层面的kexec功能支持) CONFIG_CRASH_DUMP=y Boot options --->[*] Build kdump crash kernel (EXPERIMENTAL) //崩溃转储需要启用。没有此选项,Kdump将毫无用处。(提供内核层面的kdump功能支持) CONFIG_SYSFS=y File systems --->Pseudo filesystems --->[*] Tmpfs virtual memory file system support //启用sysfs文件系统支持 CONFIG_PROC_VMCORE=y File systems --->Pseudo filesystems --->-*- /proc file system support--->[*] /proc/vmcore support //此配置允许Kdump将内存转储保存到/proc/vmcore。 CONFIG_DEBUG_INFO=y Kernel hacking --->Compile-time checks and compiler options --->[*] Compile the kernel with debug info
- 安装kdump(kexec-tools)工具
- 最后加上crashkernel=aut 或者 256M 等设置,根据系统内存来决定,具体比例设置 可以google看下

sundray >cat /etc/kdump/kdumpvcore.sh #!/bin/sh #set -x KDUMP_LOG_DIR='/opt/data/log/kdump' AVLIABLE_SPACE_THRESHOLD_MB='300' if [[ -e /proc/vmcore ]] ; then if [[ -f ${KDUMP_LOG_DIR} ]] ; then rm -f ${KDUMP_LOG_DIR} fi if [[ ! -d ${KDUMP_LOG_DIR} ]] ; then mkdir -p ${KDUMP_LOG_DIR} fi # clear kdump log dir find ${KDUMP_LOG_DIR} -type f -exec rm -f {} \; dmesg_file_path="${KDUMP_LOG_DIR}/dmesg_$(date +%Y-%m-%d_%H:%M:%S).txt" vmcore-dmesg /proc/vmcore > ${dmesg_file_path} dump_file_path="${KDUMP_LOG_DIR}/kpanic_$(date +%Y-%m-%d_%H:%M:%S)" makedumpfile -c -d 31 /proc/vmcore ${dump_file_path} > /dev/console 2>&1 space_avail=$(df --block-size=1M ${CNEOS_KDUMP_LOG_DIR} | awk '{if (NR != 1) { print $4; } }') if [[ ${space_avail} -lt ${AVLIABLE_SPACE_THRESHOLD_MB} ]] ; then rm -f ${dmesg_file_path} fi reboot -f fi sundray>cat /etc/cneos-kdump/loadk2.sh #!/bin/sh #set -x # /sys/kernel/kexec_crash_loaded will be 1 even if the 2nd kernel loaded via kexec, default '0' if [[ ! -e /proc/vmcore && "$(cat /sys/kernel/kexec_crash_loaded)" != "1" ]] ; then if [[ -s /boot/bzImage && -s /boot/initrd.gz ]] ; then kexec --load-panic /boot/bzImage --initrd=/boot/initrd.gz --append='libata.dma=0 root=/dev/ram0 rw 1 maxcpus=1 irqpoll console=ttyS0,115200 systemd.unit=rescue.target' elif [[ ! -s /opt/boot/bzImage ]] ; then echo "/opt/boot/bzImage is not exists" elif [[ ! -s /opt/boot/initrd.gz ]] ; then echo "/opt/boot/initrd.gz is not exists" fi elif [[ -e /proc/vmcore ]] ; then echo "/proc/vmcore is exists" elif [[ "$(cat /sys/kernel/kexec_crash_loaded)" == "1" ]] ; then echo "/sys/kernel/kexec_crash_loaded is 1" fi
root>cat /etc/kdump/kdumpvcore.sh #!/bin/sh #set -x KDUMP_LOG_DIR='/opt/data/log/kdump' f AVLIABLE_SPACE_THRESHOLD_MB='200' if [[ -e /proc/vmcore ]] ; then # kdump log dir must be a folder if [[ -f ${KDUMP_LOG_DIR} ]] ; then rm -f ${KDUMP_LOG_DIR} fi if [[ ! -d ${KDUMP_LOG_DIR} ]] ; then mkdir -p ${CNEOS_KDUMP_LOG_DIR} fi # clear kdump log dir find ${KDUMP_LOG_DIR} -type f -exec rm -f {} \; # generate dmesg according to /proc/vmcore dmesg_file_path="${KDUMP_LOG_DIR}/dmesg_$(date +%Y-%m-%d_%H:%M:%S).txt" vmcore-dmesg /proc/vmcore > ${dmesg_file_path} dump_file_path="$KDUMP_LOG_DIR}/kpanic_$(date +%Y-%m-%d_%H:%M:%S)" makedumpfile -c -d 31 /proc/vmcore ${dump_file_path} > /dev/console 2>&1 space_avail=$(df --block-size=1M ${CNEOS_KDUMP_LOG_DIR} | awk '{if (NR != 1) { print $4; } }') if [[ ${space_avail} -lt ${AVLIABLE_SPACE_THRESHOLD_MB} ]] ; then rm -f ${dmesg_file_path} fi reboot -f fi root>cat /etc/cneos-kdump/loadk2.sh dmesg_2023-02-20_10:07:41.txt kpanic_2023-02-20_10:07:41 root>cat /etc/cneos-kdump/loadk2.sh #!/bin/sh #set -x # /sys/kernel/kexec_crash_loaded will be 1 even if the 2nd kernel loaded via kexec, default '0' if [[ ! -e /proc/vmcore && "$(cat /sys/kernel/kexec_crash_loaded)" != "1" ]] ; then if [[ -s /boot/bzImage && -s /boot/initrd.gz ]] ; then kexec --load-panic /boot/bzImage --initrd=/boot/initrd.gz --append='libata.dma=0 root=/dev/ram0 rw 1 maxcpus=1 irqpoll console=ttyS0,115200 systemd.unit=rescue.target' elif [[ ! -s /opt/boot/bzImage ]] ; then echo "/opt/boot/bzImage is not exists" elif [[ ! -s /opt/boot/initrd.gz ]] ; then echo "/opt/boot/initrd.gz is not exists" fi elif [[ -e /proc/vmcore ]] ; then echo "/proc/vmcore is exists" elif [[ "$(cat /sys/kernel/kexec_crash_loaded)" == "1" ]] ; then echo "/sys/kernel/kexec_crash_loaded is 1"
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 零经验选手,Compose 一天开发一款小游戏!
· 一起来玩mcp_server_sqlite,让AI帮你做增删改查!!