PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Wie kann man die cron-Meldung für gekillte cronjobs vermeiden?



michel_vaclav
31.12.15, 08:38
Hallo zusammen,

ich nutze einen Cronjob, um Daten alle fünf Minuten zu einem Server zu übertragen. Der Cronjob ruft ein Shellskript auf, welches neben ein paar anderen Dingen eben die Datenübermittlung übernimmt.
Nun kommt es unregelmäßig vor, dass der Server die Daten nicht annimmt, dann bleibt das Sendeskript solange aktiv, bis es manuell abgebrochen wird. Das hat mir während eines Urlaubs meinen Rechner lahmgelegt, weil alle fünf Minuten ein weiterer Job dazugekommen ist.
Um dies zu verhindern, möchte ich das erneute Senden verhindern, wenn noch ein Sendejob aktiv ist. Das habe ich auch problemlos hinbekommen, indem ich die PID des Shellskripts in eine Datei wegschreibe und beim nächsten Aufruf prüfe, ob die PID noch aktiv ist. Falls ja, wird der zugehörige Job gekillt.

Nun zu meinem Problem: Das Killen des Shellskripts, welches per cron aufgerufen wurde, führt jedes Mal dazu, dass in die Systemlogs eine entsprechende Meldung geschickt wird. Diese spamt mir mein email-Postfach zu.
Wie kann ich dem Cron abgewöhnen, in diesem Fall eine Meldung zu generieren? Kann man das in der Crontab definieren oder muss ich das als Ausnahme in der syslog-Konfiguration definieren (was mir deutlich unsympathischer wäre)? Oder löst man das ganz anders.

michel_vaclav

fork
31.12.15, 08:59
Ausgabeumleitung des Cronjob-Kommandos?

michel_vaclav
31.12.15, 09:13
Ausgabeumleitung des Cronjob-Kommandos?
Momentan ist der Eintrag der crontab:
*/5 * * * * /usr/local/bin/cron_send2wunderground.sh 1> /dev/null 2>/dev/null
Das führt aber trotzdem zu:
/bin/sh: line 1: 21722 Killed /usr/local/bin/cron_send2wunderground.sh > /dev/null 2> /dev/null

fork
31.12.15, 10:39
statt...


*/5 * * * * /usr/local/bin/cron_send2wunderground.sh 1> /dev/null 2>/dev/null

schreibe...


*/5 * * * * { /usr/local/bin/cron_send2wunderground.sh ; } 1> /dev/null 2>/dev/null

...und testen ob das überhaupt geht :)

drcux
31.12.15, 10:41
Ausgabe von kill nach /dev/null schicken...

michel_vaclav
01.01.16, 15:47
*/5 * * * * { /usr/local/bin/cron_send2wunderground.sh ; } 1> /dev/null 2>/dev/null
Habe ich ausprobiert, wird ausgeführt. Wolltest Du mit dem Smiley andeuten, dass ggfs. die Syntax falsch ist? Habe zwischenzeitlich nochmals gegoogled und die Syntax in der crontab verändert:
*/5 * * * * /usr/local/bin/cron_send2wunderground.sh > /dev/null 2>&1 Beide Zeilen werden ausgeführt. Bei letzterem Befehl wird wieder die Nachricht generiert, dass beim Fehlschlagen des Sendens der cronjob gekillt wurde.


Ausgabe von kill nach /dev/null schicken...
Auch das habe ich probiert: gleiches Ergebnis, Nachricht wird generiert.

BetterWorld
01.01.16, 16:37
Ich würde das ganz anders lösen.
Da es eh alle fünf Minuten senden soll, würde ich statt eines Cronjobs schlicht im Script selber einfach warten.
Und wenn ein Script "hängt", weil irgendwo im Netz irgendwas nicht tut, ist das schlicht schlechter Code.
Das Script sollte die Netzwerkbasics transparent behandeln.

Poste doch mal das Script.

fork
01.01.16, 17:55
@Betterworld:

Auf Programmieralgorithmen aus der Kategorie "Fauler Sack" greife ich durchaus auch gelegentlich zurück.

@vaclav:

Der Smiley war deswegen da, weil ich nicht weiss ob's funktioniert. Wahrscheintlich tut das genau das, was du willst. Also: Testen --> glücklich sein

Die neue Art von Dir die Umleitung zu schreiben ist bzgl. der Funktion das gleiche wie vorher.

---

