首页 > 解决方案 > 在 ps 中列为 (bash) 的进程,尽管会立即对其进行监控

问题描述

我正在尝试获取一些短期进程的进程信息,所以我制作了一个测试脚本来帮助我。

我启动了一个后台任务,该任务运行一个连续循环,将输出管道ps传输到awk以查找新进程。循环运行的速度与处理器允许的速度一样快。为了测试我的程序,我启动了我的脚本,然后运行了一些后台sleep任务。像这样:

watchPIDs 10
sleep 1&
sleep 2&
sleep 3&

上面的10意思是让我的脚本运行10秒。尽管循环运行的速度与处理器允许的一样快,但我认为一些睡眠命令在某些东西注册之前“生死攸关”,它弄乱了我的结果......有时我看到sleep 1上面示例中的过程显示as (bash)(用括号括起来bash)而不是sleep 1.

谷歌搜索括号命名法会出现以下结果:

括号表示命令覆盖了它的名称,或者 ps 找不到名称,而 ps 正在打印“accounting name”。

我不太确定这是否适用于这里,或者我不理解某些东西......这可能是我不理解的脚本中的一些错误......否则,我为什么不总是得到这个名字sleep 1对于那个过程,当我几乎可以肯定我的脚本运行得足够快以在它死之前“看到”那个过程时(毕竟,它确实PID适合那个过程)?

这是我的代码(主要是awk):

watchPIDs()
{
    [ "${1}" ] || { echo "No time duration specified, exiting..."; return -1; }
    set +bm
    end=$(( `date +%s` + ${1} ))
    {
        while [ `date +%s` -lt ${end} ]; do ps -o pid=,ppid=,pgid=,command=; done |
        exec awk ' BEGIN { fmt = "%-10.10s%-10.10s%-10.10s %-.70s\n"; }
        {
            old=0
            for ( pid in pids ) if ( pids[pid] == $1 ) { old = 1; break; }
            if ( old == 0 ) {
                pids[i++] = $1
                match($0, " *" $1 " +" $2 " +" $3 " " )
                pidInfo[i-1] = sprintf(fmt, $1, $2, $3, substr($0, RLENGTH))
            }
        } END {
            print ""
            printf fmt, "PID", "PPID", "PGID", "Command"
            for ( j = 0; j < i; j++ ) printf "%s", pidInfo[j]
        }' &
    } 2>/dev/null
}

示例输出,上面列出的测试用例:

PID       PPID      PGID       Command
62246     62245     62246       -bash
62573     62246     62246       -bash
62574     62246     62246       awk  BEGIN { fmt = "%-10.10s%-10.10s%-10.10s %-.70s\n"; }\012        
63097     62246     62246       (bash)
63552     62246     62246       sleep 2
63985     62246     62246       sleep 3

谢谢!

标签: bashawkprocessbackground-processps

解决方案


要运行sleep,Bash 将首先调用fork(),然后在子进程中调用execve()以将自身替换为sleep. 所以 和 之间forkexecve子进程名称仍然是bash.

(我不知道是谁添加了括号。)


推荐阅读