crontab, utf8 und python3 Problem

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
LetzterZucker
User
Beiträge: 7
Registriert: Freitag 24. Februar 2023, 23:34

Hallo Leute,
habe auf einem Ubuntu Server 18.04 ein Python3 Script welches sich einwandfrei mit der shell
ausführen lässt:

Code: Alles auswählen

./xyz.py -p
In der Ausgabe ist ein Umlaut enthalten.

Shebang und Codierung vorhanden, Rechte gesetzt:

Code: Alles auswählen

#!/usr/bin/python3
# -*- coding: utf-8 -*-
Wird das gleiche Script in der crontab aufgerufen:

Code: Alles auswählen

6 * * * *  python3 xyz.py -p
folgt der Abbruch durch einen Unicode Fehler:

Code: Alles auswählen

UnicodeEncodeError: 'ascii' codec can't encode character '\xfc' in position 1: ordinal not in range(128)
Der gleiche Fehler wird mit fcron geworfen.
crontab und Script werden als normaler User ausgeführt.
die "local" Einstellungen in /etc und etc/default scheinen alle korrekt, habe auch sonst nirgends ein Problem mit utf-8.
Es wurden absolute und relative Pfade versucht, es funktioniert nichts!
Der Umweg über ein bash Script, welches von Cron aufgerufen, das Python Script starten soll, führte genauso daneben.

Was für ein versteckter Saurier-Code bringt hier den "ascii codec" ins Spiel?
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Es würde helfen, den eigentlichen Code zu sehen, inklusive der vollen Fehlermeldung.
LetzterZucker
User
Beiträge: 7
Registriert: Freitag 24. Februar 2023, 23:34

Python3 (etwas eingedampft...)

Code: Alles auswählen

#!/usr/bin/python3
# -*- coding: utf-8 -*-

print('wilder Süden')
fcrontab (alle 2 Minuten..):

Code: Alles auswählen

@ 2 python3 xyz.py
/var/mail/cek:

Code: Alles auswählen

Traceback (most recent call last):
  File "xyz.py", line 4, in <module>
    print('wilder S\xfcden')
UnicodeEncodeError: 'ascii' codec can't encode character '\xfc' in position 8: ordinal not in range(128)
Job 'python3 xyz.py' terminated (exit status: 1) (mailing output)
Und hier am Prompt:

Code: Alles auswählen

cek@localhost:~$ ./xyz.py
wilder Süden
Das verstehe wer will.....
Benutzeravatar
sparrow
User
Beiträge: 4538
Registriert: Freitag 17. April 2009, 10:28

Die Coding-Zeile kann weg. Unter Python 3 ist UTF-8 der Standard.

Was passiert denn, wenn du die Datei exakt so aufrufst, wie es auch Cron macht?

Code: Alles auswählen

python3 xyz.py
?
LetzterZucker
User
Beiträge: 7
Registriert: Freitag 24. Februar 2023, 23:34

Code: Alles auswählen

cek@localhost:~$ python3 xyz.py
wilder Süden

cek@localhost:~$ which python3
/usr/bin/python3
cek@localhost:~$ export PYTHONIOENCODING=UTF-8

cek@localhost:~$ python3 --version
Python 3.6.9

Benutzeravatar
snafu
User
Beiträge: 6872
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Offenbar führt das crontab-Kommando dein Python-Skript in einer Shell mit ASCII-Encoding aus. Das kannst du auch leicht prüfen mittels ``print(sys.stdout.encoding)``. Bau das mal in dein Skript ein und lass es durch crontab ausführen, dann solltest du den Unterschied sehen.

Du musst also die Sub-Shell dazu bringen, das richtige Encoding anzuwenden. Vielleicht hilft dir in dem Zusammenhang diese Antwort weiter: https://stackoverflow.com/a/40739010. Dabei geht es unter anderem darum, dass der cron-Service neu gestartet werden muss, damit die Änderungen wirksam werden.
heyJo
User
Beiträge: 25
Registriert: Mittwoch 24. Januar 2018, 20:49
Wohnort: Köln

Ich hatte auch mal ein Encoding-Problem, das sich mit dem Tool „dos2unix“ beheben ließ. Ursache war, dass ich die Datei mir einem Windows-Editor erstellt habe und unter Linux nutzen wollte. Vielleicht bringt es dich weiter.
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Das ist hier nicht das Problem. Das beträfe das encoding der Datei selbst, und das ist dem Anschein nach korrekt - fc ist der Code point für ü.
Benutzeravatar
snafu
User
Beiträge: 6872
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

