Awk not working inside bash script - linux

Im trying to write a bash script and trying to take input from user and executing a kill command to stop a specific tomcat.
...
read user_input
if [ "$user_input" = "2" ]
then
ps -ef | grep "search-tomcat" |awk {'"'"'print $2'"'"'}| xargs kill -9
echo "Search Tomcat Shut Down"
fi
...
I have confirmed that the line
ps -ef | grep "search-tomcat"
works fine in script but:
ps -ef | grep "search-tomcat" |awk {'"'"'print $2'"'"'}
doesnt yield any results in script, but gives desired output in terminal, so there has to be some problem with awk command

xargs can be tricky - Try:
kill -9 $(ps -ef | awk '/search-tomcat/ {print $2}')
If you prefer using xargs then check man page for options for your target OS (i.e. xargs -n.)
Also noting that 'kill -9' is a non-graceful process exit mechanism (i.e. possible file corruption, other strangeness) so I suggest only using as a last resort...
:)

Related

Bash script works locally but not on a server

This Bash script is called from a SlackBot using a Python script that uses the paramiko library. This works perfectly when I run the script locally from the bot. It runs the application and then kills the process after the allotted time. But when I run this same script on a server from the SlackBot, it doesn't kill the process. Any suggestions?? The script name is "runslack.sh" which is what is called with the grep command below.
#!/bin/bash
slack-export-viewer -z "file.zip"
sleep 10
ps aux | grep runslack.sh | awk '{print $2}' | xargs kill
Please try this and let me know if this helps you
ps -ef | grep runslack.sh | grep -v grep | awk '{print $2}' |xargs -i kill -9 {}
and i hope your user has sufficient permission to execute/kill this action on your server environment.

how can I kill a process in a shell script

My bash script has:
ps aux | grep foo.jar | grep -v grep | awk '{print $2}' | xargs kill
However, I get the following when running:
usage: kill [ -s signal | -p ] [ -a ] pid ...
kill -l [ signal ]
Any ideas, how to fix this line?
In general, your command is correct. If a foo.jar process is running, its PID will be passed to kill and (should) terminate.
Since you're getting kill's usage as output, it means you're actually calling kill with no arguments (try just running kill on its own, you'll see the same message). That means that there's no output in the pipeline actually reaching xargs, which in turn means foo.jar is not running.
Try running ps aux | grep foo.jar | grep -v grep and see if you're actually seeing results.
As much as you may enjoy a half dozen pipes in your commands, you may want to look at the pkill command!
DESCRIPTION
The pkill command searches the process table on the running system and signals all processes that match the criteria
given on the command line.
i.e.
pkill foo.jar
Untested and a guess at best (be careful)
kill -9 $(ps -aux | grep foo.jar | grep -v grep | awk '{print $2}')
I re-iterate UNTESTED as I'm not at work and have no access to putty or Unix.
My theory is to send the kill -9 command and get the process id from a sub shell command call.

xargs' $1 conflicts with $1 in shell script

I have these lines in one shell script file foo.sh:
ps ax | grep -E "bar" | grep -v "grep" | awk '{print $1}' | xargs kill -9 $1
when I execute the shell script with an arguments like this:
sh foo.sh arg_one
the xargs can't work now. It takes the $1 from the shell script but not the output of awk.
I do know I can store the output of awk into one file and use it in xargs later.
But, is there any better solution?
== edited ==
thanks the answer from #peterph.
But, is there any way that I can use $1 in xargs?
== edited 2 ==
thanks #Brian Campbell
Despite weather there should be a useless $1 in the example, if a argument of "the shell script file" is given, then the $1 in xargs will not work as my wish, in my computer(In your computer too, I think).
Why? And, how to get avoid it?
xargs reads list from stdin so just discard the last $1 on the line if what you want is to kill processes by their PIDs.
As a side note, ps can also print processes according to their command name (with procps on linux see the -C option).
Instead of that complicated pipeline, you can always use killall -9 name to kill a process, or pkill -9 pattern if you don't know the exact name of the process but know a substring (be careful that you don't kill any unintended processes, though).
For your command to work, just remove the $1; xargs takes its arguments from standard in, and runs the command line passing in the values it gets from standard in at the end of the command.
edit (in response to your edit): What do you expect xargs to do with the $1 argument? What are you expecting to be in it? The only interpretation of $1 that has any meaning here is the first argument that was passed to your script.
The $1 from your awk script is what awk finds in the first column of its input; it then prints that out, and xargs takes those values from standard input, and will call the command you pass it with those values at the end of the command line. So if the awk command returns:
100
120
130
Then piping that result to xargs kill -9 will result in the following being called:
kill -9 100 120 130
You do not need a variable like $1 to make this work
This should work:
ps ax | grep -E "bar" | grep -v "grep" | awk '{print $1}' | xargs kill -9
You can also try:
result=$(ps -ef | grep -E "bar" | grep -v "grep" | awk '{print $2}')
kill -9 $result
In my case piping xargs sometimes returned below error even if matched processes existed:
usage: kill [ -s signal | -p ] [ -a ] pid ...
kill -l [ signal ]
usage: kill [ -s signal | -p ] [ -a ] pid ...
kill -l [ signal ]

