免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
12345
最近访问板块 发新帖
楼主: 93237984
打印 上一主题 下一主题

shell的困惑 [复制链接]

论坛徽章:
0
41 [报告]
发表于 2006-04-06 16:42 |只看该作者
to waker:
我刚才用
a=$(ps -ef)
echo "$a"|grep proc...|grep -v grep|wc -l
是没问题的,第一次运行返回1,第2次返回2。但我把它改成下面那样放到脚本里运行时就有问题了!
看看我的脚本:
procname=processctl
a=$(ps -ef)

ifrunning=`"$a"|grep -w $procname|grep -v grep|wc -l`

echo $ifrunning
if [ $ifrunning -gt 1 ]; then  
  echo "the process is running!"
  sleep 10
  exit
else
   echo "start!"
   sleep 10
fi

我从两个终端执行%sh processctl但是返回的$ifrunning都变成0,从第三个终端进去查看发现有两个进程在运行。而且每次执行sh processctl 时开始都会先返回一大堆进程,然后才返回0,start!

论坛徽章:
1
荣誉会员
日期:2011-11-23 16:44:17
42 [报告]
发表于 2006-04-06 18:40 |只看该作者
原帖由 waker 于 2006-4-6 15:51 发表
...
每个pipeline都需要一个额外的subshell
这个subshell process的cmdline 都是 $0

如果你用
ps -ef |grep $0|.....|....|
相信会得到5,6,7个 ...

很有启发!我想的确是subshell造成的问题,不光是管道,还有进程替换都会造成的问题,因为它们都会生成子进程。不过子进程的名字并不是当前脚本的$0参数,而是各自子命令的命令行,于是grep就会找到多余的匹配了。

让我们在脚本中加入几级管道看看:
  1. cmdsubsted1=`ps -ef|grep [p]rocessctl|grep [p]rocessctl|grep [p]rocessctl|grep [p]rocessctl|wc -l`
  2. echo \$cmdsubsted1= $cmdsubsted1
复制代码

可以看到输出
$cmdsubsted1=2
并没有增加额外的匹配。因为多余加进去的管道中的每一级,命令行都不能匹配processctl。

如果去掉grep的正则中的方括号:
  1. cmdsubsted2=`ps -ef|grep processctl|grep processctl|grep processctl|grep processctl|wc -l`
  2. echo \$cmdsubsted2= $cmdsubsted2
复制代码

这样会输出:
$cmdsubsted=6
增加了4个匹配,因为加入的4个grep的命令行能够匹配processctl。

如果不用进程替换,并且grep的命令行字串不匹配processctl,我们就不会得到多余的匹配:
  1. ps -ef|grep [p]rocessctl|wc -l > tmp
  2. nocmdsubst=`cat tmp`
  3. echo \$nocmdsubst= $nocmdsubst
复制代码

会输出
$cmdsubsted=1

你的解决方法也是同样,而且更高效些:
a=$(ps -ef)
echo "$a"|grep proc...|grep -v grep|wc -l

同样命令替换的一句并没有生成含有我们要查找的"processctl"字样的子进程,之后的管道虽会生成子进程,但这时我们是由变量$a而不是ps的结果来查找匹配,所以不会有问题。


说明:水很深啊!在不同的软件、硬件平台下,不同的shell下测试结果可能不同。最好的解决办法还是上面最后引用waker的一个。

很牛的问题,让人头脑发晕!^_^

[ 本帖最后由 woodie 于 2006-4-6 20:04 编辑 ]

论坛徽章:
0
43 [报告]
发表于 2006-04-06 19:48 |只看该作者
老兄,帮我看看41楼的问题

论坛徽章:
1
荣誉会员
日期:2011-11-23 16:44:17
44 [报告]
发表于 2006-04-06 19:52 |只看该作者
原帖由 93237984 于 2006-4-6 19:48 发表
老兄,帮我看看41楼的问题

你掉了点东西:
`"$a"|... ===> `echo "a"|...

论坛徽章:
0
45 [报告]
发表于 2006-04-06 20:04 |只看该作者
我在两个终端分别启动了两次processctl,返回的$ifrunning值都是0,然后打开第三个终端查看有两个进程同时存在

论坛徽章:
0
46 [报告]
发表于 2006-04-06 20:26 |只看该作者
终于搞定了:

procname=processctl
a=$(ps -ef)

ifrunning=`echo "$a"|grep -w $procname|grep -v grep|wc -l`

echo $ifrunning
if [ $ifrunning -gt 1 ]; then  
  echo "Alert: You can not start the process twice!"
  sleep 10
  exit
else
  echo "Start Success!"
  sleep 5
fi

论坛徽章:
0
47 [报告]
发表于 2006-04-06 20:30 |只看该作者
以后要用到控制进程重复的时候估计上面的方案应该是可行的了!

论坛徽章:
0
48 [报告]
发表于 2006-04-07 17:14 |只看该作者
fork出来的subshell,返回两个值,一个是返回给父进程(PPID)的一个subshell PID ,一个是返回subshell 0;

to
每个pipeline都需要一个额外的subshell
这个subshell process的cmdline 都是 $0

如果你用
ps -ef |grep $0|.....|....|
相信会得到5,6,7个 ...
俺觉得他说的非常的好。也理解了一下,确实是这个样子的。

论坛徽章:
0
49 [报告]
发表于 2011-05-05 01:22 |只看该作者
回复 38# waker


    a=$(ps -ef)
echo "$a"|grep proc...|grep -v grep|wc -l

上面这一条echo "$a"|grep proc...|grep -v grep|wc -l 跟 echo "$a"|grep proc...|wc -l  是不是等价呢? grep -v grep 这个是不是多余的呢?
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP