DEV Community

Cover image for Análisis y Organización de Historial de Comandos en Arch Linux con Python
Javier Sabando
Javier Sabando

Posted on

Análisis y Organización de Historial de Comandos en Arch Linux con Python

Como entusiasta y usuario de Arch Linux, siempre estoy buscando maneras de optimizar mi flujo de trabajo y entender mejor cómo interactúo con mi sistema. Uno de los aspectos fascinantes de trabajar con Linux es la gran cantidad de información que puedo obtener a través de la terminal, especialmente el historial de comandos.

Recientemente, he desarrollado un script en Python que me permite analizar y organizar mi historial de comandos de la consola zsh, enfocándome especialmente en los comandos relacionados con la instalación y desinstalación de paquetes. Aquí os explico cómo funciona mi script y cómo lo utilizo para mejorar mi experiencia en Arch Linux y tener un respaldo en caso de que quiera hacer un reset.

El Propósito del Script

El principal objetivo de mi script es filtrar y organizar los comandos de instalación y desinstalación que he utilizado en mi terminal zsh. Al hacer esto, puedo tener una visión clara de qué paquetes he instalado o eliminado, lo cual es crucial para mantener un sistema limpio y eficiente.

Funcionamiento del Script

El script utiliza Python, un lenguaje poderoso y versátil, para leer mi archivo de historial .zsh_history. Mediante el uso de listas y diccionarios en Python, clasifico los comandos basándome en si son de instalación o desinstalación.

Aquí hay una breve explicación técnica de cómo funciona:

  1. Lectura del Archivo de Historial: El script comienza leyendo el archivo ~/.zsh_history, que contiene todos mis comandos ejecutados en zsh.

  2. Filtrado de Comandos: A continuación, el script filtra los comandos basándose en un conjunto predefinido de acciones de instaladores (pacman, yay, flatpak).

  3. Organización de los Comandos: Los comandos se organizan en un diccionario, separando los comandos de instalación de los de desinstalación.

Ejemplo de Uso y Salida

Después de ejecutar el script, obtengo una salida estructurada que me muestra qué paquetes he instalado y cuáles he desinstalado. Por ejemplo, si ejecuto un comando para instalar firefox y luego otro para desinstalarlo, mi script lo detectará y organizará adecuadamente.

Aquí es donde podría incluir una captura de pantalla del terminal mostrando la salida del script:

Output

Explicación del Código

El corazón del script es una función denominada save_map, que analiza cada línea del historial y decide si es un comando relevante. Si encuentra un comando de instalación o desinstalación, lo procesa y lo almacena en el diccionario installation_commands_map.

Imports y configuraciones iniciales

import os
import json

# Define la ruta al archivo de historial de zsh
history_path = os.path.expanduser('~/.zsh_history')

# Define los comandos de instalación y desinstalación para diferentes gestores de paquetes
INSTALLER_COMMANDS = [
    {"command":'pacman', "install_command":'-S', "uninstall_command":'-Rns'},
    {"command":'yay', "install_command":'-S', "uninstall_command":'-Rns'}, 
    {"command":'flatpak', "install_command":'install',"uninstall_command":'uninstall'}
    ]
Enter fullscreen mode Exit fullscreen mode

Tratado de datos

try:
    # Inicializa un diccionario para mapear comandos de instalación y desinstalación
    installation_commands_map = {'uninstall':[]}
    for installer in INSTALLER_COMMANDS:
        name_com = installer['command']
        installation_commands_map[name_com] = []

    # Define una función para procesar y guardar los comandos relevantes del historial
    def save_map(command):
        for installer in INSTALLER_COMMANDS:
            name_com = installer['command']
            install_com = installer['install_command']
            uninstall_com = installer['uninstall_command']

            # Agrega comandos de instalación al mapa
            if name_com in split_command and install_com in split_command:
                filtered_command = [part for part in split_command if part != 'sudo']
                installation_commands_map[name_com].append(' '.join(filtered_command))

            # Agrega comandos de desinstalación al mapa y elimina el paquete de la lista de instalados
            if name_com in split_command and uninstall_com in split_command:
                filtered_command = [part for part in split_command if part != 'sudo']
                installation_commands_map['uninstall'].append(' '.join(filtered_command))
                package_to_uninstall = split_command[-1]
                installation_commands_map[name_com] = [
                    com for com in installation_commands_map[name_com]
                    if package_to_uninstall not in com
                ]
    # Abre y lee el archivo de historial línea por línea
    with open(history_path, 'r', encoding='utf-8', errors='ignore') as file:
        history = file.readlines()

        for command in history:
            striped = command.strip()
            if(striped != '' ):
                split_command_time = striped.split(';')[1]
                split_command = split_command_time.split(' ')
                if( len(split_command)>=3):
                    save_map(split_command)
    # Escribe el mapa de comandos procesados a un archivo JSON
    with open('history_commands_map.json', 'w', encoding='utf-8') as json_file:
        json.dump(installation_commands_map, json_file, ensure_ascii=False, indent=4)
Enter fullscreen mode Exit fullscreen mode

Manejo de excepciones

except FileNotFoundError:
    print(f"File not found in: {history_path}")
except Exception as e:
    print(f"Error: {e}")
Enter fullscreen mode Exit fullscreen mode

Conclusiones y Mejoras

Este script es un ejemplo perfecto de cómo, un poco de conocimiento de zsh y Python puede combinarse para crear herramientas personalizadas que mejoren tu experiencia como usuario de cualquier sistema, en mi caso, de Arch.

Top comments (0)