Kill random process with name

I want a way to kill a random process with a name (eg a random perl process).
What would be the best way of doing this?
I was thinkign of using something like this:
ps aux | grep PROCESS-NAME
to a file, then find a random line number, get the second column (process ID?) and kill that.
For my use it doesn't actually need to be a random one, as long as it kills one of the processes. Making it random just makes it better.
look at the -r option of the killall command!
Bash one-liner :-p
kill `ps auxww | grep zsh | awk '{print $2}' | while read line; do echo "$RANDOM $line"; done | sort | cut -d ' ' -f 2 | head -n 1`
There's also the 'pidof' command, which can be used to kill with:
kill `pidof processname`
To get just one process when there are multiple with the same name, use -s for "single shot".
It sounded like you were already on the right track.
you can use the following perl script, save it as randomline.pl, which will return a random line from whats piped into it
#!/usr/bin/perl
srand (time ^ $$ ^ unpack "%L*", `ps axww | gzip`);
while (<>) { push(#_,$_); } print #_[rand()*#_];
then run the following command to send the kill command
kill `ps aux | grep PROCESS-NAME | perl randomline.pl | awk '{print $2}'`
You might also want to add in some checking, perhaps with an inverted grep for root to make sure you don't try to kill root level processes that match your process name.
just kill and awk.
kill $(ps -eo cmd,pid|awk '/zsh/&&!/awk/{pid[$NF]}END{for(i in pid){print i;exit}}')
the for loop in the END block will give you you a random pid to kill
with recent bash shell
#!/bin/bash
declare -a pid
pid=( $(pidof myprocess) )
length=${#pid}
rnumber=$((RANDOM%length+1))
rand=$((rnumber-1))
kill ${pid[$rand]}
How about using pgrep and pkill. They allow lot of options to select the processes.
kill process with name "my_proc_name" :
kill -9 `ps xf | grep my_proc_name | grep -v grep | cut -d " " -f 1`
Maybe off topic, but I use this on Cygwin. Inspired by
Lev Victorovich Priyma’s answer
ps -W | awk '/calc.exe/,NF=1' | xargs kill -f
or
ps -W | awk '$0~z,NF=1' z=calc.exe | xargs kill -f

How can I kill a process by name instead of PID, on Linux? [duplicate]

This question already has answers here:
Find and kill a process in one line using bash and regex
(30 answers)
Closed 1 year ago.
Sometimes when I try to start Firefox it says "a Firefox process is already running". So I have to do this:
jeremy#jeremy-desktop:~$ ps aux | grep firefox
jeremy 7451 25.0 27.4 170536 65680 ? Sl 22:39 1:18 /usr/lib/firefox-3.0.1/firefox
jeremy 7578 0.0 0.3 3004 768 pts/0 S+ 22:44 0:00 grep firefox
jeremy#jeremy-desktop:~$ kill 7451
What I'd like is a command that would do all that for me. It would take an input string and grep for it (or whatever) in the list of processes, and would kill all the processes in the output:
jeremy#jeremy-desktop:~$ killbyname firefox
I tried doing it in PHP but exec('ps aux') seems to only show processes that have been executed with exec() in the PHP script itself (so the only process it shows is itself.)
pkill firefox
More information: http://linux.about.com/library/cmd/blcmdl1_pkill.htm
Also possible to use:
pkill -f "Process name"
For me, it worked up perfectly. It was what I have been looking for.
pkill doesn't work with name without the flag.
When -f is set, the full command line is used for pattern matching.
You can kill processes by name with killall <name>
killall sends a signal to all
processes running any of the specified
commands. If no signal name is
specified, SIGTERM is sent.
Signals can be specified either by
name (e.g. -HUP or -SIGHUP ) or by number (e.g.
-1) or by option -s.
If the command name is not regular
expression (option -r) and contains a
slash (/), processes executing that
particular file will be selected for
killing, independent of their name.
But if you don't see the process with ps aux, you probably won't have the right to kill it ...
A bit longer alternative:
kill `pidof firefox`
The easiest way to do is first check you are getting right process IDs with:
pgrep -f [part_of_a_command]
If the result is as expected. Go with:
pkill -f [part_of_a_command]
If processes get stuck and are unable to accomplish the request you can use kill.
kill -9 $(pgrep -f [part_of_a_command])
If you want to be on the safe side and only terminate processes that you initially started add -u along with your username
pkill -f [part_of_a_command] -u [username]
Kill all processes having snippet in startup path. You can kill all apps started from some directory by for putting /directory/ as a snippet. This is quite usefull when you start several components for the same application from the same app directory.
ps ax | grep <snippet> | grep -v grep | awk '{print $1}' | xargs kill
* I would prefer pgrep if available
Strange, but I haven't seen the solution like this:
kill -9 `pidof firefox`
it can also kill multiple processes (multiple pids) like:
kill -9 `pgrep firefox`
I prefer pidof since it has single line output:
> pgrep firefox
6316
6565
> pidof firefox
6565 6316
Using killall command:
killall processname
Use -9 or -KILL to forcefully kill the program (the options are similar to the kill command).
On Mac I could not find the pgrep and pkill neither was killall working so wrote a simple one liner script:-
export pid=`ps | grep process_name | awk 'NR==1{print $1}' | cut -d' ' -f1`;kill $pid
If there's an easier way of doing this then please share.
To kill with grep:
kill -9 `pgrep myprocess`
more correct would be:
export pid=`ps aux | grep process_name | awk 'NR==1{print $2}' | cut -d' ' -f1`;kill -9 $pid
I normally use the killall command.
Check this link for details of this command.
I was asking myself the same question but the problem with the current answers is that they don't safe check the processes to be killed so... it could lead to terrible mistakes :)... especially if several processes matches the pattern.
As a disclaimer, I'm not a sh pro and there is certainly room for improvement.
So I wrote a little sh script :
#!/bin/sh
killables=$(ps aux | grep $1 | grep -v mykill | grep -v grep)
if [ ! "${killables}" = "" ]
then
echo "You are going to kill some process:"
echo "${killables}"
else
echo "No process with the pattern $1 found."
return
fi
echo -n "Is it ok?(Y/N)"
read input
if [ "$input" = "Y" ]
then
for pid in $(echo "${killables}" | awk '{print $2}')
do
echo killing $pid "..."
kill $pid
echo $pid killed
done
fi
kill -9 $(ps aux | grep -e myprocessname| awk '{ print $2 }')
If you run GNOME, you can use the system monitor (System->Administration->System Monitor) to kill processes as you would under Windows. KDE will have something similar.
The default kill command accepts command names as an alternative to PID. See kill (1). An often occurring trouble is that bash provides its own kill which accepts job numbers, like kill %1, but not command names. This hinders the default command. If the former functionality is more useful to you than the latter, you can disable the bash version by calling
enable -n kill
For more info see kill and enable entries in bash (1).
ps aux | grep processname | cut -d' ' -f7 | xargs kill -9 $
awk oneliner, which parses the header of ps output, so you don't need to care about column numbers (but column names). Support regex. For example, to kill all processes, which executable name (without path) contains word "firefox" try
ps -fe | awk 'NR==1{for (i=1; i<=NF; i++) {if ($i=="COMMAND") Ncmd=i; else if ($i=="PID") Npid=i} if (!Ncmd || !Npid) {print "wrong or no header" > "/dev/stderr"; exit} }$Ncmd~"/"name"$"{print "killing "$Ncmd" with PID " $Npid; system("kill "$Npid)}' name=.*firefox.*

Resources