Register
It is currently Sat May 30, 2015 4:50 am

kill a process by name: namekill


All times are UTC - 6 hours


Post new topic Reply to topic  [ 2 posts ] 
Author Message
 PostPosted: Tue May 26, 2015 4:44 pm   

Joined: Mon Sep 26, 2011 10:17 pm
Posts: 6
to kill a process by name, I am used to this:
Code:
[nodots@localhost ~]$ lsof | grep -m1 ^programname
programname   4242       nodots  cwd       DIR                8,5     4096   157206 /home/nodots
[nodots@localhost ~]$ kill 4242

but no I type "namekill programname" and it asks me if I want to kill. A partial name can work too, like "kons" for "konsole".
Do read what it asks though, as it stops searching at the first match.

Code:
#!/bin/bash

if [ "$1" == '' ]; then exit; fi
if [ "$1" != '' ]; then finder="$1"; fi
line=`lsof | grep -m1 ^$finder | sed 's/ \+/ /g'`
pname=`echo $line | cut -d' ' -f1`
pid=`echo $line | cut -d' ' -f2`
if [ "$pid" != '' ]; then echo "$pname, pid=$pid"; fi
if [ "$pid" == '' ]; then echo "file not open: $finder"; fi
if [ "$pid" != '' ]; then
    read -p "Do you want to kill \"$pname\"? " -n 1 -r
    echo
    if [[ $REPLY =~ ^[Yy]$ ]]; then kill "$pid"; fi
fi


Top
 Profile  
 PostPosted: Wed May 27, 2015 6:54 am   

Joined: Mon Oct 20, 2014 9:53 am
Posts: 128
If you deal with processes, use the tools programed to deal with processes.
killall programname kills each instance of "programname"
pgrep programname gives all pids of "programname" (ProcessGREP)

To use lsof for this is a bad idea. It spits out a lots of entries. Think of the case if only "ba" is given as input, when searching for bash.
You end up with name and pid from any running balo* as well (balo* are KDE search thingies)
If you delimit output to one line (grep -m1), you will rarely hit the process you want to hit.
And you are using lots of pipes with echo and cut very unnecessary.

To avoid all these problems try:
Code:
lsof | grep  ^programname  | awk '{print $1 " " $2}' | uniq |  \
    while read programname pid; do
            echo "found program \"$programname\" with pid $pid"
    done
Like in your solution it starts with lsof and greps all lines starting ^ with programname. From this output we use a little awk script '{ to print the first field $1 followed by a blank " " followed by the second field $2 and the script is finished }'. But we still got much too much lines of output. Hence we pipe this output to uniq and condense the output to the result we are really after. These few line are piped to a while loop, which reads it into the two vars programname and pid.

Another solution could be:
Code:
#!/usr/bin/env bash

# copyright © CC-BY-NC-SA karl.thomas.schmidt@googlemail.com

# check for arguments. If none given, ask user
if [[ $# == 0 ]]; then
   read -p "Please enter program name : " temp
   programname=( $temp ) # split $temp into an array
else
   programname=( $* )  # we save arguments in an array
                       # no matter how many given
fi

# now we loop over all entries in array "programname"
for p in ${programname[*]}; do
   # each entry of "instances" is a pid of "$p"rogramname[]
   # pgrep finds all "$p"rograms and spits out pid
   # using "tr" to eliminate the newline to easily fill array
   instances=( $( pgrep $p | tr '\n' ' ' ) )
 
   # if "instances" has no entries, this still does not say, that
   # there is no running instance of any interpreter script
   # in these cases we got for instance "bash" as cmd and the
   # scriptname "mysuperscript" shows up in the args list of bash
   # so we do an extended search. This times we search entire command line
   if [[ ${#instances} == 0 ]]; then  #nothing found
      # "ps ax" spits out ALL processes of ALL users.
      # "h" omits the header line
      # and "-o"utput format is <pid><entire command line>
      # we grep out the "$p"program line
      # and let "awk" print the first field i.e. the pid
      # for easy filling the array "instances"
      # we set at the "BEGIN"ning the "O"utput"R"ecord"S"eparator
      instances=( $( ps ax h -o pid,args | grep $p | awk 'BEGIN{ORS="\n"}{print $1}' ) )
   fi

  # building the comma separated pid string, which we use later
   pidstring=$(printf "%s," ${instances[*]} )

   # strip trailing "," from $pidstring.
   # see "man bash" chapter PARAMETER EXPANSION
   pidstring=${pidstring::-1}
 
   # now we prepare interactive part to let user choose which
   # instance to kill.
   # to give the user a clue what each instance is about,
   # we get the entire command line
   # again we save the command lines into an array
   # we use "ps -p $pid -o cmd" for this.
   # "-p" awaits a pid or a comma separated list of pids
   # "-o" formats the output and "cmd" is a named parameter for "-o"
   # and "args" gives the entire commandline
   # the single "h" omits the header line
   # and now we fill the array "cmdlines"
   IFS=$'\n' cmdlines=( $( ps -p $pidstring h -o args  ) )
   
   # btw "pgrep -a someprogram" gives the entire commandline too
   # just wanted to demonstrate usage of very mighty "ps" command
   
   # PS3 is used as prompt by "select"
   PS3="Enter number of command to kill (press <ctrl+d> when done) : "

   # count of all instandes found.
   num=${#cmdlines[*]}
   
   if [[ $num > 1 ]]; then # we display menu to choose from
      # read "help select" to understand what's going on
      select w in "${cmdlines[@]}"; do  # we pass all "cmdlines" to menu
         # windows style. are you really, really sure?
         read -p "do you want to kill \"$w\"? (y|n) : " confirm
         if [[ $confirm == "y" ]]; then
            echo killing process \"$p\"
         elif [[ $confirm == "n" ]]; then
           :  #nothing to do
         else
           echo only \"y\" or \"n\" valid
         fi
      done
   elif [[ $num == 1 ]] ; then # only one instance. no need for menu
      # windows style. are you really, really sure?
      read -p "do you want to kill \"$w\"? (y|n) : " confirm
      if [[ $confirm == "y" ]]; then
        echo killing process \"$p\"
      elif [[ $confirm == "n" ]]; then
        :  #nothing to do
      else
        echo only \"y\" or \"n\" valid. Try again later.
      fi
   else
      echo  \"$p\" is not running
   fi
done
echo "Thanks for using \"$(basename $0\" . Bye."
Of course one can compress this thingie. But i wanted to demonstrate some of the commands and technics one can use for dealing with processes.


Top
 Profile  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 2 posts ] 

All times are UTC - 6 hours


Who is online

Users browsing this forum: Google [Bot], Majestic-12 [Bot] and 1 guest


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Jump to:  


BashScripts | Promote Your Page Too
Powered by phpBB © 2011 phpBB Group
© 2003 - 2011 USA LINUX USERS GROUP