strace使用
介绍
您是否想在Linux服务器上查看其他人的终端? 我有。当然,物理显示终端是一种方法,但这有点麻烦。 您也可以使用script
命令,但这比较费力,因为您必须要求淋浴执行script
命令。
因此,我创建了一个工具,可以轻松查看服务器上其他用户的登录状态! 此工具包装strace
。 它称为ttycopy
。 这非常简单,而且非常有用。
https://github.com/d-tsuji/ttycopy
痕迹
众所周知, strace
命令可用于跟踪系统调用。 在介绍ttycopy
的工作原理之前,让我们回顾一下如何使用strace
检查系统调用。 例如,如果当前目录是/tmp
并且在/tmp
下有一个名为sample.txt
的空文件,则跟踪的结果如下所示。 换句话说,情况如下。
[root@localhost tmp]# pwd
/tmp
[root@localhost tmp]# ls
sample.txt
我们可以使用strace
来检查在调用ls
时正在调用哪种系统调用。
[root@localhost tmp]# strace ls
execve("/usr/bin/ls", ["ls"], [/* 27 vars */]) = 0
brk(NULL) = 0xaf7000
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f2afb9f4000
access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory)
open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=84100, ...}) = 0
mmap(NULL, 84100, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f2afb9df000
close(3) = 0
open("/lib64/libselinux.so.1", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\320i\0\0\0\0\0\0"..., 832) = 832
fstat(3, {st_mode=S_IFREG|0755, st_size=155784, ...}) = 0
mmap(NULL, 2255184, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7f2afb5ad000
mprotect(0x7f2afb5d1000, 2093056, PROT_NONE) = 0
mmap(0x7f2afb7d0000, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x23000) = 0x7f2afb7d0000
mmap(0x7f2afb7d2000, 6480, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7f2afb7d2000
...
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f288e995000
write(1, "sample.txt\n", 11sample.txt
) = 11
close(1) = 0
munmap(0x7f288e995000, 4096) = 0
close(2) = 0
exit_group(0) = ?
即使我们如上所述进行一项操作来获得ls
命令的结果,我们也可以看到很多系统调用是在后台进行的。
ttycopy
我想告诉你这是如何处理的。 该过程的基本流程如下。
- 检查tty登录过程的PID
- 使用strace命令将读取的系统调用检索到PID
- 打印strace输出的读取系统调用的格式化字符串
1.检查tty登录过程的PID
Shell实现如下。
pid=`ps fauwwx | grep sshd.*${tty} | grep -v grep | sed -e 's/^[a-zA-Z0-9]\+[ \n\r\f\t]\+\([0-9]\+\).*/\1/'`
这将使用带有以下过程树的字符串的正则表达式捕获PID,该字符串可以在完成grep后检索到。 您可以使用正则表达式使其看起来很整洁。
[tsuji@localhost ~]$ ps fauwwx | grep sshd.
root 1531 0.0 0.1 82568 6236 ? Ss 15:29 0:00 /usr/sbin/sshd -D
root 2830 0.0 0.2 149824 8916 ? Ss 15:29 0:01 \_ sshd: root@pts/0
root 13315 0.0 0.2 158980 10280 ? Ss 18:58 0:00 \_ sshd: root@notty
root 14956 0.0 0.2 154512 9352 ? Ss 20:10 0:00 \_ sshd: tsuji [priv]
tsuji 14959 0.0 0.1 154512 4092 ? S 20:10 0:00 \_ sshd: tsuji@pts/1
tsuji 15012 0.0 0.0 112672 2268 pts/1 S+ 20:11 0:00 \_ grep --color=auto sshd.
2.使用strace命令将读取的系统调用检索到PID
Shell实现如下。
strace -e read -s16384 -q -xx -p ${pid} 2>&1
我们正在做的是使用跟踪来检索由与刚刚检索的tty相关联的PID发出的读取系统调用。 因为除了读取系统调用之外还调用了其他各种系统调用,所以只有选项-e read
of trace才提取读取的系统调用。
读取的系统调用是下面定义的系统调用,使用starce可以获得的结果也如下。
# include <unistd.h>
ssize_t read( int fd, void *buf, size_t count);
对于在另一个终端登录的用户,请在/tmp
目录中执行ls
命令。
应变端子
# strace -p 14959 -e read
read(0, "l", 1) = 1
read(0, "s", 1) = 1
read(0, "\r", 1) = 1
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=2985, si_uid=1000, si_status=0, si_utime=0, si_stime=0} ---
我们只能获得从标准输入读取的读取系统调用的结果,如上所示。 标准输入是文件描述符编号0。
3.打印由strace输出的读取的系统调用的格式化字符串
目的是显示在步骤2中获得的read系统调用的第二个参数的内容。shell实现如下。
sed -une "s/^read([0-9]\+, \"\(.*\)\".*/echo -n \$'\1'/p" | bash
首先,第一部分sed -une "s/^read([0-9]\+, \"\(.*\)\".*/echo -n \$'\1'/p"
。它捕获了read系统的第二个参数在正则表达式中调用,并为其提供字符串echo -n` and `$''
。
因此,可以实时恢复在扫描终端中执行的命令。
字符串输出到源终端
[tsuji@localhost tmp]$ ls
sample.txt
[tsuji@localhost tmp]$
跟踪处理后要输出的终端字符串。
echo -n $'\x00\x00\x00\x10\x97\xcb\x9f\x29\xb7\x68\xee\xb5\x30\x84\xee\xad\x9d\x73\x52\x01\x17\x63\x30\x62\xe3\xe2\x7e\x61\x26\x64\x5b\x73\x93\x64\x96\xfd'
echo -n $'l'
echo -n $'\x00\x00\x00\x10\x70\x94\x30\xff\x6a\xfa\xbf\xfb\x1a\x1c\x23\x95\x85\x7d\x8f\xa4\xb7\x55\x42\xa4\x8e\x6e\x3e\x3e\xcd\xe4\xd1\xf7\xfb\x05\x5c\xb8'
echo -n $'s'
echo -n $'\x00\x00\x00\x10\x2d\xda\xa7\x40\xa5\xbc\x6a\xf4\x3f\x42\xce\x89\x6d\x3b\x6a\xe1\x16\xe6\x2e\x14\x55\x0d\xdd\x2b\xd8\x9c\xe0\x81\x84\x7d\x8d\x9d'
echo -n $'\r\n'
echo -n $'sample.txt\r\n'
echo -n $'\x1b\x5d\x30\x3b\x74\x73\x75\x6a\x69\x40\x6c\x6f\x63\x61\x6c\x68\x6f\x73\x74\x3a\x2f\x74\x6d\x70\x07\x5b\x74\x73\x75\x6a\x69\x40\x6c\x6f\x63\x61\x6c\x68\x6f\x73\x74\x20\x74\x6d\x70\x5d\x24\x20'
echo -n
的-n
选项是为了避免解释时出现换行。 Bash的$''
形式具有以下效果。 手册页摘录
$'string'形式的单词经过特殊处理。 该单词扩展为字符串,并按ANSI C标准的规定替换反斜杠转义字符。 反斜杠转义序列(如果存在)的解码方式如下:
参考: https : //linux.die.net/man/1/bash
这可以用来扩展为字符串所包含的含义。
剩下要做的就是让shell用| bash
解释echo
字符串| bash
| bash
显示字符串。
摘要
通过使用strace
检索读取系统调用的参数字符串并实时恢复它们,我可以随意共享终端。 我认为ttycopy
非常有用并且是一种教育工具,因为您可以实时查看其他人的作品。 如果要扫描终端,则应尝试一下。
谢谢!
翻译自: https://hackernoon.com/real-time-scanning-of-other-terminals-with-strace-rx9n3yr0
strace使用