@heyJo
Es geht nicht darum, in welchem Encoding die Datei gespeichert ist, sondern um das Encoding der Ausgabe (bzw des ausgebenden Streams) in der betreffenden Shell. Und da muss man halt nochmal beachten, dass der cron-Service seine eigene Shell zur Ausführung benutzt. Was da als Encoding verwendet wird, ist das Entscheidende.

Das erkennt man daran, dass Python sich nicht vor der eigentlichen Ausführung über das Skript beschwert. Stattdessen kommt es während der Ausführung beim print()-Aufruf zu einem Laufzeitfehler. Somit fällt das Encoding der Datei schon mal weg. In einem anderen Zusammenhang, insbesondere mit Python 2.x, wäre dein Hinweis nicht verkehrt. Hier wird er das Problem aber leider nicht lösen.
LetzterZucker
User
Beiträge: 7
Registriert: Freitag 24. Februar 2023, 23:34

@snafu "1968" .... Ich habs befürchtet!
@heyJo Windows darf hier nicht mehr mitspielen...
@deets "- fc ist der Code point für ü" -fc? fcrontab?

Python3:

Code: Alles auswählen

#!/usr/bin/python3

import sys

print(sys.stdout.encoding)
print('wilder Süden')
fcrontab:

Code: Alles auswählen

@ 2 python3 xyz.py >> ~/xyz.log 2>&1
@ 2 echo "schönes Wetter heute" >> xyz.log 2>&1
xyz.log:
schönes Wetter heute

ANSI_X3.4-1968

Traceback (most recent call last):
File "xyz.py", line 6, in <module>
print('wilder S\xfcden')
UnicodeEncodeError: 'ascii' codec can't encode character '\xfc' in position 8: ordinal not in range(128)
schönes Wetter heute
Benutzeravatar
snafu
User
Beiträge: 6872
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Ja, das ist eine Variante von ASCII und die kommt halt nicht mit Umlauten klar. Wie sieht deine /etc/crontab aus? Idealerweise sollten folgende Dinge drin stehen:

Code: Alles auswählen

SHELL=/bin/bash
TERM=xterm
PYTHONIOENCODING=UTF-8
LANG=de_DE.UTF-8
LC_ALL=de_DE.UTF-8
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Mit fc meinte ich https://codepoints.net/U+00FC?lang=de, in deiner Fehlermeldung UnicodeEncodeError: 'ascii' codec can't encode character '\xfc' in position 8: ordinal not in range(128)
LetzterZucker
User
Beiträge: 7
Registriert: Freitag 24. Februar 2023, 23:34

Es funktioniert,
Dank Euch allen!

User crontab:

Code: Alles auswählen

PYTHONIOENCODING=UTF-8
LANG=de_DE.UTF-8
# m h  dom mon dow   command
*/3 * * * *  ./xyz.py >> xyz.log 2>&1
/etc/crontab:

Code: Alles auswählen

SHELL=/bin/sh
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
        # m h dom mon dow user  command
MAILTO = "cek@xxxxxxxxxxx.de"
17 *    * * *   root    cd / && run-parts --report /etc/cron.hourly
.....
Das "LANG=de_DE.UTF-8" darf jedoch nicht in der /etc/crontab stehen weil sonst offensichtlich
die "run-parts --report" welche die scripte aus cron.daily, cron.weekly, cron.hourly laden, nicht mehr funktionieren!

Cron <root@localhost> root cd / && run-parts --report /etc/cron.hourly
/bin/bash: root: Befehl nicht gefunden
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Na das sollte ja auch der User, nicht ein Teil des Kommandos sein. Vielleicht ist da die Formatierung komisch, aber so richtig viel findet man in der man-page dazu nicht. Gff. kannst du auf eine systemd Timer-Unit umstellen, und da ist das expliziter angegeben.
Benutzeravatar
grubenfox
User
Beiträge: 612
Registriert: Freitag 2. Dezember 2022, 15:49

in der /etc/crontab irritiert mich der leere Bereich zweischen dem ersten * und dem zweiten *
Wie in der User crontab sollten da doch nur ein Leerzeichen Abstand zwischen sein? Oder nicht? Habe ich bisher immer so gemacht.
nezzcarth
User
Beiträge: 1764
Registriert: Samstag 16. April 2011, 12:47

