专栏首页首富手记df 和 ls 命令执行夯主

df 和 ls 命令执行夯主

df 和 ls 命令执行夯主

作者:张首富
时间:2020-05-21
w x:y18163201

原因

今天一个朋友问我一个问题,他的描述如下:

1,ls / 执行这个命令的时候卡住,什么反应都没有,但是 ls 其他目录的时候就没有事情 2,df 查看文件挂载的时候也卡住, 3,我什么都没干啊,就做了一个 ISCSI

其实他说第二点问题的时候我就已经猜到问题所在了,那不就是远程挂载的磁盘非正常的掉了,然后就会造成这个问题。但是他说 ISCSI 这个玩意的时候我不知道是啥,于是查了一下,有兴趣的同学可以看看这是:https://zhuanlan.zhihu.com/p/60986068,看的出来他是一个网络存储,那么就更加坚定我的想法了,开始指挥解决问题

解决办法

问题原因大概猜想出来之后,就是开始解决问题了。

找到是哪个挂载点失效了

我们可以使用此命令来查找挂载点哪个地方失效了。

strace df -Th

执行卸载

通过上面命令我们能找到是哪个挂载点失效了,我们可以使用下面命令先尝试卸载

umount -lf 有问题的挂载点

然后等个1~2 分钟看看效果,-f 是强制卸载的意思。

如果使用这个命令还是解决不了问题,那么我们先确认有哪些进程在占用这个挂载点

fuser -cu 挂载点

会得到进程 ID,和进程命令,看看此进程是否能正常杀掉,如果可以我们手工停止这个进程,然后进行卸载,或者直接使用下面命令进行卸载

fuser -ck 挂载点

strace 工具实现原理

什么是 strace

它是一个具有 Linux 传统命令行界面的诊断、调试和指令性用户空间的使用程序。它用于监控和篡改进程与 Linux 内核之间的交互,包括系统调用、信号传递和进程状态的变化。strace 的所有操作都是通过内核的ptrace功能来实现的。项目主页是:https://github.com/strace/strace

关于 ptrace 相关知识可以阅读:

main ptrace

Linux 沙箱之 ptrace

https://jin-yang.github.io/post/linux-ptrace-api-introduce.html

使用 strace

最简单的 strace 命令的用法就是: strace PROG;PROG 就是要执行的程序(linux 命令)。strace 命令执行的结果就是按照调用顺序打印出所有的系统调用,包括函数名、参数列表以及返回值。

使用 strace 跟踪一个进程的系统调用的基本流程如下图:

(此图片来源网络)

从图中可以看出strace做了以下几件事情:

  1. 设置SIGCHLD 信号的处理函数,这个处理函数只要不是SIG_IGN即可。由于子进程停止后是通过SIGCHLD信号通知父进程的,所以这里要防止SIGCHLD信号被忽略。
  2. 创建子进程,在子进程中调用ptrace(PTRACE_TRACEME,0L, 0L, 0L)使其被父进程跟踪,并通过execv函数执行被跟踪的程序。
  3. 通过wait()等待子进程停止,并获得子进程停止时的状态status。
  4. 通过子进程的状态查看子进程是否已正常退出,如果是,则不再跟踪,随后调用ptrace发送PTRACE_DETACH请求解除跟踪关系。
  5. 子进程停止后,打印系统调用的函数名、参数和返回值。具体流程见图2。
  6. 通过PTRACE_SYSCALL让子进程继续运行,由于这个请求会让子进程在系统调用的入口处和系统调用完成时都会停止并通知父进程,这样,父进程就可以在系统调用开始之前获得参数,结束之后获得返回值。

在系统调用的入口和结束时子进程停止运行时,这时父进程认为子进程是因为收到SIGTRAP信号而停止的。所以父进程在wait()后可以通过SIGTRAP来与其他信号区分开。

Strace中为每个要跟踪的进程维护了一个TCB(Trace Control Block)结构,定义如下。它保存了当前发生的系统调用的信息。

/* Trace Control Block */
struct tcb {
    int flags;    /* See below for TCB_ values */
    int pid;      /* Process Id of this entry */
    int qual_flg; /* qual_flags[scno] or DEFAULT_QUAL_FLAGS + RAW*/
    int u_error;  /* Error code */
    long scno;    /* System call number */
    long u_arg[MAX_ARGS];    /* System call arguments */
    long u_rval;      /* Return value */
    int curcol;       /* Output column for this process */
    FILE *outf;       /* Output file for this process */
    const char *auxstr;/*Auxiliary info from syscall (see RVAL_STR) */
    const struct_sysent *s_ent;/* sysent[scno] or dummy struct for bad scno */
    struct timeval stime;/*System time usage as of last process wait */
    struct timeval dtime;    /* Delta for system time usage */
    struct timeval etime;    /* Syscall entry time */
              /* Support fortracing forked processes: */
    long inst[2];     /* Saved clone args (badly named) */
};

上面已经提到,子进程会在系统调用前后各停止一次,所以打印系统调用信息时分为两个阶段:在系统调用开始时可以获取系统调用号和参数,在系统调用结束时可以获取系统调用的返回结果。通过给tcb结构的flags字段清除和添加TCB_INSYSCALL标志位来区分系统调用的开始和结束。

例如编写一个使用printf打印“Hello world”的程序hello.c,使用strace跟踪该程序的系统调用可以看到如下结果:

