Python CGI auf Webserver verbindet sich nicht mit mySQL Datenbank

Installation und Anwendung von Datenbankschnittstellen wie SQLite, PostgreSQL, MariaDB/MySQL, der DB-API 2.0 und sonstigen Datenbanksystemen.
Antworten
Tom_11
User
Beiträge: 5
Registriert: Samstag 27. März 2021, 19:02

Hallo,

ich beschäftige mit erst seit ein paar Wochen mit Python und versuche derzeit verzweifelt, mit einem Python Skript als CGI auf meinem Strato Webhosting Server auf eine mySQL Datenbank zuzugreifen, was leider stets in folgender Fehlermeldung resultiert: "Error while connecting to MySQL 2055: Lost connection to MySQL server at 'rdbms.strato.de:3306', system error: 104 Connection reset by peer".

Das Skript sieht wie folgt aus:

Code: Alles auswählen

#!/usr/bin/python3
import cgi
import sys
sys.path.append("PATH TO SIDE PACKAGES DUE TO MISSING ROOT ACCESS")
import mysql.connector
from mysql.connector import Error

print('Content-type: text/html') # the mime-type header.
print() # header must be separated from body by 1 empty line.


try:
    connection_config_dict = {
        'user': 'MY_USER',
        'password': 'MY_PASSWORD',
        'host': 'rdbms.strato.de',
        'database': 'MY_DATABASE',

    }
    connection = mysql.connector.connect(**connection_config_dict)

    if connection.is_connected():
        db_Info = connection.get_server_info()
        print("Connected to MySQL Server version ", db_Info)
        cursor = connection.cursor()
        cursor.execute("select database();")
        record = cursor.fetchone()
        print("Your connected to database: ", record)

except Error as e:
    print("Error while connecting to MySQL", e)
finally:
    if connection.is_connected():
        cursor.close()
        connection.close()
        print("MySQL connection is closed")
Andere Python Skripte die ich zuvor getestet habe, die keine mySQL Verbindung beinhaltet haben, liefen problemlos. Auch die Login Daten sind definitiv korrekt, ein vergleichbares PHP Skript mit exakt den selben Daten funktioniert ohne Probleme. Für mich als Anfänger sieht die Fehlermeldung danach aus, dass Strato die Verbindung unterbindet, obwohl ich das Skript ja von ihrem Netzwerk aus ausführe. Ein paar mehr Informationen zu der Umgebung: Die Python Version auf dem Server ist 3.8.1, die mySQL Server Version 5.7, für die Verbindung vom Python Skript zur Datenbank nutze ich mysql_connector_python von mySQL/Oracle in der Version 8.0.23. Da es sich um das Webhosting Paket handelt, habe ich keinen Root Zugriff auf den Server, konnte via SSH und pip --user allerdings Module für mich lokal installieren und auch bereits erfolgreich verwenden (beispielsweise requests). Den Ordner mit den zusätzlichen Modulen habe ich mit sys.path.append eingebunden, siehe oben. Eine Fehlermeldung im Error Log des Servers wird nicht erzeugt.

Ich habe mich bereits an den Kundenservice von Strato gewandt, der mir allerdings in keinster Weise hilfreich sein konnte, sondern nur mit Textbausteinantworten aus der FAQ geantwortet und ziemlich am Thema vorbei geredet hat. Daher hoffe ich, dass mir eventuell hier jemand behilflich sein könnte und eine Idee hat, wie ich das ganze eventuell doch noch zum Laufen bekomme.

Vielen Dank im Voraus und ich hoffe, das Problem gut dargestellt zu haben.
Sirius3
User
Beiträge: 17711
Registriert: Sonntag 21. Oktober 2012, 17:20

