Tabla de contenido
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
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.