【问题标题】:Why doesn't "xargs sudo perf top" work as expected?为什么“xargs sudo perf top”没有按预期工作?
【发布时间】:2021-03-08 22:46:10
【问题描述】:

我想分析一个进程,所以首先获取它的 pid,然后使用“perf top”来检查它:

$ pgrep program
14472
$ sudo perf top -p 14472

它按预期工作:

那我想用管道连接这两个命令,所以我用xargs

$ pgrep program | sudo xargs perf top -p

但是这次“perf top”好像不能正常工作: 我比较了这两个操作的流程:
(1) 分别运行pgrepperf

$ ps -ef | grep perf
root      18468  16827  0 09:34 pts/3    00:00:00 sudo perf top -p 14472
root      18469  18468 91 09:34 pts/3    00:00:06 perf top -p 14472
nanxiao   18477  18295  0 09:34 pts/4    00:00:00 grep --color=auto perf

(2)使用xargs连接pgrepperf

$ ps -ef | grep perf
nanxiao   18250  16827  0 09:32 pts/3    00:00:00 xargs sudo perf top -p
root      18251  18250  0 09:32 pts/3    00:00:00 sudo perf top -p 14472
root      18252  18251 87 09:32 pts/3    00:01:47 perf top -p 14472
nanxiao   18442  18295  0 09:34 pts/4    00:00:00 grep --color=auto perf

恕我直言,看起来一样。任何人都可以提供一些线索吗?提前致谢!

P.S.,我的操作系统是CentOS 7

【问题讨论】:

    标签: linux pipe sudo xargs perf


    【解决方案1】:

    再次检查manual后,我发现-o选项可以解决这个问题:

    -o, --open-tty 执行前在子进程中重新打开stdin为/dev/tty 命令。如果您希望 xargs 运行 交互式应用程序。

    命令是这样的:

    $ pgrep program | sudo xargs -o perf top -p
    

    但是很遗憾,CentOS 7xargs 有点老了,不提供这个选项。

    根本原因是:没有-o选项,perf程序的stdin就是/dev/null

    $ sudo lsof -p 1495
    ......
    perf    1495 root    0r      CHR    1,3       0t0     2052 /dev/null
    ......
    

    perf SLang_getkey() 屏蔽:

        ......
        FD_ZERO(&read_set);
        FD_SET(0, &read_set);
    
        if (delay_secs) {
            timeout.tv_sec = delay_secs;
            timeout.tv_usec = 0;
        }
    
        err = select(1, &read_set, NULL, NULL, ptimeout);
    
        if (err == 0)
            return K_TIMER;
    
        if (err == -1) {
            if (errno == EINTR)
                return K_RESIZE;
            return K_ERROR;
        }
    
        key = SLang_getkey();
        if (key != K_ESC)
            return key;
        ......
    

    读取/dev/null 将返回EOF,然后select() 将返回1

    使用-o 选项,perf 程序的stdin/dev/tty

    $ sudo lsof -p 1394
    ......
    perf    1394 root    0u      CHR 136,25       0t0       28 /dev/pts/25
    ......
    

    在上面的代码中,select()会返回0,整个函数也会相应的返回。

    【讨论】:

      【解决方案2】:

      更好的方法是直接在pgrep 的输出上运行top,而不是通过xargs 进行管道传输。我相信top 命令默认不会通过标准输入读取信息

      sudo perf top -p "$(pgrep program)"
      

      这样$(..) 返回pgrep 命令的输出,并将返回值作为位置参数值传递给-p 标志。

      【讨论】:

      • 确实,perf top 似乎被封闭管道的输入破坏了。 cat /dev/null | sudo perf top 永远不会超过“正在收集样本...”,但终端上的 sudo perf top 对我来说正常工作。
      猜你喜欢
      • 2012-03-02
      • 2014-08-04
      • 2021-01-03
      • 2018-11-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多