Jetzt wäre es noch hilfreich, wenn man den wüßte, wo der Fehler tatsächlich auftritt. Die Fehlerbehandlung ist nicht wirklich sinnvoll, und stört mehr. Im Fehlerfall bekommst Du noch zusätzlich einen NameError, weil `connection` im finally-Block nicht definiert ist.
Konfigurationsdaten haben eigentlich nichts direkt im Pythonskript verloren, vor allem sollte in Variablennamen keine Typen vorkommen.
Tom_11
User
Beiträge: 5
Registriert: Samstag 27. März 2021, 19:02

Ich habe die Fehlerbehandlung einmal komplett rausgenommen:

Code: Alles auswählen

#!/usr/bin/python3
import cgi
import sys
sys.path.append(""PATH TO SIDE PACKAGES DUE TO MISSING ROOT ACCESS"")
import mysql.connector

print('Content-type: text/html') # the mime-type header.
print() # header must be separated from body by 1 empty line.


cnx = mysql.connector.connect(user='xxx', password='xxx',
                              host='rdbms.strato.de',
                              database='xxx')
cnx.close()
Als Resultat bekomme ich eine komplett weiße Seite angezeigt, was für mich als Anfänger ja per se Sinn macht, da kein (sichtbarer) Inhalt im Skript ausgegeben wird. Allerdings bekomme ich so auch keinerlei Fehlermeldung angezeigt, das Error Log auf dem Server ist ebenfalls leer. Wie kann ich herausfinden, wo genau der Fehler auftritt?
Sirius3
User
Beiträge: 17711
Registriert: Sonntag 21. Oktober 2012, 17:20

Jetzt macht Dein Skript auch im Erfolgsfall nichts. Also irgendetwas solltest Du schon ausgeben.
Tom_11
User
Beiträge: 5
Registriert: Samstag 27. März 2021, 19:02

Code: Alles auswählen

#!/usr/bin/python3
import cgi
import sys
sys.path.append("PATH TO SIDE PACKAGES DUE TO MISSING ROOT ACCESS")
import mysql.connector

print('Content-type: text/html') # the mime-type header.
print() # header must be separated from body by 1 empty line.


cnx = mysql.connector.connect(user='xxx', 
                              password='xxx',
                              host='rdbms.strato.de',
                              database='xxx')
print(cnx)
cnx.close()
Resultiert ebenfalls in einer Blankoseite, ebenfalls kein Eintrag im Serverlog.
Benutzeravatar
__blackjack__
User
Beiträge: 13004
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Tom_11: Mach mal ein ganz einfaches "Hallo Welt"-CGI ohne import vom Datenbankmodul, das einfach nur einen statischen Text ausgibt. Um zumindest mal *das* sicherzustellen.

Als nächstes dann eines wo zusätzlich noch das Ergebnis von 1/0 ausgegeben wird. Und dann schau mal in welchem Log der ZeroDivisionError auftaucht. Wenn Du den nirgends zu sehen bekommst, dann geht das mit CGI auf dem Webserver nicht wirklich sinnvoll, denn Fehler die einfach so verschluckt werden kann man nicht finden und beheben.
“Most people find the concept of programming obvious, but the doing impossible.” — Alan J. Perlis
Tom_11
User
Beiträge: 5
Registriert: Samstag 27. März 2021, 19:02

Code: Alles auswählen

#!/usr/bin/python3
import cgi
print('Content-type: text/html') # the mime-type header.
print() # header must be separated from body by 1 empty line.
print("Hello World")
Funktioniert und gibt ganz normal "Hello World" wieder.


Code: Alles auswählen

#!/usr/bin/python3
import cgi
print('Content-type: text/html') # the mime-type header.
print() # header must be separated from body by 1 empty line.
result = 1/0
print(result)
Gibt wieder nur eine weiße Seite wieder. Jetzt habe ich allerdings zusätzlich

Code: Alles auswählen

import cgitb
cgitb.enable()
hinzugefügt und bekomme den Division by Zero Fehler im Browser angezeigt. Nun habe ich das ganze nochmal in das vorherige Skript mit der mySQL Datenbankverbindung eingefügt und bekomme eine ganze Reihe an Fehlern angezeigt:

