#!/bin/bash #==============================================================================# # # Mir diesem Skript kann man, mit einem einzigen Kommando, # eine voll funktionstüchtige MySQL-DBMS-Instanz erstellen. # #==============================================================================# #VERSION="v2025042500" # initiale Erstellung #VERSION="v2025050600" # ZFS-Tuning: compression=lz4 recordsize=1M VERSION="v2025051400" # Fehler behoben #------------------------------------------------------------------------------# #### Sicherheitsüberprüfungen # Prüfen, ob die übergebene Option leer ist. if [ x = "x${1}" ] ; then echo 'Es muß eine Portnummer für die neue MySQL-DBMS-Instanz übergeben werden!' echo " ${0} [Portnummer]" echo "zum Beispiel:" echo " ${0} 13309" echo "Abbruch" exit 1 fi # Prüfen, ob die übergebene Option eine Integer-Zahl, mit fünf Stellen, ist. I_FUENF="$(echo "${1}" | grep -E '^[0-9]{5}$')" if [ x = "x${I_FUENF}" ] ; then echo 'Bitte übergeben sie diesem Skript die gewünschte Portnummer.' echo 'Die übergebene Option muß eine Integer-Zahl, mit fünf Stellen, sein!' echo 'Abbruch' exit 1 else PORTNUMMER="${1}" fi if [ -e "/var/lib/mysql/port_${PORTNUMMER}" ] ; then echo 'Das gesuchte Verzeichnis existiert schon!' ls -d "/var/lib/mysql/port_${PORTNUMMER}" echo "Abbruch" exit 1 fi #------------------------------------------------------------------------------# ### Aktion: SystemD-Dateien erstellen DATEI_01="/etc/default/mysql.${PORTNUMMER}" if [ -e "${DATEI_01}" ] ; then echo "${DATEI_01} existiert schon" else echo "EXTRA_ARGS=\" --defaults-file=/var/lib/mysql/port_${PORTNUMMER}/etc/my.cnf \"" > ${DATEI_01} echo "MY_CNF_ARGS=\" --defaults-file=/var/lib/mysql/port_${PORTNUMMER}/etc/my.cnf \"" >> ${DATEI_01} fi ls -lha ${DATEI_01} DATEI_02="/etc/default/mysql.${PORTNUMMER}.bootstrap" if [ -e "${DATEI_02}" ] ; then echo "${DATEI_02} existiert schon" else echo "EXTRA_ARGS=\" --defaults-file=/var/lib/mysql/port_${PORTNUMMER}/etc/my.cnf --wsrep-new-cluster \"" > ${DATEI_02} echo "MY_CNF_ARGS=\" --defaults-file=/var/lib/mysql/port_${PORTNUMMER}/etc/my.cnf \"" >> ${DATEI_02} fi ls -lha ${DATEI_02} ### diese Datei ist nicht speziell für eine Portnummer ### und gehört deshalb zur Allgemeinen/Globalen Konfiguration DATEI_03="/usr/bin/mysql-systemd_port" if [ -x "${DATEI_03}" ] ; then echo "${DATEI_03} existiert schon" else cat /usr/bin/mysql-systemd | sed 's/my_print_defaults /&${MY_CNF_ARGS} /;' > ${DATEI_03} chmod 0755 ${DATEI_03} fi ls -lha ${DATEI_03} ### diese Datei ist nicht speziell für eine Portnummer ### und gehört deshalb zur Allgemeinen/Globalen Konfiguration DATEI_04="/usr/lib/systemd/system/mysql_port@.service" if [ -x "${DATEI_04}" ] ; then echo "${DATEI_04} existiert schon" else cat /usr/lib/systemd/system/mysql@.service | sed 's/^Alias=.*/Alias=mysqld_port.service/;s/mysql-systemd /mysql-systemd_port /' > ${DATEI_04} fi ls -lha ${DATEI_04} #------------------------------------------------------------------------------# ### Aktion: ZFS-Volumen mit Verzeichnissen erstellen # # Es wird empfohlen, für DataDir und Log-Bin unterschiedliche ZFS-Volumen (DataSets) # zu verwenden und das ZFS-Volumen für DataDir mit "recordsize=16K" zu konfigurieren. # zfs create -o mountpoint=/var/lib/mysql/port_${PORTNUMMER} mysql_datadir/port_${PORTNUMMER} chown -R mysql:mysql /var/lib/mysql/port_${PORTNUMMER} # https://www.zfshandbook.com/docs/advanced-zfs/performance-tuning/ # https://openzfs.readthedocs.io/en/latest/performance-tuning.html zfs set compression=lz4 mysql_datadir/port_${PORTNUMMER} zfs set recordsize=16K mysql_datadir/port_${PORTNUMMER} zfs set logbias=throughput mysql_datadir/port_${PORTNUMMER} mkdir -p /var/lib/mysql/port_${PORTNUMMER}/datadir/ mkdir -p /var/lib/mysql/port_${PORTNUMMER}/etc/conf.d/ mkdir -p /var/lib/mysql/port_${PORTNUMMER}/XtraBackup/ mkdir -p /var/lib/mysql/port_${PORTNUMMER}/log_bin/ mkdir -p /var/lib/mysql/port_${PORTNUMMER}/relay_log/ mkdir -p /var/lib/mysql/port_${PORTNUMMER}/log mkdir -p /var/lib/mysql/port_${PORTNUMMER}/tmpdir # Insecure configuration for --secure-log-path: Location is accessible to all OS users. Consider choosing a different directory. chmod 0750 /var/lib/mysql/port_${PORTNUMMER}/log chmod 0777 /var/lib/mysql/port_${PORTNUMMER}/tmpdir chown -R mysql:mysql /var/lib/mysql/port_${PORTNUMMER} #------------------------------------------------------------------------------# ### Aktion: MySQL-CNF-Dateien erstellen mkdir -p /var/run/mysqld/ chown mysql:mysql /var/run/mysqld/ #==========================================# # my.cnf echo "# /var/lib/mysql/port_${PORTNUMMER}/etc/my.cnf !includedir /etc/mysql/meine.conf.d/ !includedir /var/lib/mysql/port_${PORTNUMMER}/etc/conf.d/ " > /var/lib/mysql/port_${PORTNUMMER}/etc/my.cnf #==========================================# # client.cnf echo "# /var/lib/mysql/port_${PORTNUMMER}/etc/conf.d/client.cnf [client] port = ${PORTNUMMER} socket = /var/run/mysqld/mysqld_${PORTNUMMER}.sock " > /var/lib/mysql/port_${PORTNUMMER}/etc/conf.d/client.cnf #==========================================# # mysqld.cnf SERVER_ID="$(hostname -f | sed 's/[0-9][a-zA-Z][-].*[0-9][0-9]/"&/; s/^[^"]*["]//; s/^.//; s/^./&"/; s/["][^"]*$//; s/[aA]/1/;s/[bB]/2/;s/[cC]/3/;')" # 3 REPORTNUMMER="$(echo "${PORTNUMMER}" | awk '{print $1 - 10000}')" REPORTKENNUNG="$(hostname -f | sed 's/[0-9][a-zA-Z][-].*[0-9][0-9]/"&"/; s/^[^"]*["]//; s/["][^"]*$//; s/[-][^0-9]*//;')" # 1C01 MYSQLX_PORT="$(echo "${PORTNUMMER}" | awk '{print $1 + 100}')" ADMIN_PORT="$(echo "${PORTNUMMER}" | awk '{print $1 + 200}')" echo "# /var/lib/mysql/port_${PORTNUMMER}/etc/conf.d/mysqld.cnf #------------------------------------------------------------------------------# [mysqld] server_id = ${SERVER_ID} report_host = mysql_${REPORTNUMMER}-${REPORTKENNUNG} port = ${PORTNUMMER} mysqlx_port = ${MYSQLX_PORT} admin_port = ${ADMIN_PORT} datadir = /var/lib/mysql/port_${PORTNUMMER}/datadir socket = /var/run/mysqld/mysqld_${PORTNUMMER}.sock mysqlx_socket = /var/run/mysqld/mysqlx_${PORTNUMMER}.sock secure_log_path = /var/lib/mysql/port_${PORTNUMMER}/log log-error = /var/lib/mysql/port_${PORTNUMMER}/log/mysqld_error.log general_log_file = /var/lib/mysql/port_${PORTNUMMER}/log/mysqld_general.log slow_query_log_file = /var/lib/mysql/port_${PORTNUMMER}/log/mysqld_slow_query.log tmpdir = /var/lib/mysql/port_${PORTNUMMER}/tmpdir # Binary log expiration period is 604800 seconds, which equals 7 days binlog_expire_logs_seconds = 604800 log_bin = /var/lib/mysql/port_${PORTNUMMER}/log_bin/mysql-bin log_bin_index = /var/lib/mysql/port_${PORTNUMMER}/log_bin/mysql-bin.index relay_log = /var/lib/mysql/port_${PORTNUMMER}/relay_log/mysql-relay-bin relay_log_index = /var/lib/mysql/port_${PORTNUMMER}/relay_log/mysql-relay-bin.index # The syntax '--relay-log-info-file' is deprecated and will be removed in a future release. relay_log_info_file = /var/lib/mysql/port_${PORTNUMMER}/relay_log/relay-log.info #------------------------------------------------------------------------------# #innodb_flush_method = O_DIRECT # innodb_autoinc_lock_mode changes how InnoDB autoincrement locks are managed and is a requirement for Galera innodb_autoinc_lock_mode = 2 innodb_file_per_table = ON innodb_flush_log_at_trx_commit = 2 innodb_thread_concurrency = 0 # # siehe: mysqltuner.pl # innodb_log_buffer_size = 16MB innodb_redo_log_capacity = 256M innodb_buffer_pool_instances = 1 innodb_buffer_pool_size = 1G binlog_cache_size = 2M # # siehe: SHOW STATUS LIKE 'Max_used_connections%'; #" > /var/lib/mysql/port_${PORTNUMMER}/etc/conf.d/mysqld.cnf . /root/bin/Neue_MySQL-Instanz_mysqld_cnf.txt #==========================================# # mysqld_safe.cnf echo "# /var/lib/mysql/port_${PORTNUMMER}/etc/conf.d/mysqld_safe.cnf # 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 [mysqld_safe] pid-file = mysqld.pid socket = /var/run/mysqld/mysqld_${PORTNUMMER}.sock nice = 0 " > /var/lib/mysql/port_${PORTNUMMER}/etc/conf.d/mysqld_safe.cnf #==========================================# # wsrep.cnf NODE_ADDRESS="$(ip a | grep -F 'inet 192.168.1.' | awk '{gsub("/"," "); print $2}')" SST_PORT="$(echo "${PORTNUMMER}" | awk '{print ($1 - 10000) * 10 + 4}')" INTERCOM_PORT="$(echo "${PORTNUMMER}" | awk '{print ($1 - 10000) * 10 + 7}')" echo "# /var/lib/mysql/port_${PORTNUMMER}/etc/conf.d/wsrep.cnf [mysqld] # Path to Galera library wsrep_provider = /usr/lib/libgalera_smm.so #wsrep_provider = /usr/lib/galera3/libgalera_smm.so #wsrep_provider = /usr/lib/galera4/libgalera_smm.so # Cluster connection URL contains IPs of nodes #If no IP is found, this implies that a new cluster needs to be created, #in order to do that you need to bootstrap this node ### Standard für InterCom: 4567 -> 33XX7 wsrep_cluster_address = gcomm:// #wsrep_cluster_address = gcomm://192.168.1.61:${INTERCOM_PORT},192.168.1.62:${INTERCOM_PORT},192.168.1.63:${INTERCOM_PORT} # Slave thread to use wsrep_applier_threads = 8 wsrep_log_conflicts # Node IP address #wsrep_node_address = 192.168.70.63 wsrep_node_address = ${NODE_ADDRESS} # Cluster name #wsrep_cluster_name = pxc-cluster wsrep_cluster_name = pxc-cluster_${REPORTNUMMER} # kompatibel zur alten Umgebung im 2.O.G. #If wsrep_node_name is not specified, then system hostname will be used wsrep_node_name = pxc-${REPORTNUMMER}-${REPORTKENNUNG} #pxc_strict_mode allowed values: DISABLED,PERMISSIVE,ENFORCING,MASTER pxc_strict_mode = ENFORCING # SST method wsrep_sst_method = xtrabackup-v2 #------------------------------------------------------------------------------# ### Standard für SST: 4444 -> 33XX4 (das , am Zeilenende muss unbedingt bleiben) wsrep_sst_donor = 192.168.1.61:${SST_PORT},192.168.1.62:${SST_PORT},192.168.1.63:${SST_PORT} ### Standard für IST / replication: 4568 -> 33XX8 (:) ### Standard für GCache: 128 MB -> 4G ### IST bezieht seine Daten aus dem GCache, vergleichbar mit der BIN-LOG-Historie bei GTID-Replikation ### Je größer der GCache ist, desto länger dürfen Wartungsarbeiten sein. wsrep_provider_options = \"gcache.recover=yes;gcache.size=4G;\" #------------------------------------------------------------------------------# pxc-encrypt-cluster-traffic = OFF " > /var/lib/mysql/port_${PORTNUMMER}/etc/conf.d/wsrep.cnf #==========================================# # wsrep_knoten.cnf echo "# /var/lib/mysql/port_${PORTNUMMER}/etc/conf.d/wsrep_knoten.cnf [mysqld] ### Standard für SST: 4444 -> 33XX4 wsrep_sst_receive_address = ${NODE_ADDRESS}:${SST_PORT} # ### Standard: 4567 (InterCom) -> 33XX7 (Referenzadresse für viele andere Variablen) wsrep_node_address = ${NODE_ADDRESS}:${INTERCOM_PORT} " > /var/lib/mysql/port_${PORTNUMMER}/etc/conf.d/wsrep_knoten.cnf #------------------------------------------------------------------------------# ### Aktion: DataDir mit Daten füllen / DBMS initialisieren # https://dev.mysql.com/doc/refman/8.0/en/data-directory-initialization.html # Bei der Initialisierung des Datenverzeichnisses sollten Sie keine anderen Optionen als diese angeben: # --basedir oder --datadir # --user # --initialize oder --initialize-insecure # # https://www.middlewareinventory.com/blog/mysql-error-unable-lock-ibdata1/ # #mysqld --datadir=/var/lib/mysql/port_${PORTNUMMER}/datadir/ --user=mysql --initialize #grep -F 'A temporary password is generated for root@localhost:' /var/lib/mysql/port_${PORTNUMMER}/log/mysqld_error.log # #mysqld --datadir=/var/lib/mysql/port_${PORTNUMMER}/datadir/ --user=mysql --initialize-insecure echo "mysqld --no-defaults --datadir=/var/lib/mysql/port_${PORTNUMMER}/datadir/ --user=mysql --initialize-insecure" mysqld --no-defaults --datadir=/var/lib/mysql/port_${PORTNUMMER}/datadir/ --user=mysql --initialize-insecure echo "rm -f /var/lib/mysql/port_${PORTNUMMER}/datadir/auto.cnf /var/lib/mysql/port_${PORTNUMMER}/datadir/*.pem" rm -f /var/lib/mysql/port_${PORTNUMMER}/datadir/auto.cnf /var/lib/mysql/port_${PORTNUMMER}/datadir/*.pem #------------------------------------------------------------------------------# ### Aktion: DataDir mit Daten füllen / DBMS initialisieren # Erster Start nach der Initialisierung # mit '--skip-grant-tables' kann man seit MySQL 8.0 das root-Passwort nicht mehr ändern, nur noch löschen echo "(mysqld --defaults-file=/var/lib/mysql/port_${PORTNUMMER}/etc/my.cnf --datadir=/var/lib/mysql/port_${PORTNUMMER}/datadir/ --user=mysql) &" (mysqld --defaults-file=/var/lib/mysql/port_${PORTNUMMER}/etc/my.cnf --datadir=/var/lib/mysql/port_${PORTNUMMER}/datadir/ --user=mysql) & echo # # root ein Passwort geben ls -lha /root/.my.cnf PWT="$(grep -E '^password' /root/.my.cnf 2>/dev/null | awk '{gsub("="," "); print $NF}')" if [ x = "x${PWT}" ] ; then passwortabfrage() { echo echo "Bitte geben Sie das root-Passwort für das neue DBMS ein:" read PWT1 echo echo "Bitte das neue root-Passwort einmal wiederholen:" read PWT2 echo } passwort_abfrage() { passwortabfrage if [ "${PWT1}" != "${PWT2}" ] ; then passwort_abfrage fi } passwort_abfrage} fi sleep 2 echo echo "Kein Passwort eingeben, einfach nur ENTER drücken!" echo "echo \"ALTER USER 'root'@'localhost' IDENTIFIED BY '${PWT}'; FLUSH PRIVILEGES;\" | mysql -S /var/run/mysqld/mysqld_${PORTNUMMER}.sock -p" echo "ALTER USER 'root'@'localhost' IDENTIFIED BY '${PWT}'; FLUSH PRIVILEGES;" | mysql -S /var/run/mysqld/mysqld_${PORTNUMMER}.sock -p # # root auf machen echo "echo \"UPDATE mysql.user SET host='%' WHERE user='root'; FLUSH PRIVILEGES;\" | mysql -S /var/run/mysqld/mysqld_${PORTNUMMER}.sock -uroot" echo "UPDATE mysql.user SET host='%' WHERE user='root'; FLUSH PRIVILEGES;" | mysql -S /var/run/mysqld/mysqld_${PORTNUMMER}.sock -uroot -p"${PWT}" # # Benutzer anzeigen #echo "SELECT host,user,plugin,password_last_changed,authentication_string FROM mysql.user;" | mysql -S /var/run/mysqld/mysqld_${PORTNUMMER}.sock -t echo "echo 'SELECT host,user,plugin,password_last_changed FROM mysql.user;' | mysql -S /var/run/mysqld/mysqld_${PORTNUMMER}.sock -uroot -t" echo 'SELECT host,user,plugin,password_last_changed FROM mysql.user;' | mysql -S /var/run/mysqld/mysqld_${PORTNUMMER}.sock -uroot -p"${PWT}" -t # # einfacher Zugriff per root funktioniert jetzt echo "mysqlshow -S /var/run/mysqld/mysqld_${PORTNUMMER}.sock -uroot" mysqlshow -S /var/run/mysqld/mysqld_${PORTNUMMER}.sock -uroot -p"${PWT}" # #------------------------------------------------------------------------------# # MySQL-Dienst wieder beenden #MY_PID_02="$(ps alxwww | grep -Fv grep | grep -F mysqld | grep -F /var/lib/mysql/port_${PORTNUMMER}/etc/my.cnf | awk '{print $3}')" MY_PID_02="$(ps alxwww | grep -Fv grep | grep -F mysqld | grep -F "datadir=/var/lib/mysql/port_${PORTNUMMER}/datadir/" | awk '{print $3}')" if [ x != "x${MY_PID_02}" ] ; then echo "kill -15 ${MY_PID_02}" kill -15 ${MY_PID_02} sleep 20 fi #------------------------------------------------------------------------------# # DBMS regulär starten # ab jetzt kann man diesen MySQL-Dienst auch per SystemD starten und stoppen rm -f /var/lib/mysql/port_${PORTNUMMER}/datadir/auto.cnf /var/lib/mysql/port_${PORTNUMMER}/datadir/*.pem service mysql_port@${PORTNUMMER} restart sleep 1 # Probeaufruf echo "mysqlshow -S /var/run/mysqld/mysqld_${PORTNUMMER}.sock -uroot" mysqlshow -S /var/run/mysqld/mysqld_${PORTNUMMER}.sock -uroot -p"${PWT}" echo "################################################################################" grep -F ERROR /var/lib/mysql/port_${PORTNUMMER}/log/mysqld_error.log echo "################################################################################" #------------------------------------------------------------------------------# ### Zum guten Schluß gibt es noch ein paar Hinweise. systemctl daemon-reload JETZT="$(date +'%F_%H-%M-%S')" echo " # So wird das BDMS behandelt: > service mysql_port@${PORTNUMMER}.bootstrap start > service mysql_port@${PORTNUMMER}.bootstrap status > service mysql_port@${PORTNUMMER}.bootstrap stop > service mysql_port@${PORTNUMMER} start > service mysql_port@${PORTNUMMER} status > service mysql_port@${PORTNUMMER} stop > mysqlshow -S /var/run/mysqld/mysqld_${PORTNUMMER}.sock > echo 'SELECT host,user,plugin,password_last_changed,authentication_string FROM mysql.user;' | mysql -S /var/run/mysqld/mysqld_${PORTNUMMER}.sock -t > echo \"SHOW VARIABLES LIKE '%ssl%';\" | mysql -S /var/run/mysqld/mysqld_${PORTNUMMER}.sock -t > echo \"SHOW VARIABLES WHERE variable_name IN ('hostname','wsrep_node_name','wsrep_cluster_name','port','ssl_ca','ssl_cert','ssl_key'); SHOW STATUS LIKE '%Ssl_server_not_%';\" | mysql -S /var/run/mysqld/mysqld_${PORTNUMMER}.sock -t > mysqlshow --ssl-ca=/etc/mysql/ca.pem --ssl-mode=VERIFY_CA -S /var/run/mysqld/mysqld_${PORTNUMMER}.sock zum kompletten und unwiederbringlichen entfernen dieser MySQL-DBMS-Instanz, ist nur dieses Kommando nötig: /root/bin/Neue_MySQL-Instanz_löschen.sh ${PORTNUMMER} " #------------------------------------------------------------------------------# # damit keiner etwas illegales unten anhängen kann exit