# ./strace ./hello
execve("./hello ", ["./hello "], [/* 7 vars */])= 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS,-1, 0) = 0x2aaad000
stat("/etc/ld.so.cache", 0x7faf4ca8)    = -1 ENOENT (No such file or directory)
open("/tmp/libgcc_s.so.1", O_RDONLY)    = -1 ENOENT (No such file or directory)
open("/lib/libgcc_s.so.1", O_RDONLY)    = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=1565445, ...}) = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS,-1, 0) = 0x2aaae000
read(3,"\177ELF\1\2\1\0\0\0\0\0\0\0\0\0\0\3\0\10\0\0\0\1\0\0\263\200\0\0\0004"...,4096) = 4096
mmap(NULL, 241664, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) =0x2aabe000
mmap(0x2aabe000, 169308, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED,3, 0) = 0x2aabe000
mmap(0x2aaf8000, 2400, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED,3, 0x2a000) = 0x2aaf8000
close(3)                                = 0
munmap(0x2aaae000, 4096)                = 0
open("/tmp/libc.so.0", O_RDONLY)        = -1 ENOENT (No such file or directory)
open("/lib/libc.so.0", O_RDONLY)        = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=431732, ...}) = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS,-1, 0) = 0x2aaae000
read(3, "\177ELF\1\2\1\0\0\0\0\0\0\0\0\0\0\3\0\10\0\0\0\1\0\0\252\200\0\0\0004"...,4096) = 4096
mmap(NULL, 471040, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) =0x2aaf9000
mmap(0x2aaf9000, 380336, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED,3, 0) = 0x2aaf9000
mmap(0x2ab65000, 8088, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED,3, 0x5c000) = 0x2ab65000
mmap(0x2ab67000, 19376, PROT_READ|PROT_WRITE,MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x2ab67000
close(3)                                = 0
munmap(0x2aaae000, 4096)                = 0
open("/tmp/libc.so.0", O_RDONLY)        = -1 ENOENT (No such file or directory)
open("/lib/libc.so.0", O_RDONLY)        = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=431732, ...}) = 0
close(3)                                = 0
stat("/lib/ld-uClibc.so.0", {st_mode=S_IFREG|0755,st_size=22604, ...}) = 0
mprotect(0x2ab65000, 4096, PROT_READ)   = 0
mprotect(0x2aabc000, 4096, PROT_READ)   = 0
ioctl(0, TIOCNXCL, {B115200 opost isig icanon echo ...}) = 0
ioctl(1, TIOCNXCL, {B115200 opost isig icanon echo ...}) = 0
write(1, "Hello world\n", 12Hello world
)           = 12
exit(0)                                 = ?
+++ exited with 0 +++

从结果可以看出,执行该程序调用了很多系统调用,并最终通过write系统调用打印出“Hello world”。

跟踪一个正在运行的进程,使用-p选项加上进程的pid。

跟踪某个特定的系统调用,使用-e选项加上系统调用名。

例如,跟踪进程727的epoll_wait系统调用:strace -e epoll_wait -p 727

参考:

https://blog.csdn.net/jasonchen_gbd/article/details/44044539

https://blog.csdn.net/shandianling/article/details/17033299

http://godorz.info/2011/02/process-tracing-using-ptrace/(值得一看)

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • alias设置别名使用的时候报错:-bash: this: command not found

    使用alias指定别名的时候一定要使用‘’将原来的命令引起来,防止特殊字符发生错误。

    张琳兮
  • docker 挂载文件不同步问题记录

    今天上午开发给我反应一个问题,所在宿主机上更改了挂载的文件在 docker 里面看不到改变,问我是不是 docker 启动的时候挂载的时候有问题,我说不可能啊,...

    张琳兮
  • docker 挂载文件不同步问题记录

    今天上午开发给我反应一个问题,所在宿主机上更改了挂载的文件在 docker 里面看不到改变,问我是不是 docker 启动的时候挂载的时候有问题,我说不可能啊,...

    张琳兮
  • Linux 命令(137)—— strace 命令

    strace 命令是一个集诊断、调试、统计于一体的工具,我们可以使用 strace 对程序的系统调用和信号传递的跟踪结果来对程序进行分析,以达到解决问题或者是了...

    Dabelv
  • 大数据革新银行按揭贷款业务

    Tomes撰写了一篇关于2008年金融危机的文章(全球金融危机 - 在金融界如此称呼)。无论是什么样的金融工具机制导致了金融崩溃 - 每个人都普遍同意的一点是,...

    eru
  • AngularDart4.0 英雄之旅-教程-07路由 顶

    如果该应用程序尚未运行,请启动该应用程序。 在进行更改时,请通过重新加载浏览器窗口来保持运行。

    南郭先生
  • APT41 Speculoos后门分析

    2020年3月25日,FireEye发表了APT41全球攻击活动报告。此攻击活动发生在1月20日至3月11日期间,主要对Citrix,Cisco和Zoho网络设...

    FB客服
  • rsGen:一款基于Windows BAT和JS混编实现的通用反弹shell命令生成器

    rsGen是一款基于Widows BAT&JS混编实现的多功能反弹shell命令生成器。不仅支持生成原生反弹shell命令,还支持生成“命令中转”形式的一句话反...

    FB客服
  • AI情绪识别技术背后:一场悄然来袭的“暴政”

    不可否认,情绪检测的技术在AI时代不断飞速发展。然而,这些情绪监控技术都基于了一种过时的科学概念:所有人都有同样的六种基本情感。

    大数据文摘
  • (译)在 Istio 中使用 Opentracing Baggage 进行传播和路由

    现代服务网格架构提供了很多的新功能,基础设施相关的依赖部分被逐步从代码中移除,极大的降低了编码工作量。除此之外,这一架构的智能路由功能还把金丝雀发布以及类似功能...

    崔秀龙

扫码关注云+社区

领取腾讯云代金券