Inicio Apuntes FPApuntes DAM Control básico de la pila LAMP con Python y Tkinter

Control básico de la pila LAMP con Python y Tkinter

Linux - Apache - MySQL/MariaDB - PHP

Publicado por entreunosyceros

Una vez más aquí. Hoy vengo a dejar un pequeño artículo para algo que a mi me ha servido, y que quizás a otros les pueda servir. En el mundo del desarrollo web, supongo que es conocido por muchos, que la pila LAMP (Linux, Apache, MySQL/MariaDB, PHP) es una de las combinaciones más populares para la creación y gestión de sitios web dinámicos. La habilidad para controlar estos servicios de manera eficiente y efectiva es fundamental para los desarrolladores y administradores.

En ocasiones, la gestión más básica de estos servicios (reiniciar, parar e iniciar) resulta interesante poder realizarla desde el escritorio (por uno u otro motivo). Esto es algo que hace años, cuando estudiaba, en Windows se hacía con XAMPP (supongo que se seguirá haciendo) y su panel de control, pero es algo que siempre eché en falta en Linux. Aun que seguramente exista ya, yo no lo conozco. Y si tú tampoco lo conoces, y por lo que sea te interesa disponer de un panel de control para realizar estas tareas básicas, en este artículo, exploraremos un ejemplo sencillo de cómo crear nuestra propia aplicación de control básico de la pila LAMP utilizando para ello Python y Tkinter para construir la interfaz gráfica.

Introducción a la aplicación para el control básico de la pila LAMP

Control básico de la pila LAMP

Como decía, la aplicación que vamos a construir proporcionará al usuario una interfaz gráfica para iniciar, detener y reiniciar los servicios de Apache y MySQL/MariaDB. Además me pareció útil disponer también de una opción para abrir phpMyAdmin y la terminal MySQL/MariaDB. Todo esto, creo que puede simplificar el proceso de gestión de la pila LAMP para los usuarios.

Un vistazo rápido al código de la aplicación para el control básico de la pila LAMP

Toda la aplicación se reduce tan solo a un archivo, que en mi caso llamé index.py. Y dentro el contenido es el siguiente:

import tkinter as tk
from tkinter import simpledialog, messagebox
import subprocess
import webbrowser

