【问题标题】:How can I spy on communication between a process and a terminal?如何监视进程和终端之间的通信?
【发布时间】:2010-08-04 22:24:27
【问题描述】:

我有一个由第三方开发的与终端通信的 Linux 进程。对于调试,我希望看到通信返回。

有人可能会认为cat 可以解决问题(看到一个方向):

    ./third-party-app &
    cat /dev/tty

...但事实并非如此。相反,cat 将窃取一半用于应用程序的数据,这几乎毫无价值。

第三方应用被硬编码为/dev/tty

我发现监视通信的一种方法是将/dev/tty 设备重命名为/dev/real_tty,并在其位置创建一个名为/dev/tty 的命名管道。然后运行:

    cat /dev/real_tty | tee /dev/tty &

...至少可以让我看到/dev/real_tty 的输出,方法是将数据从/dev/real_tty 复制到命名管道/dev/ttystdout

这种方法很有效,但感觉很狡猾,并且依赖于更换设备的诡计。它也不能双向工作,因为命名管道只能在一个方向上传输数据。

这样做的正确方法是什么?

如果有人想知道,TTY 设备是与微控制器的 RS-232 链接。该信息不敏感或不安全。所有进程(应用程序和间谍)都可以以 root 身份运行。

【问题讨论】:

    标签: linux terminal embedded-linux tty pty


    【解决方案1】:

    您是否考虑过使用strace/ltrace?您可以看到它正在执行的系统调用,特别是您可以看到正在执行的 write/ioctl 等调用。

    【讨论】:

      【解决方案2】:

      RS-232?只需用夹子轻敲 RxD/TxD/GND 线。自从我看到任何设备甚至关心 DCD、DTR 等,这已经是很长时间了。

      【讨论】:

      • 那是作弊! :)。绝对可以,但是让 RS-232 输出与第三方应用程序的标准输出调试消息交错对解决时序问题非常有帮助。
      【解决方案3】:

      您可以查看slsnif。它完全符合您的要求,或者如果您有兴趣自己编写一个源代码,可以查看它是如何工作的。

      【讨论】:

      • 很好的建议。我去看看情况如何。
      • 它至少完成了一半的工作而不会从流中“窃取”数据,尽管它没有显示数据正在发送到串行端口。我可能还没有找到合适的选择。
      • 令人讨厌的是,我之前至少必须这样做一次(它是记录一个通过 ssh 的进程),但我找不到任何关于我是如何做到的或记住细节的注释。稍微复杂一点的方法是使用伪 ttys。模糊的记忆说,一对以 /dev/tty 打开(可能使用符号链接,因为它们有奇怪的名称 /dev/pttym 和 /dev/pttyc),另一端连接到真正的 tty 设备。它更复杂,因为您需要编写一个 C 包装器来选择 FD 并在将副本保存到磁盘时来回传递块。
      【解决方案4】:

      有一些选择:

      使用 GDB 自己动手:Redirecting Output from a Running Process

      CryoPID 允许您捕获 Linux 中正在运行的进程的状态并将其保存到文件中。然后,此文件可用于稍后在重新启动后或什至在另一台计算机上恢复该过程。

      Distributed MultiThreaded CheckPointing 是一个透明的工具 检查点传播的任意程序组的状态 跨多台机器并通过套接字连接。

      【讨论】:

      • 问题不在于标准输出。它是关于应用程序写入特定设备,特别是微控制器的链接。
      • 关闭,但我认为不会这样做。我对输入和输出都感兴趣。应用程序可能使用单个文件描述符来读取和写入 TTY,然后我遇到了与之前命名管道相同的问题。 TTY 不是标准输入/标准输出。我还希望有一些比使用 gdb 侵入性更小的东西....
      • @Moron 那又怎样?您没有必须选择 1 作为您替换的 fd 的编号 :)
      • @hobbs:如果它是应用程序执行一些 ioctl 的设备,那么重定向到管道可能不起作用!我希望你现在明白我的意思。
      • @Moron:好点——该应用确实使用 ioctl 来配置 RS-232 波特率
      【解决方案5】:

      script 程序可以使用 psudo 终端执行此操作。设备/dev/tty 通常是特殊的,它指的是当前进程的控制终端,因此您可能不必求助于重命名。

      script 打开一个伪终端,然后以该新 shell 作为其控制终端运行你的 shell 的另一个实例(因此/dev/tty 指的是这个 shell 及其子进程的这个伪终端)。 -c 选项允许您运行特定命令而不是您的 shell。

      script 的主要问题是无法判断在输出文件(默认为./typescript)中捕获的数据的走向——双向流动的数据被转储到同一个文件并且看起来相似使用交互式终端时屏幕上显示的内容(除了包括转义、回车和类似的愚蠢的东西以及正常显示的字符)。

      无论如何,我知道这个问题早已得到解答,但我认为如果有人要搜索类似的解决方案并且不使用真正的串行端口,这可能会对他们有所帮助。

      【讨论】:

        【解决方案6】:

        不简单(至少对我来说不是),但应该适用于 tty 串行驱动程序的机制是 line discipline

        【讨论】:

          【解决方案7】:

          这里的人已经提出了很好的建议,但这里还有一个:

          您还可以使用自己的write() 编写一个共享库,在从libc.so 调用write() 之前完成一些工作。然后你可以使用LD_PRELOAD 环境变量在进程启动时加载你的库。

          【讨论】:

          • s/LDD_PRELOAD/LD_PRELOAD/ 不幸的是,即使是语法错误修复,SO 也不允许进行单字符编辑,所以我必须使用评论,抱歉。
          • @arielf - 你是对的。已编辑。虽然 5 年后回头看,但我认为这不是一个很好的答案。
          • :) 我认为如果它更完整的话可能是一个很好的答案。包括一个实际工作的代码 sn-p(例如,write 在调用具有相同名称的 libc 入口点时如何避免调用自身)和编译行以创建预加载的模块。这是非常有价值的,因为它是许多类似问题的通用解决方案:“如何稍微修改 libc 中已经存在的内容。”
          猜你喜欢
          • 2014-11-06
          • 1970-01-01
          • 2018-02-10
          • 2018-09-16
          • 1970-01-01
          • 1970-01-01
          • 2016-07-23
          • 2014-07-20
          • 1970-01-01
          相关资源
          最近更新 更多