Code: Alles auswählen

--> -->
 
 
OperationalError	Python 3.8.8: /usr/bin/python3
Sun Mar 28 00:15:25 2021
A problem occurred in a Python script. Here is the sequence of function calls leading up to the error, in the order they occurred.

 /home/strato/xxx/htdocs/cgi-bin/abc_test.py in <module>
     12 
     13 
=>   14 cnx = mysql.connector.connect(user='xxx', 
=>   15                               password='xxx',
=>   16                               host='rdbms.strato.de',
cnx undefined, mysql = <module 'mysql' from '/home/strato/xxx/lib/python3.8/site-packages/mysql/__init__.py'>, mysql.connector = <module 'mysql.connector' from '/home/strato/www...on3.8/site-packages/mysql/connector/__init__.py'>, mysql.connector.connect = <function connect>, user undefined, password undefined, host undefined, database undefined
 /home/strato/xxx/htdocs/.local/lib/python3.8/site-packages/mysql/connector/__init__.py in connect(*args=(), **kwargs={'database': 'xxx', 'host': 'rdbms.strato.de', 'password': 'xxx', 'user': 'xxx'})
    276     if HAVE_CEXT and not use_pure:
    277         return CMySQLConnection(*args, **kwargs)
=>  278     return MySQLConnection(*args, **kwargs)
    279 Connect = connect  # pylint: disable=C0103
    280 
global MySQLConnection = <class 'mysql.connector.connection.MySQLConnection'>, args = (), kwargs = {'database': 'xxx', 'host': 'rdbms.strato.de', 'password': 'xxx', 'user': 'xxx'}
 /home/strato/www/ac/xxx/htdocs/.local/lib/python3.8/site-packages/mysql/connector/connection.py in __init__(self=<mysql.connector.connection.MySQLConnection object>, *args=(), **kwargs={'database': 'xxx', 'host': 'rdbms.strato.de', 'password': 'xxx', 'user': 'xxx'})
    106         if kwargs:
    107             try:
=>  108                 self.connect(**kwargs)
    109             except:
    110                 # Tidy-up underlying socket on failure
self = <mysql.connector.connection.MySQLConnection object>, self.connect = <bound method MySQLConnectionAbstract.connect of...sql.connector.connection.MySQLConnection object>>, kwargs = {'database': 'xxx', 'host': 'rdbms.strato.de', 'password': 'xxx', 'user': 'xxx'}
 /home/strato/xxx/htdocs/.local/lib/python3.8/site-packages/mysql/connector/abstracts.py in connect(self=<mysql.connector.connection.MySQLConnection object>, **kwargs={'database': 'xxx', 'host': 'rdbms.strato.de', 'password': 'xxx', 'user': 'xxx'})
   1001 
   1002         self.disconnect()
=> 1003         self._open_connection()
   1004         # Server does not allow to run any other statement different from ALTER
   1005         # when user's password has been expired.
self = <mysql.connector.connection.MySQLConnection object>, self._open_connection = <bound method MySQLConnection._open_connection o...sql.connector.connection.MySQLConnection object>>
 /home/strato/xxx/htdocs/.local/lib/python3.8/site-packages/mysql/connector/connection.py in _open_connection(self=<mysql.connector.connection.MySQLConnection object>)
    350         try:
    351             self._socket.open_connection()
=>  352             self._do_handshake()
    353             self._do_auth(self._user, self._password,
    354                           self._database, self._client_flags, self._charset_id,
self = <mysql.connector.connection.MySQLConnection object>, self._do_handshake = <bound method MySQLConnection._do_handshake of <mysql.connector.connection.MySQLConnection object>>
 /home/strato/www/ac/xxx/htdocs/.local/lib/python3.8/site-packages/mysql/connector/connection.py in _do_handshake(self=<mysql.connector.connection.MySQLConnection object>)
    148     def _do_handshake(self):
    149         """Get the handshake from the MySQL server"""
=>  150         packet = self._socket.recv()
    151         if packet[4] == 255:
    152             raise errors.get_exception(packet)
packet undefined, self = <mysql.connector.connection.MySQLConnection object>, self._socket = None, self._socket.recv undefined
 /home/strato/www/ac/xxx/htdocs/.local/lib/python3.8/site-packages/mysql/connector/network.py in recv_plain(self=<mysql.connector.network.MySQLTCPSocket object>)
    291             return packet
    292         except IOError as err:
=>  293             raise errors.OperationalError(
=>  294                 errno=2055, values=(self.get_address(), _strioerror(err)))
    295 
global errors = <module 'mysql.connector.errors' from '/home/str...thon3.8/site-packages/mysql/connector/errors.py'>, errors.OperationalError = <class 'mysql.connector.errors.OperationalError'>, errno undefined, values undefined, self = <mysql.connector.network.MySQLTCPSocket object>, self.get_address = <bound method MySQLTCPSocket.get_address of <mysql.connector.network.MySQLTCPSocket object>>, global _strioerror = <function _strioerror>, err undefined
OperationalError: 2055: Lost connection to MySQL server at 'rdbms.strato.de:3306', system error: 104 Connection reset by peer
      args = (2055, "2055: Lost connection to MySQL server at 'rdbms....3306', system error: 104 Connection reset by peer", None)
      errno = 2055
      msg = "Lost connection to MySQL server at 'rdbms.strato...3306', system error: 104 Connection reset by peer"
      sqlstate = None
      with_traceback = <built-in method with_traceback of OperationalError object>
Ich muss allerdings gestehen, dass mich persönlich das leider noch nicht auf die Lösung führt. Ein kleiner Hinweis noch dazu: Ich habe mittlerweile doch Fehlermeldungen von den Skriptausführungen früher am Abend gefunden, seltsamerweise scheint es, als würden diese bei meinem Strato Account ca 30min verzögert angezeigt werden. Den letzten Error im Log sehe ich von vor 35 Minuten, obwohl ich gerade eben mehrere produziert habe.
Benutzeravatar
__blackjack__
User
Beiträge: 13004
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Tom_11: Sieht also so aus als würde der Datenbankserver die Verbindung ablehnen/schliessen. Was sagt denn das Log vom MySQL zu den Verbindungsversuchen?
“Most people find the concept of programming obvious, but the doing impossible.” — Alan J. Perlis
Tom_11
User
Beiträge: 5
Registriert: Samstag 27. März 2021, 19:02

Ich habe bislang leider keine Möglichkeit gefunden, auf das MySQL Log zuzugreifen. Ich kann auf die Datenbank bei Strato via PhpMyAdmin und SSH zugreifen, allerdings habe ich auch dort keine Option gesehen, um sich Fehlermeldungen anzeigen zu lassen.
AntonKr69
User
Beiträge: 1
Registriert: Freitag 22. Juli 2022, 16:48

Hallo Tom,

ich bin noch nicht so weit und würde mich über Deine Unterstützung freuen....

Mein Python-Script läuft unter Windows super und ich würde es jetzt gerne bei Strato installieren.
Allerdings gibt es bei Strato die Pakete
- yaml
- mysql.connector
nicht.

Ich habe gesehen, dass Du diese anscheinend lokal installiert hast ('...PATH TO SIDE PACKAGES DUE TO MISSING ROOT ACCESS...').

Woher bekommt man die Pakete?

Vielen Dank für eine kurze Rückmeldung.

Anton
__deets__
User
Beiträge: 14493
Registriert: Mittwoch 14. Oktober 2015, 14:29

Bekommen tut man die wie alle anderen Pakete vom PyPi. Du musst die dann in Verzeichnis installieren, welches als site-packages dient. Und das dann in sys.path packen. Wenn man Pakete mit pip installiert, dann kann man ein Verzeichnis angeben, wohin die installiert werden sollen. Damit muesste das gehen.
Antworten