写了一个很简单的脚本,用于统计memcache进程的数量:

#!/bin/bash
echo `ps aux | grep memcache | grep -v grep | wc -l`

然而在执行时却遇到了问题:

[work@ oss_memcache_status]$ pwd
/home/work/cdn/monitor/ocelot-scripts/oss_memcache_status
[work@ oss_memcache_status]$ ./run.sh
1
[work@ oss_memcache_status]$ ../oss_memcache_status/run.sh
3

这个原因是因为我们在执行shell脚本时,会通过子进程的方式来执行,而子进程的执行路径字段为:../oss_memcache_status/run.sh,会被grep过滤器留下,因此统计数量比预期要多1个。
解决方案为grep -v bash

执行shell脚本的方式

我们有三种常用的方式执行shell脚本:

  • source run.sh: 会在当前进程下执行脚本,执行时的变量会保存下来。
  • . run.sh: 和source方法基本一样,区别在于source不是POSIX要求的。
  • ./run.sh: 如果脚本以#!/bin/bash开头,会在单独的子进程中执行,执行完毕后变量不保存。否则和source一样。

因此,在上面的脚本中,我们在执行时,因为是以#!/bin/bash开头,会在子进程中执行,我们改动一下脚本看都是哪些进程:

#!/bin/bash
echo `ps aux | grep memcache | grep -v grep`

执行:

work 24414 0.0 0.0 108116 1276 pts/0 S+ 15:31 0:00 /bin/bash ../oss_memcache_status/run.sh
work 24415 0.0 0.0 108116 612 pts/0 S+ 15:31 0:00 /bin/bash ../oss_memcache_status/run.sh
work 30558 0.0 0.0 371236 47096 ? Ssl 2016 15:14 /usr/local/bin/memcached -d -m 256 -u nobody -l localhost -p 11211

我们通过结果,可以看出来,第一个进程和第二个进程的父进程相同,他们都属于当前终端启动的进程。前两个分别为执行run脚本的进程和调起的子进程(这两个什么区别,我也不太清楚),第三个为真正的进程。

防止进程数量增多

解决方案:

  1. 删除脚本头部#!/bin/bash
  2. 增加过滤:grep -v bash
  3. 改变调用方式:source run.sh

参考资料

  1. 执行 shell 脚本时,「source」、「. 」和「./」的区别:https://hoxis.github.io/linux...

赵帅强
3.3k 声望380 粉丝

前端打工人