class LAMPControlApp:
    def __init__(self, master):
        self.master = master
        master.title("Control de Servicios LAMP") # Título de la ventana
        master.geometry("700x400")  # Ajusta el tamaño de la ventana

        # Establece el icono de la ventana
        icon_image = tk.PhotoImage(file="lamp.png")
        master.iconphoto(True, icon_image)

        # Frame para botones de inicio/detención
        control_frame = tk.Frame(master)
        control_frame.pack(pady=10, side="top", anchor="center")

        # Frame para mensajes de estado
        status_frame = tk.Frame(master)
        status_frame.pack(pady=10, side="top", anchor="center")

        # Frame para la versión de PHP
        php_frame = tk.Frame(master)
        php_frame.pack(pady=10, side="top", anchor="center")

        # Botones de inicio y detención de LAMP
        self.start_lamp_button = tk.Button(control_frame, text="Iniciar LAMP", command=self.start_lamp)
        self.start_lamp_button.grid(row=0, column=0, padx=5, pady=5)
        self.stop_lamp_button = tk.Button(control_frame, text="Detener LAMP", command=self.stop_lamp)
        self.stop_lamp_button.grid(row=0, column=1, padx=5, pady=5)
        self.restart_lamp_button = tk.Button(control_frame, text="Reiniciar LAMP", command=self.restart_lamp)
        self.restart_lamp_button.grid(row=0, column=2, padx=5, pady=5)
        
        # Botones de inicio y detención de Apache
        self.start_apache_button = tk.Button(control_frame, text="Iniciar Apache", command=self.start_apache)
        self.start_apache_button.grid(row=1, column=0, padx=5, pady=5)
        self.stop_apache_button = tk.Button(control_frame, text="Detener Apache", command=self.stop_apache)
        self.stop_apache_button.grid(row=1, column=1, padx=5, pady=5)
        self.restart_apache_button = tk.Button(control_frame, text="Reiniciar Apache", command=self.restart_apache)
        self.restart_apache_button.grid(row=1, column=2, padx=5, pady=5)

        # Botones de inicio y detención de MySQL/MariaDB
        self.start_db_button = tk.Button(control_frame, text="Iniciar MySQL/MariaDB", command=self.start_db)
        self.start_db_button.grid(row=2, column=0, padx=5, pady=5)
        self.stop_db_button = tk.Button(control_frame, text="Detener MySQL/MariaDB", command=self.stop_db)
        self.stop_db_button.grid(row=2, column=1, padx=5, pady=5)
        self.restart_db_button = tk.Button(control_frame, text="Reiniciar MySQL/MariaDB", command=self.restart_db)
        self.restart_db_button.grid(row=2, column=2, padx=5, pady=5)

        # Botón para abrir phpMyAdmin
        self.open_phpmyadmin_button = tk.Button(control_frame, text="Abrir phpMyAdmin", command=self.open_phpmyadmin)
        self.open_phpmyadmin_button.grid(row=3, column=0, padx=5, pady=5)

        # Botón para abrir terminal MySQL/MariaDB
        self.open_mysql_terminal_button = tk.Button(control_frame, text="Abrir Terminal MySQL/MariaDB", command=self.open_mysql_terminal)
        self.open_mysql_terminal_button.grid(row=3, column=1, padx=5, pady=5)

        # Etiqueta para mostrar el estado de LAMP
        self.lamp_status_label = tk.Label(status_frame, text="Estado de LAMP: Desconocido", font=("Arial", 12))
        self.lamp_status_label.pack(pady=5)

        # Etiqueta para mostrar la versión de PHP
        php_version_label = tk.Label(php_frame, text="Versión de PHP instalada:", font=("Arial", 12))
        php_version_label.pack(pady=5)

        php_version = self.get_php_version()
        php_version_display = tk.Label(php_frame, text=php_version, font=("Arial", 12))
        php_version_display.pack(pady=5)
        
        # Actualizar estatus
        self.update_status()

    # Método para iniciar LAMP
    def start_lamp(self):
        password = self.ask_password()
        if password:
            self.start_apache(password)
            self.start_db(password)
            self.show_status_message("LAMP iniciado", "green")
            self.update_status()

    # Método para detener LAMP
    def stop_lamp(self):
        password = self.ask_password()
        if password:
            self.stop_apache(password)
            self.stop_db(password)
            self.show_status_message("LAMP detenido", "red")
            self.update_status()

    # Método para iniciar Apache
    def start_apache(self, password=None):
        self.execute_command("sudo systemctl start apache2", password)
        self.show_status_message("Apache iniciado", "green")

    # Método para detener Apache
    def stop_apache(self, password=None):
        self.execute_command("sudo systemctl stop apache2", password)
        self.show_status_message("Apache detenido", "red")

    # Método para iniciar la base de datos (MySQL/MariaDB)
    def start_db(self, password=None):
        if self.is_service_installed("mariadb"):
            service = "mariadb"
        elif self.is_service_installed("mysql"):
            service = "mysql"
        else:
            self.show_status_message("No se encontró MySQL o MariaDB instalado.")
            return

        self.execute_command(f"sudo systemctl start {service}", password)
        self.show_status_message(f"{service.capitalize()} iniciado", "green")

    # Método para detener la base de datos (MySQL/MariaDB)
    def stop_db(self, password=None):
        if self.is_service_installed("mariadb"):
            service = "mariadb"
        elif self.is_service_installed("mysql"):
            service = "mysql"
        else:
            self.show_status_message("No se encontró MySQL o MariaDB instalado.")
            return

        self.execute_command(f"sudo systemctl stop {service}", password)
        self.show_status_message(f"{service.capitalize()} detenido", "red")

    # Método para reiniciar LAMP
    def restart_lamp(self):
        self.stop_lamp()
        self.start_lamp()

    # Método para reiniciar Apache
    def restart_apache(self):
        self.stop_apache()
        self.start_apache()

    # Método para reiniciar la base de datos (MySQL/MariaDB)
    def restart_db(self):
        self.stop_db()
        self.start_db()
        
    # Método para abrir phpMyAdmin en el navegador web
    def open_phpmyadmin(self):
        webbrowser.open('http://localhost/phpmyadmin')

    # Método para abrir la terminal MySQL/MariaDB
    def open_mysql_terminal(self):
        if self.is_service_installed("mariadb"):
            subprocess.run(["gnome-terminal", "--", "bash", "-c", "mysql -u root -p"])
        elif self.is_service_installed("mysql"):
            subprocess.run(["gnome-terminal", "--", "bash", "-c", "mysql -u root -p"])
        else:
            messagebox.showerror("Error", "No se encontró MySQL o MariaDB instalado.")

    # Método para introducir la contraseña (para iniciar LAMP)
    def ask_password(self):
        password = simpledialog.askstring("Contraseña", "Introduce tu contraseña:", show="*")
        return password

    # Método para mostrar mensajes de estado con opción de cambiar el color del texto
    def show_status_message(self, message, color="blue"):
        self.lamp_status_label.config(text=message, fg=color)
        messagebox.showinfo("Mensaje", message)  # Utilizar messagebox para mostrar un mensaje informativo en un popup
    
    # Método para actualizar el estado de los servicios al iniciar la aplicación
    def update_status(self):
        lamp_status = self.get_lamp_status()
        self.show_status_message("Estado de LAMP: " + lamp_status)

    # Método para obtener el estado de LAMP
    def get_lamp_status(self):
        lamp_status = "Desactivado"
        apache_status = self.get_service_status("apache2")
        db_status = self.get_service_status("mariadb") or self.get_service_status("mysql")
        
        if apache_status and db_status:
            lamp_status = "Activado (Apache y MySQL/MariaDB)"
        elif apache_status:
            lamp_status = "Activado (Apache)"
        elif db_status:
            lamp_status = "Activado (MySQL/MariaDB)"

        return lamp_status

    # Método para obtener el estado de un servicio dado su nombre
    def get_service_status(self, service):
        try:
            subprocess.run(["systemctl", "is-active", "--quiet", service], check=True)
            return True
        except subprocess.CalledProcessError:
            return False


    # Método para comprobar si el servicio (de BD) está instalado
    def is_service_installed(self, service):
        try:
            subprocess.run(["which", service], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, check=True)
            return True
        except subprocess.CalledProcessError:
            return False

    # Método para ejecutar los comandos
    def execute_command(self, command, password=None):
        try:
            if password:
                command = f"echo '{password}' | sudo -S {command}"
            subprocess.run(command, shell=True, check=True)
            print("Comando ejecutado correctamente")
        except subprocess.CalledProcessError as e:
            print(f"Error al ejecutar el comando: {e}")

    # Método para obtener la versión de PHP instalada
    def get_php_version(self):
        try:
            php_version = subprocess.check_output(["php", "-v"]).decode("utf-8").strip()
            return php_version
        except subprocess.CalledProcessError:
            return "No se pudo obtener la versión de PHP"

