使用strace查看shell内置命令的系统调用(sudo亦然)

使用strace查看shell内置命令的系统调用

1. 首先来看一下strace命令基本用法和示例.

    strace ls                  # 查看ls的系用
    strace ls -l               # strace 命令后面可以跟参数, 具体请参考 linux man page
    strace -e 'trace=file' ls  # 查看执行ls命令时, 内部执行了哪些文件相关的系统调用

    which strace               # 查看strace命令类型, 是一个位于/usr/bin/strace 的可执行命令(Ubuntu 16.04.2 LTS)

注意: strace是一个外部命令, 即是一个可执行文件.

2. 现在有一个需求, 具体如下

下午想知道ulimit设置一些进程相关的资源限制(比如栈程序大小, coredump文件大小.), 是调用哪些系统调用实现的?
使用google一下子没有搜索到, 可能是搜索方式不对. 但是中文可以搜索到.(允许在这里卖个关子, 先不透露答案)

当时想到使用strace跟踪一下ulimit命令, 看一下ulimit使用了什么系统调用?
    strace ulimit -c
    输出错误信息如下:
    strace: Can't stat 'ulimit': No such file or directory
    type  ulimit        # ulimit is a shell builtin (ulimit是一个shell内置命令)
因为strace是一个外置命令, 对于shell(bash) 内置的命令, 自然是无能为力了.
同样和strace 类似的尴尬还有 sudo命令.(sudo 命令也是一个外置命令)

3. strace 追踪内置命令系统调用的解决方案( sudo同理 )

strace 虽然不能追踪shell内置命令, 但是shell命令(这里是bash)本身有一个可执行文件, 可以被strace追踪.
    strace bash                     # 像这样
    bash -c "ulimit -c"             # 同样bash 也可以带参数, 启动新进程, 同时执行内置命令
    strace bash -c "ulimit -c"      # 使用strace 追踪bash命令的执行

输出如下: 因为输出有200多行, 所以这里直接抛弃前面进程启动相关的系统调用输出, 从access(/bin/bash)开始看.
发现有一个系统调用 getrlimit() 和 “limit”有关. 

access("/bin/bash", R_OK)               = 0
brk(0x2171000)                          = 0x2171000
brk(0x2172000)                          = 0x2172000
getpgrp()                               = 26398
rt_sigaction(SIGCHLD, {0x447ad0, [], SA_RESTORER|SA_RESTART, 0x7f1d92e234b0}, {SIG_DFL, [], SA_RESTORER|SA_RESTART, 0x7f1d92e234b0}, 8) = 0
getrlimit(RLIMIT_NPROC, {rlim_cur=63112, rlim_max=63112}) = 0
brk(0x2173000)                          = 0x2173000
brk(0x2174000)                          = 0x2174000
rt_sigprocmask(SIG_BLOCK, NULL, [], 8)  = 0
getpeername(0, 0x7ffc798a5310, 0x7ffc798a530c) = -1 ENOTSOCK (Socket operation on non-socket)
rt_sigprocmask(SIG_BLOCK, NULL, [], 8)  = 0
brk(0x2175000)                          = 0x2175000
brk(0x2176000)                          = 0x2176000
getrlimit(RLIMIT_CORE, {rlim_cur=0, rlim_max=RLIM64_INFINITY}) = 0
write(1, "0\n", 20
)                      = 2
rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
exit_group(0)                           = ?
+++ exited with 0 +++
    man  getrlimit      # 查看这个系统调用信息
man 摘要信息如下: 正是我们要找的. 所以ulimit是通过 getrlimit(), setrlimit()系统调用实现的.  
   The  getrlimit()  and setrlimit() system calls get and set resource limits respectively.  Each resource has an associated soft and
   hard limit, as defined by the rlimit structure:

   至此, 使用strace 艰难完成检索.满足了好奇心.
   接下来是对setrlimit 和 getrlimit的测试.

你可能感兴趣的:(shell)