1 votes

Mysql écoute le mauvais port au redémarrage

Je travaille sur un projet PHP "local". Il s'agit d'une application PHP fonctionnant dans une VM Debian destinée à être utilisée sur le propre PC de l'utilisateur.

J'ai quelques scripts Python qui tournent en tant que services racine depuis /etc/init.d et qui gèrent les mises à jour des applications, les journaux, la communication avec les périphériques USB et d'autres choses.

EDIT 1 : La VM est une image Turnkey Linux LAMP, la version de Python est 2.7.3 et MySQL 5.5.47.

L'application PHP communique avec les services Python via des sockets TCP et envoie des requêtes pour les tâches spécifiques dont l'utilisateur a besoin.

J'essaie maintenant de laisser l'utilisateur choisir entre lier le serveur MySQL uniquement à localhost ou le partager avec d'autres utilisateurs du réseau. Pour cela, je demande au service Python de parcourir le fichier my.cnf et de commenter la ligne bind-address = 127.0.0.1, ou de la décommenter pour que le serveur redevienne local.

Après l'édition de my.cnf, le script Python appelle /etc/init.d/mysql restart pour que les changements prennent effet.

Le problème est que maintenant, mysql finit par écouter sur le port sur lequel le service Python écoutait pour les requêtes PHP, et si je dois redémarrer le service, Python échoue, prétendant qu'il ne peut pas ouvrir le port parce qu'il est déjà utilisé.

Je n'arrive pas à comprendre pourquoi mysql finit par écouter sur le port utilisé par le service Python au lieu de 3306 comme le dit le fichier my.cnf.

De plus, si je me connecte à la machine virtuelle et que je redémarre manuellement mysql, il recommence à écouter sur 3306 et je peux lancer le service Python sans problème.

Un peu de code du côté de Python :

RECV_BUFFER = 4096
DAEMON_PORT = 5555

daemon_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
daemon_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
daemon_socket.bind(("localhost", DAEMON_PORT))
daemon_socket.listen(10)

//// SOCKET HANDLING, QUEUE and etc

if (data =='share:enable'):
    import fileinput
    import re
    import subprocess

    for line in fileinput.input('/etc/mysql/my.cnf', inplace = 1): 
        print re.sub(r'#*bind-address',"#bind-address", line),

    print subprocess.check_output(['/etc/init.d/mysql','restart'])

Exemple de sortie :

$> lsof -i
...
...
python    17219        root    4u  IPv4  25311      0t0  TCP localhost:5555 (LISTEN)   
mysqld    20773       mysql   10u  IPv4  33299      0t0  TCP localhost:mysql (LISTEN)
$> echo 'share:enable' | netcat localhost 5555
$> lsof -i
....
....
python    17219        root    4u  IPv4  25311      0t0  TCP localhost:5555 (LISTEN)                                           
mysqld_sa 17361        root    4u  IPv4  25311      0t0  TCP localhost:5555 (LISTEN)                                           
mysqld    17856       mysql    4u  IPv4  25311      0t0  TCP localhost:5555 (LISTEN)                                           
mysqld    17856       mysql   13u  IPv4  25782      0t0  TCP localhost:mysql (LISTEN)                                          
logger    17857        root    4u  IPv4  25311      0t0  TCP localhost:5555 (LISTEN) 

Edit 2 : Ajout de mon fichier de configuration MySQL my.cnf.

#                                                                                                                                                                              
# The MySQL database server configuration file.
#                                                                                                                                                                              
# You can copy this to one of: 
# - "/etc/mysql/my.cnf" to set global options, 
# - "~/.my.cnf" to set user-specific options.
#                                                                                                                                                                              
# One can use all long options that the program supports. 
# Run program with --help to get a list of available options and with 
# --print-defaults to see which it would actually understand and use.
#                                                                                                                                                                              
# For explanations see 
# http://dev.mysql.com/doc/mysql/en/server-system-variables.html

# This will be passed to all mysql clients 
# It has been reported that passwords should be enclosed with ticks/quotes 
# escpecially if they contain "#" chars... 
# Remember to edit /etc/mysql/debian.cnf when changing the socket location.
[client]
port = 3306 
socket = /var/run/mysqld/mysqld.sock

# Here is entries for some specific programs 
# The following values assume you have at least 32M ram

# This was formally known as [safe_mysqld]. Both versions are currently parsed.
[mysqld_safe] 
socket = /var/run/mysqld/mysqld.sock 
nice = 0

