ps:干净的方式只获得父进程?

时间:2012-09-11 15:36:53

标签: linux bash shell command-line ps

我经常使用ps efps rf

以下是ps rf的示例输出:

  PID TTY      STAT   TIME COMMAND
 3476 pts/0    S      0:00 su ...
 3477 pts/0    S      0:02  \_ bash
 8062 pts/0    T      1:16      \_ emacs -nw ...
15733 pts/0    R+     0:00      \_ ps xf
15237 ?        S      0:00 uwsgi ...
15293 ?        S      0:00  \_ uwsgi ...
15294 ?        S      0:00  \_ uwsgi ...

今天我只需要在脚本中检索uwsgi的主进程(因此我只需要15237但不需要15293或15294)。

截至今天,我尝试了一些ps rf | grep -v ' \\_ ' ...但我想要一种更清洁的方式

我也来自unix.com论坛的另一个解决方案:

ps xf | sed '1d' | while read pid tty stat time command ; do [ -n "$(echo $command | egrep '^uwsgi')" ] && echo $pid ; done

但仍然是很多管道丑陋的技巧

是否真的没有ps选项或更干净的技巧(可能使用 awk )来实现这一目标?

9 个答案:

答案 0 :(得分:8)

在与@netcoder讨论他的回答后,他用了一个很好的伎俩:D
f上使用ps将始终将父级置于最佳状态。

这应该可行:

$ ps hf -opid -C <process> | awk '{ print $1; exit }'

正如我在评论中提到的那样,这将只返回一个进程的pid


我会选择:

ps rf -opid,cmd -C <process-name> | awk '$2 !~ /^[|\\]/ { print $1 }'

即:

  • 列出正在运行的流程r(或e如果您需要所有内容)
  • 以及父/子图f
  • 仅输出pid和命令名称-opid,cmd
  • 仅适用于给定流程-C <process>

然后

  • 如果第二个字段 - 这是命令(-opid,cmd) - 不是以\|开头那么它是父进程,那么打印第一个字段 - 是pid。

简单测试:

$ ps f -opid,cmd -Cchromium
  PID CMD
 2800 /usr/lib/chromium/chromium --type=zygote --enable-seccomp-sandbox
 2803  \_ /usr/lib/chromium/chromium --type=zygote --enable-seccomp-sandbox
 2899      \_ /usr/lib/chromium/chromium --type=renderer --enable-seccomp-sandbox --lang=en-US --force-fieldtrials=ConnCountImpact/conn_count_6/ConnnectB
 2906      |   \_ /usr/lib/chromium/chromium --type=renderer --enable-seccomp-sandbox --lang=en-US --force-fieldtrials=ConnCountImpact/conn_count_6/Connn
 [  ... snip ... ]
 2861      \_ /usr/lib/chromium/chromium --type=renderer --enable-seccomp-sandbox --lang=en-US --force-fieldtrials=ConnCountImpact/conn_count_6/ConnnectB
 2863          \_ /usr/lib/chromium/chromium --type=renderer --enable-seccomp-sandbox --lang=en-US --force-fieldtrials=ConnCountImpact/conn_count_6/Connn
 2794 /usr/lib/chromium/chromium --enable-seccomp-sandbox --memory-model=low --purge-memory-button --disk-cache-dir=/tmp/chromium
 2796  \_ /usr/lib/chromium/chromium --enable-seccomp-sandbox --memory-model=low --purge-memory-button --disk-cache-dir=/tmp/chromium
 3918  \_ /usr/lib/chromium/chromium --type=gpu-process --channel=2794.45.1891443837 --gpu-vendor-id=0x10de --gpu-device-id=0x0611 --gpu-driver-version -
25308  \_ [chromium] <defunct>
31932  \_ /usr/lib/chromium/chromium --type=plugin --plugin-path=/usr/lib/mozilla/plugins/libflashplayer.so --lang=en-US --channel=2794.1330.1990362572


$ ps f -opid,cmd -Cchromium | awk '$2 !~ /^[|\\]/ { print $1 }'
PID
2800
2794

$ # also supressing the header of ps (top line 'PID') -- add 'h' to ps
$ ps hf -opid,cmd -Cchromium | awk '$2 !~ /^[|\\]/ { print $1 }'
2800
2794

答案 1 :(得分:2)

/usr/bin/pgrep -o <process_name>

其中&#39; -o&#39;是匹配过程中最早的(最近最少开始的)

答案 2 :(得分:0)

为什么不直接使用--pidfile选项将master的pid保存在文件(pidfile)中?如果它不是一个可行的解决方案,您可以使用--procname-master为主进程提供自定义名称。

对于那种事情使用ps是非常不可靠的(遍布各地的竞争条件,以及使解析规则无效的特殊情况......)

答案 3 :(得分:0)

另一种解决方案(来自here):

ps -ocommand= -p $PPID | awk -F/ '{print $NF}' | awk '{print $1}'

答案 4 :(得分:0)

获取进程的主进程ID是另一种解决方案。但是很好。

pstree -p 1 |grep <proc_name>|sed -n 1p|tr -d "|,-"|sed 's/(/ /g'|sed 's/)/ /g'|tr -d "+"|awk {'print $2'};

答案 5 :(得分:0)

如果你可以放心地假设你只有一个父母进程有n个孩子,或者你只关心最早的&#39;几个父进程(最低PID),然后我认为这个更简单的解决方案工作正常。

ps h -opid -C<commandname> | head -1

答案 6 :(得分:0)

按文件名(输出父母人数)

o=""; for p in $(pgrep -f example.sh); do o="${o}$(pstree -lp | grep -nF \($p\))\n"; done; echo -e "$o" | cut -f2 -d: | cut -f2 -d- | sort -n | grep -vE ^$ | uniq -c | awk '$1>0' | wc -l

修改:我以前使用过

| cut -f1 -d: |

但是显然,不能保证子进程会接连进行,所以我最后用父进程的名称和pid来计数:

| cut -f2 -d: | cut -f2 -d- |

答案 7 :(得分:0)

所有父母的ps fuxa | grep 'PID\|[0-9] /'怎么样,或者: ps fuxa | grep '[0-9] /' | grep 'PID\|<commandname>'用于单个过程?

答案 8 :(得分:-1)

从关键词KEYWORD

ps aux | grep -i KEYWORD | grep -v grep | awk '{print $2}'|sort -h|head -1|xargs kill
BTW,假设父进程ID是有效的最小ID ????