2017-10-12 8 views
0

J'ai écrit un script pour extraire les résultats d'analyse de Qualys à exécuter chaque semaine aux fins de la collecte des mesures.La requête PyCurl se bloque à l'infini

La première partie de ce script consiste à extraire une liste de références pour chacune des analyses exécutées la semaine dernière pour un traitement ultérieur.

Le problème est que, bien que cela fonctionne parfois, d'autres fois le script se bloquera sur la ligne c.perform(). Ceci est gérable lorsque vous exécutez le script manuellement car il peut juste être relancé jusqu'à ce que cela fonctionne. Cependant, je cherche à exécuter cela comme une tâche planifiée chaque semaine sans aucune interaction manuelle.

Y at-il un moyen infaillible que je peux détecter si un blocage s'est produit et renvoyer la requête PyCurl jusqu'à ce que cela fonctionne?

J'ai essayé de définir les options c.TIMEOUT et c.CONNECTTIMEOUT mais celles-ci ne semblent pas efficaces. En outre, comme aucune exception n'est levée, le simple fait de la placer dans un bloc try-except ne volera pas non plus.

La fonction en question est la suivante:

# Retrieve a list of all scans conducted in the past week 
# Save this to refs_raw.txt 
def getScanRefs(usr, pwd): 

    print("getting scan references...") 

    with open('refs_raw.txt','wb') as refsraw: 
     today = DT.date.today() 
     week_ago = today - DT.timedelta(days=7) 
     strtoday = str(today) 
     strweek_ago = str(week_ago) 

     c = pycurl.Curl() 

     c.setopt(c.URL, 'https://qualysapi.qualys.eu/api/2.0/fo/scan/?action=list&launched_after_datetime=' + strweek_ago + '&launched_before_datetime=' + strtoday) 
     c.setopt(c.HTTPHEADER, ['X-Requested-With: pycurl', 'Content-Type: text/xml']) 
     c.setopt(c.USERPWD, usr + ':' + pwd) 
     c.setopt(c.POST, 1) 
     c.setopt(c.PROXY, 'companyproxy.net:8080') 
     c.setopt(c.CAINFO, certifi.where()) 
     c.setopt(c.SSL_VERIFYPEER, 0) 
     c.setopt(c.SSL_VERIFYHOST, 0) 
     c.setopt(c.CONNECTTIMEOUT, 3) 
     c.setopt(c.TIMEOUT, 3) 

     refsbuffer = BytesIO() 
     c.setopt(c.WRITEDATA, refsbuffer) 
     c.perform() 

     body = refsbuffer.getvalue() 
     refsraw.write(body) 
     c.close() 

    print("Got em!") 
+0

je me rends compte maintenant que je l'ai utilisé un mélange horrible de camelCase, sous_ligne et nothingatall pour nommer des variables. S'il te plait, ne me juge pas trop sévèrement. –

Répondre

0

je résolu le problème moi-même en lançant un processus distinct en utilisant multiprocessing pour lancer l'appel d'API dans un processus séparé, tuant et redémarrer si elle se poursuit pendant plus longtemps que 5 secondes. Ce n'est pas très joli mais est multi-plateforme. Pour ceux qui recherchent une solution plus élégante, mais fonctionne uniquement sur * nix regardez dans the signal library, en particulier SIGALRM.

code ci-dessous:

# As this request for scan references sometimes hangs it will be run in a separate thread here 
# This will be terminated and relaunched if no response is received within 5 seconds 
def performRequest(usr, pwd): 
    today = DT.date.today() 
    week_ago = today - DT.timedelta(days=7) 
    strtoday = str(today) 
    strweek_ago = str(week_ago) 

    c = pycurl.Curl() 

    c.setopt(c.URL, 'https://qualysapi.qualys.eu/api/2.0/fo/scan/?action=list&launched_after_datetime=' + strweek_ago + '&launched_before_datetime=' + strtoday) 
    c.setopt(c.HTTPHEADER, ['X-Requested-With: pycurl', 'Content-Type: text/xml']) 
    c.setopt(c.USERPWD, usr + ':' + pwd) 
    c.setopt(c.POST, 1) 
    c.setopt(c.PROXY, 'companyproxy.net:8080') 
    c.setopt(c.CAINFO, certifi.where()) 
    c.setopt(c.SSL_VERIFYPEER, 0) 
    c.setopt(c.SSL_VERIFYHOST, 0) 

    refsBuffer = BytesIO() 
    c.setopt(c.WRITEDATA, refsBuffer) 
    c.perform() 
    c.close() 
    body = refsBuffer.getvalue() 
    refsraw = open('refs_raw.txt', 'wb') 
    refsraw.write(body) 
    refsraw.close() 

# Retrieve a list of all scans conducted in the past week 
# Save this to refs_raw.txt 
def getScanRefs(usr, pwd): 

    print("Getting scan references...") 

    # Occasionally the request will hang infinitely. Launch in separate method and retry if no response in 5 seconds 
    success = False 
    while success != True: 
     sendRequest = multiprocessing.Process(target=performRequest, args=(usr, pwd)) 
     sendRequest.start() 

     for seconds in range(5): 
      print("...") 
      time.sleep(1) 

     if sendRequest.is_alive(): 
      print("Maximum allocated time reached... Resending request") 
      sendRequest.terminate() 
      del sendRequest 
     else: 
      success = True 

    print("Got em!")