suse linux 13.2 我那个系统里面没查看错误日志

suse linux 13.2 我那个系统里面没查看错误日志,第1张

日志服务器:1、编辑/etc/sysconfig/syslog:SYSLOGD_OPTIONS="-m 0"为SYSLOGD_OPTIONS="-m 0 -r"2、重启syslog服务,会发现UDP的514端口处于监听状态。

您好,很高兴为您解答。

L Linux 死机有很多种情况,最常见的是系统负载过高导致的。

由于系统负载过高导致的卡死,一定是解决的越快越好!此时必须 记住的是,不能再试图依赖任何图形界面的东西,如 Gnome 的系统监视器,这只会继续加重这种卡死的局面。Linux 最初就是不需要图形界面的,因为有一个很强大的文字界面。按 Ctrl-Alt-F1(F1-F6 一般来说都可以),然后等一会儿,就会切换到 tty,也就是所谓的文字界面。这个时候需要用用户名密码登入。注意,可能键盘输入的速度比较慢,不过应该还是可以忍受的。下面在提示符后面输入 top 回车,这时会看到一张动态的表,上面列出了耗用资源最多的进程。观察它刷新一两次,按q退出,然后输入 kill ,其中的 PID 你可以在 top 里面看到。这个时候应该会快了不少,如果你发现没有成功结束掉,就再输入 kill -KILL ,这次基本上就没问题了。

除了上面这种情况外,一些底层软件的 bug 也可能导致一些奇怪的死机问题。在键盘上可以找到一个叫做“Sys Rq”的键,在台机的键盘上通常与 Prt Sc 共键,在笔记本可能在其他位置,如 Delete。以台机为例,要使用这种方法需要按住 Alt-Print(Sys Rq),然后依次按下 reisub 这几个键,按完 b 系统就会重启。

下面解释一下这个方法:其实 Sys Rq 是一种叫做系统请求的东西,按住 Alt-Print 的时候就相当于按住了 Sys Rq 键,这个时候输入的一切都会直接由 Linux 内核来处理,它可以进行许多低级 *** 作。这个时候 reisub 中的每一个字母都是一个独立 *** 作,他们分别表示:unRaw将键盘控制从X Server那里抢回来tErminate 给所有进程发送 SIGTERM 信号,让他们自己解决善后kIll 给所有进程发送 SIGKILL 信号,强制他们马上关闭Sync将所有数据同步至磁盘Unmount将所有分区挂载为只读模式reBoot重启这6个字母的顺序是不可以记错的。

如若满意,请点击右侧【采纳答案】,如若还有问题,请点击【追问】

希望我的回答对您有所帮助,望采纳!

~ O(∩_∩)O~

线上环境进程崩溃,运维为了不背锅,要求崩溃之后立马将进程拉起。然而发现有个问题:一旦运维将进程拉起之后,之后使用崩溃的 core 文件来进行分析时,符号信息都丢失,看到的都是问号。

但是,如果崩溃之后未被拉起,可以正常的看到符号。

后来发现,是运维启动进程的 shell 脚本,每次启动之前,会将需要加载的部分业务相关的 so 文件,文件名字修改(名称里加上了时间戳,类似 lib20200423002608_xxxx.so 这种)。名称被修改之后,gdb 自然没法加载加载这个 so 文件。

info shared

在 gdb 里使用 info shared,可以看到这个 so 文件无对应的地址,因为没有对应的 so 文件被加载。线上环境的 gdb版本是 7.2,启动时没有与 so 文件不存在相关的提示。

当然这是后话。

那么在奔溃时,如何将奔溃时的调用栈记录到日志里呢。

可以借助 backtrace 相关的 3 个函数来实现。

#include <execinfo.h>

int backtrace(void *symaddr[], int size)

char **backtrace_symbols(void *const symaddr[], int size)

void backtrace_symbols_fd(void *const *buffer, int size, int fd)

参数和返回值说明:

backtrace 传入一个数组 symaddr,用来保存符号的地址;size 为数组的大小。size 应该足够大,不然会有部分符号丢失。返回值为实际保存的地址数量。

backtrace_symbols 用来根据符号的地址,得到对应的符号。size 为 backtrace 的返回值,表示实际需要处理的符号数量。

返回的是一个 malloc 得到的字符串数组的起始地址(C 语言中不太严谨的讲,char* 就是字符串),所以最后需要调用者释放内存。

#include <stdlib.h>

#include <string>

#include <execinfo.h>

#include <unistd.h>

void getCallStackInfo(std::string &stackInfo)

{

static const int size = 100 //符号数量,100足够

int nptrs

void *buffer[size]

char **syms

nptrs = backtrace(buffer, size)//返回当前调用栈实际的符号数量

syms = backtrace_symbols(buffer, nptrs)

if (syms == nullptr)

{

perror("backtrace_symbols")

exit(EXIT_FAILURE)

}

for(int i = 0i <nptrs++i)

{

stackInfo.append(syms[i])

stackInfo.append("\n")

}

free(syms)

}

void say(int &n)

{

static int call_count = 0

++n

++call_count

printf("call count %d\n", call_count)

if(call_count == 6)

{

std::string stack_info

getCallStackInfo(stack_info)

printf("%s\n", stack_info.c_str())

return

}

say(n)

}

int main()

{

int n = 3

say(n)

return 0

}

编译运行,clang++ main.cpp -rdynamic -o main.out &&./main.out

call count 1

call count 2

call count 3

call count 4

call count 5

call count 6

./main.out(_Z16getCallStackInfoRNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE+0x23) [0x400d53]

./main.out(_Z3sayRi+0x6a) [0x400e8a]

./main.out(_Z3sayRi+0xc1) [0x400ee1]

./main.out(_Z3sayRi+0xc1) [0x400ee1]

./main.out(_Z3sayRi+0xc1) [0x400ee1]

./main.out(_Z3sayRi+0xc1) [0x400ee1]

./main.out(_Z3sayRi+0xc1) [0x400ee1]

./main.out(main+0x1f) [0x400f0f]

/lib64/libc.so.6(__libc_start_main+0xf3) [0x7fe51b555873]

./main.out(_start+0x2e) [0x400c6e]

看到调用栈已经被记录下来,当然符号都是 name mangling 之后的,使用 c++filt _Z3sayRi 可以看到原始名字。

回到记录奔溃时的调用栈到日志里的主题上。通常的奔溃都是由于内存问题,那么可以捕获 SIGSEGV 信号,在信号处理函数中将当前的调用栈记录到日志中就行。写文件可能需要一个 sleep 延时等待日志线程处理完毕。

void sig_log_stack_handler(int sig)

{

std::string stackInfo

getCallStackInfo(stackInfo)

abort()

}

当然严格的来说,在信号处理器函数里处理 IO 是不符合标准的,会 UB.

注意编译时一定要带上 -rdynamic 选项才有用。如果使用的是 qt creator,这个 -rdynamic 参数时需要传给链接器的,需要在 .pro 文件里加上,加到 QMAKE_CXXFLAGS 是没得用的。

QMAKE_LFLAGS += -rdynamic


欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/yw/7376095.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2023-04-04
下一篇2023-04-04

发表评论

登录后才能评论

评论列表(0条)

    保存