如何终止从脚本执行的命令?

如何终止从脚本执行的命令?

我想在我自己的脚本中启动 tcpdump,一段时间后我想再次杀死它。如何从 tcpdump 访问 PID?我用 $$ 尝试过,但这只会杀死脚本。

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

这是我 grep tcpdump 时的输出,所以我认为不可能使用 pidof 和 pkill。

在此输入图像描述

我尝试用 awk 来做

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

当我直接使用 pid 命令时,它会找到 pid 但不会执行 kill。

我想我必须稍微考虑一下我的代码。我从配置文件中导入时间,然后检查开始时间是否相同,如果是,还应该检查它是否不是结束时间。然后,只要不是结束时间,它就应该执行 tcpdump。当它到达结束时间时,它应该杀死 tcpdump。我知道这不是最好的解决方案,但如果能让它与类似的东西一起工作那就太好了。

   #!/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

答案1

如果我理解你想运行 tcpdump 一段时间并杀死它。您可以执行以下操作:

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

将为$!您提供启动命令的 pid。要杀死它,您可以调用kill [Signal] [PID]杀死 tcpdump 命令。

请注意,我们运行 tcpdump背景&命令末尾添加 ,否则 tcpdump 将继续执行前景。这exit 0将确保脚本在最后被杀死。

[概念证明]

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

[或者]

正如埃里克所建议的,你也可以这样做暂停命令

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

答案2

您的命令应该通过在该行sudo tcpdump附加一个 & 符号来进入后台:&

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

该行pid1=$!会将命令的 PID 放入sudo tcpdump变量中pid1

如果你想终止该进程,你应该使用:

sudo kill $pid1

您使用$$它代表当前正在运行的进程的PID。

由于您在另一个脚本中使用它,您可能会多次调用该脚本,因此所有后续运行都没有使用的pid1变量。

要获取此变量中的 PID,您可以使用:

pid1=$(pidof tcpdump)

else你的脚本部分。

或者直接使用:

sudo pkill tcpdump

假设您只运行一份 tcpdump 副本。

您需要注意的另一件事。每次您调用脚本并且$TIMEEND不等于$Zeit它时,都会启动另一个tcpdump进程。更好的解决方案是:

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

这将测试时间要求和tcpdump流程的存在性。

答案3

同一脚本的不同调用之间不会保留变量值。这意味着,您无法将程序 PID 保存在变量中,并期望在再次运行脚本时将该变量初始化为该值。

将 PID 值保存在临时文件中:

if [...] ; then
    sudo tcpdump -i eth0 ..... &
    disown
    echo $! > somefile.pid
    echo "started"
else
    cat somefile.pid | xargs -n 1 kill
    echo "stopped"
fi

注意这个命令保存的sudo是PID,而不是tcpdumppid,这意味着你不需要sudo再次杀死它

另外,如果您希望后台命令比执行脚本的 shell 持续时间更长,您应该disown在启动后立即执行

相关内容