[英]Bash script kill command in for loop
I want to kill all processes containing some string. 我想杀死所有包含一些字符串的进程。 I wrote script for doing this.
我为此编写了脚本。 However, when I execute it, it gets "Killed" signal after first iteration of for loop.
但是,当我执行它时,它会在for循环的第一次迭代后得到“杀死”信号。 This is my code:
这是我的代码:
#!/bin/bash
executeCommand () {
local pname="$1";
echo $HOSTNAME;
local search_terms=($(ps aux | grep $pname | awk '{print $2}'))
for pros in "${search_terms[@]}"; do
kill -9 "$pros"
echo $pros
done
exit
}
executeCommand "$1" # get the string that process to be killed contains
I execute it like ./my_script.sh zookeeper
. 我像
./my_script.sh zookeeper
一样执行它。 When I delete the line containing kill
command, for loop
executes until end, otherwise, after first kill
command, I get as an output " Killed
" and program exits. 当我删除包含
kill
命令的行时, for loop
执行到结束,否则,在第一个kill
命令之后,我将获得输出“ Killed
”,然后程序退出。
What is possible reason for this, and any other solution to reach my goal? 这可能是什么原因,还有其他解决方案可以达到我的目标吗?
The silly (faulty, buggy) way to do this is to add grep -v grep
to your pipeline: 做到这一点的愚蠢的(错误的,错误的)方法是将
grep -v grep
添加到管道中:
# ${0##*/} expands to the name of the running script
# ...thus, we avoid killing either grep, or the script itself
ps aux | grep -e "$pname" | egrep -v "grep|${0##*/}" | awk '{print $2}'
The better way is to use a tool built for the job: 更好的方法是使用为该工作而构建的工具:
# pkill already, automatically, avoids killing any of its parent processes
pkill "$pname"
That said, matching processes by name is a bad practice to start with -- you'll also kill less yourproc.log
or vim yourproc.conf
, not just yourproc
. 就是说,从名称开始匹配进程是一个坏习惯,一开始,您将杀死
less yourproc.log
或vim yourproc.conf
,而不仅仅是yourproc
。 Don't do it; 不要做 instead, use a proper process supervision system (upstart, DJB daemontools, Apple launchd, systemd, etc) to monitor your long-running daemons and kill or restart them when needed.
相反,请使用适当的过程监控系统(启动程序,DJB daemontools,Apple启动,systemd等)来监视长时间运行的守护程序,并在需要时将其杀死或重新启动。
By the way -- there's no need for a for
loop at all: kill
can be passed multiple PIDs on a single invocation, like so: 顺便说一句-有没有需要一个
for
循环都: kill
都可以通过多种PID的上一个调用,就像这样:
# a bit longer and bash-specific, but avoids globbing
IFS=$'\n' read -r -d '' -a pids \
< <(ps auxw | awk -v proc="$pname" -v preserve="${0##*/}" \
'$0 ~ proc && $0 !~ preserve && ! /awk/ { print $2 }' \
&& printf '\0')
kill -- "${pids[@]}"
...which could also be formulated as something like: ...也可以表述为:
# setting IFS and running `set -f` necessary to make unquoted expansion safe
( IFS=$'\n'; set -f; exec kill -- \
$(ps auxw | awk -v proc="$pname" -v preserve="${0##*/}" \
'$0 ~ proc && $0 !~ preserve && ! /awk/ { print $2 }') )
grep will show , it's own process . grep将显示,这是自己的过程。 it should be removed using grep -v option
应该使用grep -v选项将其删除
Try like this 这样尝试
for i in ` ps -ef | grep "$pname" | grep -v grep | awk '{print $2}'`
do
kill -9 $i
done
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.