[bash scripting] post met curl met recovery mogelijkheid

Pagina: 1
Acties:

Acties:
  • 0 Henk 'm!

  • Mistraller
  • Registratie: Oktober 2002
  • Laatst online: 14-07 10:41
Voor een projectje wil ik het volgende:
Ik heb een variabele die ik elke 5 minuten wil posten naar een site met curl.

als het om wat voor reden mislukt, dan moeten de variablen opgeslagen worden, en op een later tijdstip nogmaals gepost worden zodra de site weer benaderbaar lijkt te zijn. Wat ik daarvoor nu heb bedacht gaat werken maar ik vraag me af of het netter kan?

Komt neer op het volgende (nog niet getest, wellicht nog kleine typo's)

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
curl -d $variable --url http://www.site.com >> $success
if [ $success = "OK" ]; then
    if [ -f backlog.lst ]; then
        while read var; do
            curl -d $var --url http://www.site.com >> $success
            if [ $success != "OK" ]; then
                echo $var >> backlog2.lst
            fi
        done < backlog.lst
        if [ -f backlog2.lst ];then
            echo "backlog niet goed gepost, er zijn van `wc -l backlog.lst | awk '{print $1;}'` variabelen, `wc -l backlog2.lst| awk '{print $1;}'` posts mislukt" >> logfile
            mv backlog2.lst backlog.lst
        else
            rm backlog.lst
            echo "backlog succesvol gepost" >> logfile
        fi
    fi
else
    if [ ! -f backlog.lst ]; then
        echo "Error bij posten variabele" >> logfile
    fi
    echo $variable >> backlog.lst
fi

Kortom: probeer te posten; als het gelukt is, controleer dán of er een backlog bestaat met eerdere failures. Probeer die te posten, en bewaar eventueel weer mislukte pogingen in een file. Log het geheel in een logfile.

Backlog wordt alleen geprobeerd te posten als de eerste poging lukt, en er wordt alleen bij de eerste failure gelogd, dus bij langere tijd onbereikbaar ontstaat geen vollopende log.

Nu is mijn vraag; dit bovenstaande stukje gaat wel werken, maar ik heb het gevoel dat het netter kan. Hoe precies, weet ik echter niet goed.
Iemand die nog wat slimmigheid kan toevoegen? Ik zat al te puzzelen met een while loop om die curl heen, maar dan gaat ie iedere 5 minuten de hele backlog proberen te posten, en na een aantal dagen onbeschikbaarheid gaat dat erg lang duren. (backlog mag best een aantal dagen logregels bevatten na een poos en dat kunnen dus een paar 100 regels worden.)

My solar panels | Soladin loggen? | Strava
---------------
Gemak dient de mens, moeite dient de mensheid.


Acties:
  • 0 Henk 'm!

  • sam.vimes
  • Registratie: Januari 2007
  • Laatst online: 08-06 08:44
Mistraller schreef op woensdag 27 februari 2013 @ 00:37:
Voor een projectje wil ik het volgende:
Ik heb een variabele die ik elke 5 minuten wil posten naar een site met curl.

als het om wat voor reden mislukt, dan moeten de variablen opgeslagen worden, en op een later tijdstip nogmaals gepost worden zodra de site weer benaderbaar lijkt te zijn. Wat ik daarvoor nu heb bedacht gaat werken maar ik vraag me af of het netter kan?

Komt neer op het volgende (nog niet getest, wellicht nog kleine typo's)

code:
1
2
curl -d $variable --url http://www.site.com >> $success
...
Dit gaat natuurlijk niet werken, want $variable en $success zijn nog niet geïnitialiseerd.
  • Altijd als eerste regel van je script een 'hashbang' (#!/bin/bash o.i.d.) opnemen. Voor zowel mensen als computer is het fijn om te weten welke interpreter er gebruikt moet worden.
  • $variable moet expanderen naar iets van de vorm naam=waarde, zie man curl.
  • Als $variable spaties bevat, moet je dubbele quotes gebruiken: "$variable".
  • Wat probeer je hier te bereiken? >> verwacht een filenaam, en $success is een expansie van een variabele die nog geen waarde heeft. Variabelen geef je een waarde met success=WAARDE. Maar als je wil aftesten of het curl-commando is geslaagd, gaat dat het best met:
    Bash:
    1
    2
    3
    4
    5
    6
    
    if curl ...
    then
      ...
    else
      ...
    fi
Ik zou voor deze aanpak in elk geval 2 files gebruiken:
  1. een todo-lijst, deze is aan het begin van het script gevuld
  2. een failed-lijst, deze is aan het begin leeg.
Iedere script-aanroep itereer je één maal helemaal door de todo-lijst en roep je curl aan met de waarden uit die lijst. Zodra er een fout optreedt in curl, schrijf je de waarde waar je mee bezig was naar de failed-lijst. (Je moet daarna kiezen of je ook de rest van de waarden in de todo-lijst naar de failed-lijst schrijft, of dat je doorgaat met waarden uit de todo-lijst proberen te verzenden.)
Aan het eind van de iteratieronde hernoem je de failed-lijst naar de todo-lijst en wacht je weer 5 minuten.
In die wachtperiode kun je de nieuwe waarde die verzonden moet worden aan de todo-lijst toevoegen.

Je zou dus zoiets krijgen:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#!/bin/bash
SITE=http://www.site.com
# maak failed leeg
>failed
# doorloop todo-lijst (ja ik weet dat de cat overbodig is, maar ik vind het
# leesbaarder dan done<todo)
cat todo | while read variabele
do
  # als er al eerder een fout optrad, sla dan de rest direct over
  if [ -s failed ]
  then
    echo "$variabele" >> failed
  else
    # blijf POSTen zolang alles goed gaat
    if curl -s -d naam="$variabele" --url $SITE
    then
      : echo "$variabele succesvol gepost"
    else
      echo "$variabele" >> failed
    fi
  fi
done
mv failed todo

[ Voor 0% gewijzigd door sam.vimes op 03-03-2013 14:56 . Reden: linewrap ]


Acties:
  • 0 Henk 'm!

  • Mistraller
  • Registratie: Oktober 2002
  • Laatst online: 14-07 10:41
sam.vimes schreef op zondag 03 maart 2013 @ 14:52:
[...]

Dit gaat natuurlijk niet werken, want $variable en $success zijn nog niet geïnitialiseerd.
  • Altijd als eerste regel van je script een 'hashbang' (#!/bin/bash o.i.d.) opnemen. Voor zowel mensen als computer is het fijn om te weten welke interpreter er gebruikt moet worden.
  • $variable moet expanderen naar iets van de vorm naam=waarde, zie man curl.
  • Als $variable spaties bevat, moet je dubbele quotes gebruiken: "$variable".
  • Wat probeer je hier te bereiken? >> verwacht een filenaam, en $success is een expansie van een variabele die nog geen waarde heeft. Variabelen geef je een waarde met success=WAARDE. Maar als je wil aftesten of het curl-commando is geslaagd, gaat dat het best met:
    Bash:
    1
    2
    3
    4
    5
    6
    
    if curl ...
    then
      ...
    else
      ...
    fi
Ik zou voor deze aanpak in elk geval 2 files gebruiken:
  1. een todo-lijst, deze is aan het begin van het script gevuld
  2. een failed-lijst, deze is aan het begin leeg.
Iedere script-aanroep itereer je één maal helemaal door de todo-lijst en roep je curl aan met de waarden uit die lijst. Zodra er een fout optreedt in curl, schrijf je de waarde waar je mee bezig was naar de failed-lijst. (Je moet daarna kiezen of je ook de rest van de waarden in de todo-lijst naar de failed-lijst schrijft, of dat je doorgaat met waarden uit de todo-lijst proberen te verzenden.)
Aan het eind van de iteratieronde hernoem je de failed-lijst naar de todo-lijst en wacht je weer 5 minuten.
In die wachtperiode kun je de nieuwe waarde die verzonden moet worden aan de todo-lijst toevoegen.

Je zou dus zoiets krijgen:
Het stukje script wordt een subroutine in een groter script wat al bestaat en goed werkt, dus de interpreter is al gedefinieerd. De variabele wordt ook al elders gevuld. (Mijn huidige script doet de curl nu al netjes, maar als de site in onderhoud is, mijn internet ligt eruit, etc, dan wil ik de waardes later automatisch verwerken)

De output die ik terugkrijg van curl geeft aan of het uploaden gelukt is en of de waardes ook binnen specs vallen. Dat komt op onderstaande manier wel in een variabele:

code:
1
success=$(curl .......)

Dus of curl terugkomt met errorstatus 0 is niet voldoende, ook de reply moet ik meenemen. Zo keurt de site de upload af als het te oud is. En dan dump ik de waarde, want dan heeft retry geen zin meer.

Uiteindelijk gaat het dus meer om de hoofdstructuur, maar je manier om direct te stoppen als het 1x mislukt is had ik nog even niet bedacht, dus wat dat betreft zeker een goede tip. d:)b Ik zal al met tellertjes te klooien om het aantal regels in todo en failed te tellen en te vergelijken, maar dat is feitelijk ook niet handig.

[ Voor 9% gewijzigd door Mistraller op 04-03-2013 22:16 ]

My solar panels | Soladin loggen? | Strava
---------------
Gemak dient de mens, moeite dient de mensheid.


Acties:
  • 0 Henk 'm!

  • Hero of Time
  • Registratie: Oktober 2004
  • Nu online

Hero of Time

Moderator LNX

There is only one Legend

Als je gaat tellen e.d. op je regels, kan je net zo goed een timestamp op zetten. Door velden te gebruiken, dus datum/tijd zonder spaties bijvoorbeeld, dan spatie en daarna je waarde, kan je met awk of cut je waarde krijgen die je wilt posten, en toch weten of iets te oud is geworden of niet. Als je weet hoe oud 't mag zijn, kan je al voor 't posten items trashen zodat je geen onnodige pogingen doet met curl.

Commandline FTW | Tweakt met mate