Chinaunix

标题: 关于bash代码传参的问题 [打印本页]

作者: jiaxinhuayuan    时间: 2016-06-22 14:44
标题: 关于bash代码传参的问题
本帖最后由 jiaxinhuayuan 于 2016-06-22 14:45 编辑

想写一个shell脚本自动杀掉tomcat进程,使用了下面代码:
pid=`ps aux|grep $1|grep -v "grep"|awk '{print $2}'`
kill -9 $pid
其中$1是传入的tomcat进程关键字,发现$1可以传入,但是pid获取有错,求助这样的需求应该如何实现?
需求:tomcat进程名是传入的,不可能写死,根据这个杀掉对应的进程。谢谢各位!
作者: Shell_HAT    时间: 2016-06-22 15:01
ps aux|grep $1|grep -v "grep"
ps aux|grep $1|grep -v "grep"|awk '{print $2}'
把这两个命令的结果分别发出来,看看是哪一步出问题了。
作者: hz_oracle    时间: 2016-06-22 15:11
$1是外部传入的?不需要吧,你直接抓tomcat进程,然后取pid不行吗?
作者: jiaxinhuayuan    时间: 2016-06-22 15:17
脚本是这样写的:
#/bin/bash
echo $1
pid=`ps aux|grep $1|grep -v "grep"|awk '{print $2}'`
echo $pid
kill -9 $pid
命令执行是:bash -x test.sh tomcat
结果是:
+ echo tomcat
tomcat
++ ps aux
++ grep tomcat
++ grep -v grep
++ awk '{print $2}'
+ pid='23180
23069
23181'
+ echo 23180 23069 23181
23180 23069 23181
+ kill -9 23180 23069 23181
Killed: 9

如果换成:ps aux|grep $1|grep -v "grep"的话结果是这样的:
+ echo tomcat
tomcat
++ ps aux
++ grep tomcat
++ grep -v grep
pid='***           23189   0.0  0.0  2443624    520 s003  S+    3:14下午   0:00.00 bash -x test.sh tomcat
之类的,后面还有很多。
PS:如果不传参数,直接在终端执行ps aux |grep "tomcat" |grep -v "grep" |awk '{print $2}'是可以的。
求解
回复 2# Shell_HAT


   
作者: jiaxinhuayuan    时间: 2016-06-22 15:19
这样的话可能有多个tomcat进程了,会误杀掉别的,我需要只杀掉我想杀的,比如"tomcat-ship"这样就只有一个了回复 3# hz_oracle


   
作者: jiaxinhuayuan    时间: 2016-06-22 15:20
所以需要外部传入的回复 3# hz_oracle


   
作者: hz_oracle    时间: 2016-06-22 15:26
回复 5# jiaxinhuayuan


    那是你定位不准确啊。你要杀掉tomcat-ship为啥传参数传的是tomcat?
作者: jiaxinhuayuan    时间: 2016-06-22 15:27
我是举个例子,实际上我传tomcat这个参数已经唯一确定了回复 7# hz_oracle


   
作者: jiaxinhuayuan    时间: 2016-06-22 15:28
但有的时候当然不是喽,所以这个地方需要外部传入,保证唯一性回复 7# hz_oracle


   
作者: hz_oracle    时间: 2016-06-22 15:31
回复 9# jiaxinhuayuan


    不清楚你想表达什么意思。 你要kill掉tomcat-ship 那传入参数就写tomcat-ship啊。。否则你怎么保证抓到的pid唯一性?
作者: jiaxinhuayuan    时间: 2016-06-22 15:33
你可以按照我写的那个代码试一下,我的意思是即使传入的是tomcat-ship,也是报一样的错误,换句话说我的意思是我传入的参数已经保证唯一pid了,但是执行还是错误回复 10# hz_oracle


   
作者: hz_oracle    时间: 2016-06-22 15:38
回复 11# jiaxinhuayuan

这个问题好像我之前遇到过,你不要grep,用其他命令取pid试试
   
作者: riet2    时间: 2016-06-22 16:25
话说你到底报的啥错。
作者: seanking1987    时间: 2016-06-22 16:54
看了帖子的所有回复,LZ描述的不清楚啊。
LZ回复中给的例子pid是grep到了多个造成的执行错误,然而后面又说带入的参数,grep是能够保证唯一性的?
那么现在脚本执行的问题到底是什么?
作者: jiaxinhuayuan    时间: 2016-06-22 17:52
本帖最后由 jiaxinhuayuan 于 2016-06-22 17:53 编辑

