【问题标题】:Terminating process created in a if condition in another if condition在另一个 if 条件中终止在 if 条件中创建的进程
【发布时间】:2021-11-22 17:54:51
【问题描述】:

我不熟悉编程和从事业余项目。 当某个条件为真时,我正在使用 python 中的子进程模块创建一个进程。

现在我想在其他条件为真时终止进程。

if new_lenght>old_length:
       print("I will Record")
       process = subprocess.Popen(['sudo', 'tcpdump', '-l', '-i', wlan_iface1, '-w',f'{new[-1]}.pcap'], stdout=subprocess.PIPE)
if new_lenght < old_length:
       print("I will Stop")

更多代码 所以我正在使用我在 github https://github.com/Lynbarry/WiFinder 上找到的脚本并将其更改为做更多的事情。我所做的更改看起来很糟糕,我还编写了两次函数以更好地理解它。仍然有一些我不理解的部分,例如“UpdateHostList”函数。但是当我进行更多编辑时,我会以某种方式尝试弄清楚在代码中。

import netifaces 
import netaddr
import nmap
import re
import sys
import time
import subprocess
import os

hostList = []
gracePeriod = 1


try:
    nm = nmap.PortScanner()         # instance of nmap.PortScanner
except nmap.PortScannerError:
    print('Nmap not found', sys.exc_info()[0])
    sys.exit(0)
except:
    print("Unexpected error:", sys.exc_info()[0])
    sys.exit(0)
    
def seek():
   curHosts =[]
   global wlan_iface
   ifaces=netifaces.interfaces() #Get all the avalialbe interfaces
   pattern = '^w' #Pattern maching for wlan interface
   
   for position in range(len(ifaces)):
       name = ifaces[position]
       match_result = re.match(pattern,str(name))
       if match_result:
           wlan_iface=name
   addrs = netifaces.ifaddresses(wlan_iface)
   ipinfo = addrs[netifaces.AF_INET][0]
   address = ipinfo['addr']
   wlan_iface1=str(wlan_iface)
   netmask = ipinfo['netmask']
   # Create ip object and get CIDR
   cidr = netaddr.IPNetwork('%s/%s' % (address, netmask))
   a=str(cidr)
   nm.scan(hosts = a, arguments = '-sn -T4')
   # executes a ping scan
   localtime = time.asctime(time.localtime(time.time()))
   print('============ {0} ============\n'.format(localtime))
   for host in nm.all_hosts():

       curHosts.append((host,gracePeriod))
   curHosts.remove((str(address),gracePeriod))
   old=sniff_old()
   old_length=len(old)
   updateHostList(curHosts)
   new=sniff_new()
   new_lenght=len(new)
   if new_lenght>old_length:
       print("I will Record")
       process = subprocess.Popen(['sudo', 'tcpdump', '-l', '-i', wlan_iface1, '-w', f'{new[-1]}.pcap'], stdout=subprocess.PIPE)
   if new_lenght < old_length:
       print("I will Stop")
       process.kill()
       process.terminate()
       process.wait()
    
   return len(hostList)
   
def sniff_new():
    sniff_list=[]
    for host in hostList:      
       sniff_list.append(host[0])

    print(f"{sniff_list} NEW")
    return((sniff_list))
def sniff_old():
    sniff_list=[]
    for host in hostList:      
       sniff_list.append(host[0])
    old_sniff=(sniff_list)
    
    print(f"{old_sniff} OLD")
    return((old_sniff))
           
           
             
def updateHostList(curHosts):
    global hostList
    if hostList == []:
        hostList = curHosts
    else:
        hostList = [(x[0],x[1]-1) for x in hostList]
        


        # only the hosts that were new in this iteration
        newList = [(x[0],x[1]) for x in curHosts if not (any(x[0]==y[0] for y in hostList))]

        for host in newList:
            hostList.append(host)

        for host in hostList:
            if any(host[0] == y[0] for y in curHosts):
                hostList[hostList.index(host)] = (host[0],gracePeriod)

        for host in hostList:
            if host[1] <= 0:
                hostList.remove(host)
           
def beep():                         # no sound dependency
    print('\a')            
    
if __name__ == '__main__':
    old_count = new_count = seek()


    startCounter = gracePeriod
    
    # are there any new hosts?
    while True:
        startCounter -= 1
        time.sleep(1)               # increase to slow down the speed
        old_count = new_count
        new_count = seek()
        

    # DANGER!!!

【问题讨论】:

  • process.kill() 将终止进程。
  • 只有其中一个条件为真。如果第二个条件为真,您将不会创建进程,因此没有什么可以终止。
  • 顺便说一句,当两个长度完全相等时,你想做什么? if 中的任何一个都不能处理。
  • 谢谢!!我不确定是否可以在条件范围之外使用流程变量,但我会尝试一下。
  • Python 变量范围是按功能划分的,if 没有单独的范围。

标签: python subprocess tcpdump


【解决方案1】:

使用process.kill() 终止进程。然后执行process.wait() 等待它完全终止。下面的例子。

我用简单的 python 无限循环程序替换了你的 shell 命令。只是为了所有 StackOverflowers 都可以测试的工作示例。

在您的情况下,for 循环不是必需的,我的 shell 命令也无关紧要,这两个修改仅用于可运行的示例目的。

注意第二个if 我使用了'process' in locals() and process is not None,如果尚未创建process 变量,则此检查是必要的,以便没有错误,在这种情况下,您不需要杀死/等待任何东西,因为实际上没有任何东西要被杀死/等待,因为还没有创建进程。此外,我将变量设置为process = None,这样您就不会再对已终止的进程进行第二次终止。

Try it online!

import subprocess
for new_lenght, old_length in [(7, 5), (3, 11)]:
    if new_lenght > old_length:
        print("I will Record")
        process = subprocess.Popen(['python', '-c', 'while True: pass'],
            stdout = subprocess.PIPE)
    if new_lenght < old_length and 'process' in locals() and process is not None:
        print("I will Stop")
        process.kill()
        process.wait()
        process = None
print('All done!')

输出:

I will Record
I will Stop
All done!

【讨论】:

  • 我的代码肯定做错了。
  • @jaysoni 为什么你认为你做错了?只需添加两行 process.kill()process.wait() 即可。我的代码示例不需要其他任何东西。您的代码只需要这两行。如果您有一些错误,请在此 cmets 中发布错误消息。如果没有错误,那么为什么您认为您的代码现在不起作用?我做了更大的例子只是为了向其他 StackOverflowers 展示工作代码,对你来说只需要这两行(killwait)。
  • UnboundLocalError: local variable 'process' referenced before assignment@Arty
  • @jaysoni 要解决此错误,只需在测试此变量是否存在时添加额外的内容,换句话说,添加额外的if 'process' in locals():,如in this code sn-p。我将通过此类网络链接向您发布代码,因为在 cmets 内部您无法提供多行格式的代码。
  • @jaysoni 如果你也想分享代码,请点击我的链接(来自之前的评论),在此处更改代码,点击红色显示的“链”按钮on this screen-shot,然后点击下一步屏幕从纯 URL 单击右侧的“剪贴板按钮”,如红色 on this screen-shot 所示。现在此链接已复制到您的剪贴板,您可以将此链接发送给您想与之共享代码的任何人。
猜你喜欢
  • 2022-08-16
  • 1970-01-01
  • 1970-01-01
  • 2016-03-08
  • 2015-04-22
  • 2020-11-02
  • 1970-01-01
  • 1970-01-01
  • 2016-11-24
相关资源
最近更新 更多