How to kill a command executed from a script?

7,291

Solution 1

If i understand you want to run the tcpdump for some time and kill it. You can do the following:

#!/bin/bash
sudo tcpdump -i eth0 -w /media/usbhd-sd[b-c]1/abfrage2.pcap &
PID=$!
sleep 20
sudo kill -9 $PID
exit 0

The $! will give you the pid of the command launched. To kill it you invoke the kill [Signal] [PID] to kill the tcpdump command.

Kindly note that we run the tcpdump in background with the & at the end of the command else the tcpdump will continue executing in the foreground. The exit 0 will ensure that the script is killed at the end.

[Proof of concept]

bash -x a.sh
+ PID=21988
+ sleep 10
+ tcpdump -i eth0 -w abfrage2.pcap
tcpdump: listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes
+ kill -9 21988
+ exit 0

[Alternatively]

As suggested by Eric you can also do it with timeout command

#!/bin/bash
timeout 10s tcpdump -i eth0 -w abfrage2.pcap
exit 0

Solution 2

Your sudo tcpdump command should go into the background by appending an ampersand & to the line:

sudo tcpdump -i eth0 -w /media/usbhd-sd[b-c]1/abfrage2.pcap &

The line pid1=$! will put the PID of the sudo tcpdump command into variable pid1

If you want to kill the process you should use:

sudo kill $pid1

You used $$ which represents the PID of the current running process.

Since you are using this within another script, which you probably will call multiple times, all subsequential runs does not have a utilized pid1 variable.

To get the PID in this variable you can use:

pid1=$(pidof tcpdump)

in the else section of your script.

Or simply use:

sudo pkill tcpdump

Assuming that you only have one copy of tcpdump running.

One other thing you need to take care off. Every time you call your script and the $TIMEEND does not equals to $Zeit it will start another tcpdump process. A better solution would be:

if [ "$TIMEEND" != "$Zeit" ] && [ "$(pidof tcpdump)" == "" ]

which will test both the time requirement and the existence of a tcpdump process.

Share:
7,291

Related videos on Youtube

apuboard
Author by

apuboard

Updated on September 18, 2022

Comments

  • apuboard
    apuboard over 1 year

    I would like to start a tcpdump in my own script an after some time I would like to kill it again. How can I access the PID from the tcpdump. I tried it with $$ , but this only kills the script.

    if [[ $TIMEEND != $Zeit ]];then
                            echo "tcpdump started"
                            sudo tcpdump -i eth0 -w /media/usbhd-sd[b-c]1/abfrage2.pcap &
                            pid1=$!
                            break
                            #sudo umount /dev/sdb1
                    else
                            sudo kill $pid1
                            echo "autodump stopped"
                    fi
    

    This is the output when i grep tcpdump so I think it's not possible to use pidof and pkill.

    enter image description here

    I tried to do it with awk

      pid1=$(ps -eo pid,args|awk '/abfrage2/ && ! /awk/{print $1}')
                                echo $pid1 >> /tmp/test.txt
                                sudo kill $pid1
    

    When i directly use the command for pid, it finds the pid but it doesn't execute the kill.

    I think I have to overthink my code a little bit. I inmport the time from the config file, then I check if the starttime is the same and if it is it should also check if it isn't the endtime. Then it should execute the tcpdump as long as it isn't the endtime. When it arrives the endtime it should kill the the tcpdump. I know it's not the best solution, but it would be nice to get it working with something like that.

       #!/bin/sh
    source /media/usbhd-sdb1/config.conf
    pluggedin=true
    echo $TIMESTART
    echo $TIMEEND
    echo $$
    echo $Zeit
    echo $$ >> /tmp/test.txt
    while [ $pluggedin ];do
            Zeit=$(date +"%T")
            if [[ $TIMESTART == $Zeit ]];then
                    if [[ $TIMEEND != $Zeit ]];then
                            echo "tcpdump started"
                            sudo tcpdump -i eth0 -w /media/usbhd-sd[b-c]1/abfrage2.pcap &
                            #sudo umount /dev/sdb1
                    else
                            pid1=$(ps -eo pid,args|awk '/abfrage2/ && ! /awk/{print $1}')
                            echo $pid1 >> /tmp/test.txt
                            sudo kill -9 $pid1
                            echo "autodump stopped"
                    fi
    
            else
            echo "tcpdump not yet started"
            fi
    done
    
    • Eric Renouf
      Eric Renouf over 8 years
      If you know in advance how long you want the tcpdump to run for you should consider the timeout command which will do what you want without you having to try to reinvent it all
  • apuboard
    apuboard over 8 years
    So I tried this, but it does terminate the script above and it also doesn't kill the tcpdump. What also could be important is that it is used in a if-else clause--> check updated post
  • Kheshav Sewnundun
    Kheshav Sewnundun over 8 years
    Why is the answer down voted?
  • Lambert
    Lambert over 8 years
    Do not downvote answers if the correct question is not asked... See updated answer to clarify what is problably wrong.
  • apuboard
    apuboard over 8 years
    I didn't downvote anything. I'm thankful for every help.
  • Kheshav Sewnundun
    Kheshav Sewnundun over 8 years
    @Lambert Totally agree !! @ apuboard did you run the script since both mine and Lambert suggestion works :) Kindly check the update. Besides, please do not modify your original codes in the question, please do it whithin an update secion.
  • Lambert
    Lambert over 8 years
    @apuboard, apologies for my assumption then. nevertheless, see the updated answer for a probable cause.
  • apuboard
    apuboard over 8 years
    @Lambert So I tried it like that whti running it in the background and without, neither has worked, is it possible to just read it from the ps and awk the pid and then kill it?
  • Lambert
    Lambert over 8 years
    Sure, consider using pid1=$(ps -eo pid,args|grep abfrage2|grep -v grep)|cut -d ' ' -f1 as first statement within your else section.
  • Lambert
    Lambert over 8 years
    Or using awk: pid1=$(ps -eo pid,args|awk '/abfrage2/ && ! /awk/{print $1}')
  • Lambert
    Lambert over 8 years
    Or consider using the approach of @pqnet and use a pidfile instead: echo $! > /tmp/tcpdump-abfrage2.pid and pid1=$(</tmp/tcpdump-abfrage2.pid)
  • apuboard
    apuboard over 8 years
    @Lambert I tried it, but the kill doesn't get executed.
  • Lambert
    Lambert over 8 years
    Try to change the sudo kill $pid1 to echo sudo kill $pid1 to see what it tries to do (or use bash -x myscript.sh to see debugging messages). Perhaps you need to call kill with the -9 argument to forcibly kill the processes (sudo kill -9 $pid1).
  • Eric Renouf
    Eric Renouf over 8 years
    If you know you want to run for a fixed period the timeout command will do a lot of the work for you, and will exit before the timeout period if the command exits earlier than that, unlike sleeping for a fixed period
  • apuboard
    apuboard over 8 years
    @Lambert I just found out that you can't use && [ "$(pidof tcpdump)" == "" ] because it would kill the process just one second later