需求比较清晰简单,就是传入参数,这个参数就是进程名,根据这个参数找到对应的进程,然后杀掉,怎么实现?回复 14# seanking1987


   
作者: seanking1987    时间: 2016-06-23 08:53
本帖最后由 seanking1987 于 2016-06-23 08:56 编辑

回复 15# jiaxinhuayuan


试了一把shell,知道你的意思,我想LZ应该把出现的问题描述的更清楚一些。
系统只启了一个tomcat进程,shell代码:
  1. #!/bin/bash

  2. proName=$1
  3. pid=`ps aux|grep ${proName}|grep -v "grep"|awk '{print $0}'`
  4. echo "$pid
复制代码
运行结果:
  1. user   27193  0.0 29.8 552492 308864 ?       Sl   May13  30:27 tomcat/org.apache.catalina.startup.Bootstrap start
  2. user1   30401  0.0  0.1   5204  1060 pts/1    S+   08:53   0:00 sh test1.sh tomcat
  3. user1   30402  0.0  0.0   5204   464 pts/1    R+   08:53   0:00 sh test1.sh tomcat
复制代码
全部打印出来就发现问题,3个pid包含了shell运行的pid,那么脚本改造一下:
  1. #!/bin/bash

  2. proName=$1
  3. shellName=$0
  4. pid=`ps aux|grep ${proName}|grep -v "grep"|grep -v "$shellName"|awk '{print $0}'`
  5. echo "$pid"
复制代码
运行结果:
  1. user   27193  0.0 29.8 552492 308864 ?       Sl   May13  30:27 tomcat/org.apache.catalina.startup.Bootstrap start
复制代码
此时得到的结果是正确的
作者: 251744647    时间: 2016-06-23 10:54
本帖最后由 251744647 于 2016-06-23 10:56 编辑

这样要保证shell文件名最好不要带数字,tomcat等字样.比如你shell file 名字为tomcat这样,grep -v tomcat, 连tomcat的进程都过滤掉了,结果返回为空。名字不用数字的道理是一样的,进程ID嘛。回复 16# seanking1987


   
作者: seanking1987    时间: 2016-06-23 10:59
回复 17# 251744647


你说的没错。目前属于能解决问题,并非“完美”解决问题。在shell脚本的命名上,仍应注意你说的注意点。
等待大神来给个“完美”的方法吧,我是抛砖引玉~~


作者: 251744647    时间: 2016-06-23 11:07
pidof running program 即可。

man pidof
NAME
       pidof -- find the process ID of a running program.

SYNOPSIS
       pidof  [-s]  [-c] [-n] [-x] [-m] [-o omitpid[,omitpid..]]  [-o omitpid[,omitpid..]..]
       program [program..]


   
作者: 251744647    时间: 2016-06-23 11:15
another way is using sub-shell

[root@xxx]# cat filehh
#!/bin/bash
pid=(`ps -ef |grep $1|grep -v "grep"|awk '{print $2}'`)
echo "the first parameter is $1, the second parameter is $2"
echo "pid is $pid"
echo "-----------------------------"
ps -ef |grep $1|grep -v "grep"|grep -v $0|awk '{print $2}'
[root@xxx]# ps -ef |grep test11 |grep -v "grep" |awk '{print $2}'
42884
[root@xxx]# bash filehh test11
the first parameter is test11, the second parameter is
pid is 42884
-----------------------------
42884
[root@joey-compute azureuser]#


回复 15# jiaxinhuayuan


    pid=(`ps -ef |grep $1|grep -v "grep"|awk '{print $2}'`)
作者: woid31846    时间: 2016-06-24 08:51
kill -9 "$pid" 就可以了. 不然你PID匹配到了多个.
要不然就改成
ps aux|grep $1|grep -v "grep"|awk '{print $2}'|xargs kill -9
作者: ll104567    时间: 2016-06-24 09:17
seanking1987 发表于 2016-06-23 08:53
回复 15# jiaxinhuayuan

结合16楼的想法,用grep过滤的时候排除脚本名字`basename $0`、然后再用kill杀就行了




欢迎光临 Chinaunix (http://bbs.chinaunix.net/) Powered by Discuz! X3.2