def main():
    root = tk.Tk()
    app = LAMPControlApp(root)
    root.mainloop()

if __name__ == "__main__":
    main()

Aun que el código está todo comentado, diré que se comienza importando los módulos necesarios: tkinter para la interfaz gráfica, subprocess para ejecutar comandos del sistema y webbrowser para abrir páginas web desde la aplicación.

Después creamos una clase LAMPControlApp que representa nuestra aplicación. En el método __init__, configuramos la ventana principal de la aplicación y creamos los diferentes elementos de la interfaz de usuario, como botones para controlar los servicios y etiquetas para mostrar el estado de los mismos.

Funcionamiento general de la Aplicación

La aplicación se centra en métodos para iniciar, detener y reiniciar los servicios de Apache y MySQL/MariaDB. Da igual si utilizas MariaDB o MySQL, debería saber distinguirlos e iniciar, reiniciar o parar correctamente ambos. Cada uno de estos métodos utiliza el módulo subprocess para ejecutar comandos del sistema operativo que controlan los servicios.

Por ejemplo, el método start_lamp inicia tanto Apache como MySQL/MariaDB al solicitar al usuario que escriba su contraseña. Si la contraseña es válida, los servicios se inician y se actualiza el estado de la aplicación.

Además de controlar los servicios, la aplicación también proporciona la capacidad de abrir phpMyAdmin en un navegador web y la terminal MySQL/MariaDB en una ventana de terminal.

Descargar desde GitHub

En este artículo, hemos creado una aplicación de escritorio simple utilizando Python y Tkinter para controlar los servicios de la pila LAMP. Esta aplicación creo que pone de manifiesto cómo Python puede ser utilizado para automatizar tareas de administración del servidor y proporcionar una interfaz fácil de usar para los usuarios.

La aplicación se puede ampliar aún más añadiendole funcionalidades adicionales, como la capacidad de configurar la pila LAMP, monitorizar el rendimiento de los servicios y todo lo que al usuario se le ocurra y necesite. Pero eso ya es cosa de cada uno.

El código que acabamos de ver, también se puede descargar desde el repositorio de GitHub en el que lo he alojado. Allí también he dejado el lanzador de escritorio que nos servirá para poder iniciar la aplicación desde el menú de actividades de Ubuntu.

También te puede interesar ...

Deja un comentario

* Al utilizar este formulario, aceptas que este sitio web almacene y maneje tus datos.

Adblock Detectado!!

Ayúdanos deshabilitando la extensión AdBlocker de tu navegador para visitar esta web.
Si no sabes hacerlo en Chrome, consulta el siguiente enlace. Si utilizas Firefox, puedes consultar este otro enlace.
Esto mejorará tu experiencia en este sitio web.