[mysqld]
#                                                                                                                                                                              
# * Basic Settings
#                                                                                                                                                                              
user = mysql 
pid-file = /var/run/mysqld/mysqld.pid 
socket = /var/run/mysqld/mysqld.sock 
port = 3306 
basedir = /usr 
datadir = /var/lib/mysql 
tmpdir = /tmp 
lc-messages-dir = /usr/share/mysql 
skip-external-locking
#                                                                                                                                                                              
# Instead of skip-networking the default is now to listen only on 
# localhost which is more compatible and is not less secure.
bind-address = 127.0.0.1
#                                                                                                                                                                              
# * Fine Tuning
#                                                                                                                                                                              
key_buffer = 16M 
max_allowed_packet = 16M 
thread_stack = 192K 
thread_cache_size = 8
# This replaces the startup script and checks MyISAM tables if needed 
# the first time they are touched
myisam-recover = BACKUP
#max_connections = 100 
#table_cache = 64 
#thread_concurrency = 10
#                                                                                                                                                                              
# * Query Cache Configuration
#                                                                                                                                                                              
query_cache_limit = 1M 
query_cache_size = 16M
#                                                                                                                                                                              
# * Logging and Replication
#                                                                                                                                                                              
# Both location gets rotated by the cronjob. 
# Be aware that this log type is a performance killer. 
# As of 5.1 you can enable the log at runtime! 
#general_log_file = /var/log/mysql/mysql.log 
#general_log = 1
#                                                                                                                                                                              
# Error logging goes to syslog due to /etc/mysql/conf.d/mysqld_safe_syslog.cnf.
#                                                                                                                                                                              
# Here you can see queries with especially long duration 
#log_slow_queries = /var/log/mysql/mysql-slow.log 
#long_query_time = 2 
#log-queries-not-using-indexes
#                                                                                                                                                                              
# The following can be used as easy to replay backup logs or for replication. 
# note: if you are setting up a replication slave, see README.Debian about
#       other settings you may need to change. 
#server-id = 1 
#log_bin = /var/log/mysql/mysql-bin.log
expire_logs_days = 10 
max_binlog_size = 100M
#binlog_do_db = include_database_name 
#binlog_ignore_db = include_database_name
#                                                                                                                                                                              
# * InnoDB
#                                                                                                                                                                              
# InnoDB is enabled by default with a 10MB datafile in /var/lib/mysql/. 
# Read the manual for more InnoDB related options. There are many!
#                                                                                                                                                                              
# * Security Features
#                                                                                                                                                                              
# Read the manual, too, if you want chroot! 
# chroot = /var/lib/mysql/
#                                                                                                                                                                              
# For generating SSL certificates I recommend the OpenSSL GUI "tinyca".
#                                                                                                                                                                              
# ssl-ca=/etc/mysql/cacert.pem 
# ssl-cert=/etc/mysql/server-cert.pem 
# ssl-key=/etc/mysql/server-key.pem

[mysqldump] 
#quick quote-names 
max_allowed_packet = 16M

[mysql]
#no-auto-rehash # faster start of mysql but no tab completition

[isamchk] 
key_buffer = 16M

#                                                                                                                                                                              
# * IMPORTANT: Additional settings that can override those from this file!
#   The files must end with '.cnf', otherwise they'll be ignored.
#                                                                                                                                                                              
!includedir /etc/mysql/conf.d/

6voto

Matthew Ife Points 22370

Cela a moins à voir avec mysql et plus à voir avec Python.

Lorsque vous démarrez un processus, il hérite de beaucoup d'informations sur le processus qui l'a créé, y compris ses descripteurs de fichiers. Ce que vous avez trouvé, c'est que mysql hérite du socket d'écoute que votre processus a créé lorsqu'il a été créé.

Pour résoudre ce problème, vous devez modifier votre code Python pour ne pas utiliser subprocess.check_output(...) et utiliser à la place subprocess.Popen(..., close_fds=True)

Alternativement, définir le drapeau CLOEXEC sur votre socket l'empêchera d'être hérité du tout - bien que vous deviez vérifier que ce comportement fonctionne dans tous vos chemins de code et que rien d'étrange ne se produit à cause de cela. Ce qui suit est la base pour faire cela.

from fcntl import fcntl, FD_CLOEXEC, F_GETFD, F_SETFD

flags = fcntl(socketfd, F_GETFD)
flags |= FD_CLOEXEC
fcntl(socketfd, F_SETFD, flags)

L'un ou l'autre résoudra le problème de prise d'écoute que vous avez.

SistemesEz.com

SystemesEZ est une communauté de sysadmins où vous pouvez résoudre vos problèmes et vos doutes. Vous pouvez consulter les questions des autres sysadmins, poser vos propres questions ou résoudre celles des autres.

Powered by:

X