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.

Image of Docusign

🛠️ Bring your solution into Docusign. Reach over 1.6M customers.

Docusign is now extensible. Overcome challenges with disconnected products and inaccessible data by bringing your solutions into Docusign and publishing to 1.6M customers in the App Center.

Learn more

Top comments (0)

Image of Docusign

🛠️ Bring your solution into Docusign. Reach over 1.6M customers.

Docusign is now extensible. Overcome challenges with disconnected products and inaccessible data by bringing your solutions into Docusign and publishing to 1.6M customers in the App Center.

Learn more