Ich vermute das Problem liegt halt daran, dass wenn die Shell hart gekillt wird, dass das in der Verantwortung des übergeordneten Prozesses liegt, weswegen die Umlenkung nicht so funktioniert wie gewünscht, sondern erst in weiterer Kapselung ( also in { ... ; } ) greift. Das liegt weiterhin auch daran, dass Du wahrscheinlich mit dem KILL-Signal arbeitest("SIGKILL" oder 9). Das Problem hättest Du wahrscheinlich nicht, wenn Du statt dessen die Signale 15(TERM "Bitte Beende Dich"), wenn nicht geht dann, 1(HANGUP "Das verbundene virtuelle Terminal wurde beendet, bitte beende Dich"), wenn nicht geht dann 2(INTERRUPT "Unterbrechung von der Tastatur wurde angefordert, bitte beende Dich") verwenden würdest. kill -9 im Vergleich ist "Ich frage Dich nicht, ich töte Dich sofort". (Also die drei Signale testen, welches für dich funktioniert und dann diesen Typ verwenden, 2 / SIGINT dürfte gehen).

---

Wenn man das Vernünftig umsetzen wollen würde , dann würde man das ungefähr so machen:




VERBINDUNGSAUFBAU_ZEIT_MAX=10 # SEKUNDEN
COPY_ZEIT_MAX=240 # SEKUNDEN

if ! ping -c1 -w3 zielhost >/dev/null 2>&1 ; then
logger -t mein_backup -t local7.info "Keine Verbindung zu zielhost"
exit 1
fi

if timeout $COPY_ZEIT_MAX scp -o ConnectTimeout=$VERBINDUNGSAUFBAU_ZEIT_MAX datei zielhost:/vz >/tmp/backup.err 2>&1 ; then
logger -t mein_backup -t local7.info "Backup zu zielhost erfolgreich ausgeführt"
exit 0
else
logger -t mein_backup -t local7.info "Fehler bei scp zu zielhost: $(cat /tmp/backup.err)"
exit 1
fi

BetterWorld
01.01.16, 18:32
Nu ja, "fauler Sack" ist wohl eher nicht.

Ein ständiges Rufen via cron bedingt halt mal relativ viel Systemoverhead.
Ein schlafendes Scriptchen ist da wesentlich sparsamer.
Und die saubere Behandlung von Netzwerkevents ist ganz sicher weder faul noch soo trivial.

michel_vaclav
02.01.16, 12:41
Ich würde das ganz anders lösen.
Da es eh alle fünf Minuten senden soll, würde ich statt eines Cronjobs schlicht im Script selber einfach warten.
Und wenn ein Script "hängt", weil irgendwo im Netz irgendwas nicht tut, ist das schlicht schlechter Code.
Das Script sollte die Netzwerkbasics transparent behandeln.

Poste doch mal das Script.

Das Senden passiert nicht per Skript sondern ist ein Binary aus dem Programmpaket "open2300", eine Sammlung von Werkzeugen zum Auslesen bestimmter Wetterstationen. Darin enthalten ist das Programm wu2300, welches Daten aus der Wetterstation abruft und nach Weatherunderground schickt. An diesem Paket werde ich sicherlich nichts ändern.

michel_vaclav
02.01.16, 12:44
Der Smiley war deswegen da, weil ich nicht weiss ob's funktioniert. Wahrscheintlich tut das genau das, was du willst. Also: Testen --> glücklich sein
Momentan siehts schwer danach aus, dass es tut. Daher bin ich erst mal glücklich. Wenn ich die Tage Zeit habe, schau ich mir Eure Verbesserungsvorschläge an, die ich dann in meinem Skript umsetzen kann.
Dafür schon mal vielen Dank

fork
02.01.16, 19:33
Nu ja, "fauler Sack" ist wohl eher nicht.

Ein ständiges Rufen via cron bedingt halt mal relativ viel Systemoverhead.

Mit fauler Sack ist nicht der Computer, sondern natürlich der Programmierer gemeint. Bis jetzt haben wir noch nicht so viele Computer bzw. Software die aufgrund von Unlust den Dienst verweigern. Dazu braucht es erst noch die KI.

marce
02.01.16, 19:59
Ein ständiges Rufen via cron bedingt halt mal relativ viel Systemoverhead.
Ein schlafendes Scriptchen ist da wesentlich sparsamer.
Und die saubere Behandlung von Netzwerkevents ist ganz sicher weder faul noch soo trivial.
Was die Netzwerkevents angeht - Einverstanden.

Den Rest würde nicht sagen, daß man das so pauschal sagen kann - ein dauerhaft laufendes,aber schlafendes Script kann wesentlich mehr Systemlast verursachen als das gleiche Script, welches periodisch aufgerufen und dann sauber beendet wird. Und was den Aufrufoverhead angeht kommt es drauf an, was das Script denn so macht, wie umfangreich es ist und und und...