Für mich wirkt das so, als wäre da an dem System irgendwo etwas komisch konfiguriert. Hast du mal geschaut, was in /etc/locale so alles definiert ist? Hast du mal "locale -a" ausgeführt? Ist in der Shell-Config für den User, der das ausführt, etwas Seltsames konfiguriert? In deinem Beispiel wird die Shell in contab auf sh/dash gesetzt. Ich würde die Shell stattdessen jedoch auf bash setzen. Dann sollten eigentlich auch die genannten Umgebungsvariablen problemlos mit run-parts funktionieren. Da du als User vmtl. die Bash verwendest, Cron jedoch sh/dash, ist es nicht ungewöhnlich, dass du da abweichende Resultate mit cron/auf der Shell erhältst.

Nebenbemerkung: Ggf. bitte daran denken, dass der kostenlose LTS Support für Ubuntu 18.04 in zwei Monaten ausläuft.
LetzterZucker
User
Beiträge: 7
Registriert: Freitag 24. Februar 2023, 23:34

Der Fehler hat wohl nichts mit den locals zu tun.

Cron <root@localhost> root cd / && run-parts --report /etc/cron.hourly
/bin/bash: root: Befehl nicht gefunden

zwischenzeitlich habe ich bemerkt, dass -warum auch immer- die root crontab die gleichen Einträge wie die /etc/crontab enthält
nämlich:

Code: Alles auswählen

#17 *    * * *   root    cd / && run-parts --report /etc/cron.hourly
Das scheint die Fehlerursache zu sein! Das Userfeld (hier"root") gibt es in der User crontab nicht und wird daher als Befehl interpretiert
...logisch eigentlich.
die /etc/crontab Jobs habe ich nun gelöscht. Die root crontab enthält nun:

Code: Alles auswählen

17 *    * * *   cd / && run-parts --report /etc/cron.hourly
@deets, hast du das gemeint?
@grubenfox, die Leerzeichen scheinen nicht zu stören, werde das aber nochmal testen
@nezzcarth die locals stehen alle auf de_DE.UTF-8, habe ich mit

Code: Alles auswählen

dpkg-reconfigure locales
erst durchgeführt.
LetzterZucker
User
Beiträge: 7
Registriert: Freitag 24. Februar 2023, 23:34

zu den Leerzeichen:
was nicht erlaubt ist wird wohl sofort bemeckert....
Das geht:

Code: Alles auswählen

TERM=xterm
PYTHONIOENCODING=UTF-8
LANG=de_DE.UTF-8
#LC_ALL=de_DE.UTF-8
# m h  dom mon dow   command
     */3         *            * * *  ./cearg.py 10 >> xyz.log 2>&1
*/4 * * * *  ./qas.py >> qas.log 2>&1
*/30 * * * * ~/.local/bin/atsetter/ce_at_setter.py
10 0,8,14,20,23 * * * ~/PycharmProjects/ce_xclg_23/venv/xclogmodstart.py -p 
Das nicht:

Code: Alles auswählen

*/4****  ./qas.py >> qas.log 2>&1

Code: Alles auswählen

cek@localhost:~$ crontab -e
crontab: installing new crontab
"/tmp/crontab.BLYVav/crontab":6: bad hour
errors in crontab file, can't install.
Do you want to retry the same edit? (y/n) 
Unerwarteter Weise scheint die altachtundsechziger Ansi-Tante Cron ja doch ein gewisses Maß an Toleranz zu zeigen.
Benutzeravatar
snafu
User
Beiträge: 6872
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Das hat jetzt aber offenbar nicht mehr viel mit Python zu tun. Vielleicht fragst du besser mal in einem Linux-Forum nach. ubuntuusers.de wäre da ein prominentes Beispiel. Die helfen auch dann, wenn du keine Ubuntu-Distro hast.
Benutzeravatar
sparrow
User
Beiträge: 4538
Registriert: Freitag 17. April 2009, 10:28

Gibt es denn überhaupt noch offene Fragen?
Die crontab kann natürlich keine wilde Aneinanderreihung von Zeitparametern enthalten. Es wird an Whitespaces getrennt. Das können mehrere Leerzeichen sein, es gehen aber auch Tabs.
Das macht auch Sinn. Denn möglicherweise möchte man die Spalten untereinander schreiben und die Länger der Inhalte kann mehr als ein Zeichen enthalten.

+1 für eine systemd Unit.
Antworten