... zudem sind periodisch aufgerufene Script wenigstens immer regelmäßig da und erledigen ihre Arbeit während man für 1x gestartete Script auch noch irgenwelche Überwachungsmethoden einrichten darf, die sicherstellen, daß das Script auch läuft, seinen Job sauber erledgt und nicht irgendwie in komischen Zustanden vor sich hin dümpeln, die es nicht gäbe, wenn das Ding frisch gestartet worden wäre...

BetterWorld
02.01.16, 20:44
Ich gehe schon davon aus, dass man sein Script halbwegs sauber schreibt.
Solche Scripte starte ich via systemd Servicefile.
Ich muss mich also um gar nix kümmern.

Und dann braucht halt einmal ein schlafendes Script einfach nix.
Jedenfalls erheblich weniger, als ständiges Cron- Gerödel.

Ist das Script nicht sauber, isses schon egal, ob sleep oder cron.

michel_vaclav
03.01.16, 07:48
Da ihr ja trotz Lösung fleissig weiter diskutiert, poste ich mal das Skript, welches alle 5 Minuten per cron aufgerufen wird.
Es tut, was es soll. Ob es schön ist, dürft ihr gerne kommentieren...

#!/bin/bash
sleep 60s
LOGGING="/var/log/wetterreporting.log"
PIDFILE="/var/run/cron_send2wunderground.pid"
FAILLOG="/tmp/wunderground.fail"
MESSAGE_FROM='meine@email'
MESSAGE_SERVER='mein.email.server:587'
MESSAGE_LOGIN='meine Kennung'
MESSAGE_PW='mein Passwort'
MESSAGE_TO='meine@email'
MESSAGE_SUBJECT='Wetterstation: Senden der Daten nach Weatherunderground mehr als 1x fehlgeschlagen'
MESSAGE_TEXT='Wetterstation: Senden der Daten nach Weatherunderground mehr als 1x fehlgeschlagen!'
COUNTER=0
#Prüfen, ob letzter Versuch erfolgreich war (FAILLOG existiert nicht)

if [ -e $FAILLOG ]; then
COUNTER=`head -n 1 $INPUT`
fi


#Prüfen, ob letzter Versuch abgeschlossen wurde (PIDFILE existiert nicht)
if [ -e $PIDFILE ]; then
COUNTER=$(( $COUNTER + 1 ))
echo $COUNTER > $FAILLOG
ZEITSTEMPEL=`date +"%Y %b %d %H:%M:%S"`
echo $ZEITSTEMPEL" cron_send2wunderground.sh: Status: beim letzten Mal nicht erfolgreich" >> $LOGGING
PIDTOKILL=`head -n 1 $PIDFILE`
rm $PIDFILE
kill -9 $PIDTOKILL
if [ $COUNTER -gt 1 ]; then
/usr/local/bin/sendEmail -f $MESSAGE_FROM -s $MESSAGE_SERVER -xu $MESSAGE_LOGIN -xp $MESSAGE_PW -t $MESSAGE_TO -o tls=yes -u $MESSAGE_SUBJECT -m $MESSAGE_TEXT -o message-charset=utf-8
fi
exit 1
fi
echo $BASHPID > $PIDFILE
/usr/local/bin/wu2300 /etc/open2300.conf
rm $PIDFILE
ZEITSTEMPEL=`date +"%Y %b %d %H:%M:%S"`
# echo $ZEITSTEMPEL" cron_send2wunderground.sh: Status: erfolgreich" >> $LOGGING
if [ -e $FAILLOG ]; then
rm $FAILLOG
fi

marce
03.01.16, 10:11
Und dann braucht halt einmal ein schlafendes Script einfach nix.
Sorry, aber da sagt meine Erfahrung was anderes - klar, hängt auch vom Script ab. Bash-1-Zeiler sind da wesentlich entspannter als komplexere Java-Prozesse.

So oder so - schlafende Prozesse brauchen was - Speicher, FileHandles, ggf. offene Datenbank-Verbindungen, ... und je nach System und Script ist es ggf. besser, in der Schlafenszeit alle nichtr benötigten Ressourcen wieder freizugeben und das Script neu zu starten als den kompletten Müll über "Jahre" hinweg mitzuschleifen. Sozusagen Overhead vs. Overhead.

Wie auch immer, bevor das in einen Streit ausartet - meine Grundaussage dazu ist: Pauschalaussagen würde ich nicht treffen und es kommt immer auf den Einzelfall an, was dort die bessere Methode darstellt.