Error: mysql_secure_installation command not found

Cuando se instala el gestor de bases de datos MariaDB, una de las primeras cosas que se suele hacer es ejecutar el script mysql_secure_insallation, que permite aumentar la seguridad de la instalación de varias formas, como podemos leer en la página correspondiente de la documentación de MySQL.

Como dicho script tiene su origen en MySQL, como es evidente por su nombre, los desarrolladores de MariaDB decidieron a partir de la versión 10.5 que mejor creaban su propio script, que es mariadb-secure-installation. Aunque en su página de documentación dicen que aún puede ejecutarse dicho script usando el nombre original, porque hay un enlace simbólico que relaciona ambos scripts, lo cierto es que si, por ejemplo, instalas Debian 12 de la rama testing, dicho enlace no existe, por lo que es posible que nos surja cierto desconcierto al no encontrar un script tan conocido y usado. Que al renombrar dicho script no solo se haya cambiado el nombre mysql por el de mariadb, sino que también se hayan sustituido los guiones bajos por guiones normales, no ayuda mucho a la hora de encontrar este nuevo script.

Así que habrá que acostumbrarse al nuevo nombre y ejecutar mariadb-secure-installation cada vez que instalemos una nueva inistancia de MariaDB.

Esqueleto de aplicación web con Codigniter 4 y Shield

Caso todos los framework de PHP, al menos los más populares, tienen una forma más o menos automatizada de comenzar una aplicación web desde cero formando un esqueleto de código utilizable para, a partir de él, comenzar a programar el resto de la aplicación.

En el caso del framework Codeigniter, suponiendo que ya tenemos montado un entorno LAMP donde trabajar, en el cual tengamos además instalado el programa Composer para la gestión de dependencias, el proceso para hacerlo sería el siguiente:

En el directorio raíz de nuestro servidor web, creamos el esqueleto básico de la aplicación usando Composer, con el siguiente comando:

composer create-project codeigniter4/appstarter shield

Esto nos genera una carpeta de nombre shield en la que se ha instalado el código base de Codeigniter 4.

A continuación modificamos el nombre del archivo env, que se encuentra en el primer nivel de directorios de dicha carpeta, llamándole .env

Abrimos ese archivo y modificamos la línea donde se especifica la url base de la aplicación, poniendo la que corresponda a la nuestra. Es muy recomendable crear un host virtual en nuestro servidor web, que en este caso podría llamarse shield.local. La línea quedaría entonces:

app.baseURL = 'http://shield.local'

A continuación tenemos que incluir la información necesaria para hacer la conexión a nuestra base de datos, editando el archivo app/Config/Database.php en el que modificaremos la definición de la variable $default para que quede:

 public array $default = [
        'DSN'          => '',
        'hostname'     => 'localhost',
        'username'     => '<mi_usuario>',
        'password'     => '<mi_password>',
        'database'     => '<mi_database>',
        'DBDriver'     => 'MySQLi',
        'DBPrefix'     => '',
        'pConnect'     => false,
        'DBDebug'      => true,
        'charset'      => 'utf8mb4',
        'DBCollat'     => 'utf8mb4_general_ci',
        'swapPre'      => '',
        'encrypt'      => false,
        'compress'     => false,
        'strictOn'     => false,
        'failover'     => [],
        'port'         => 3306,
        'numberNative' => false,
        'dateFormat'   => [
            'date'     => 'Y-m-d',
            'datetime' => 'Y-m-d H:i:s',
            'time'     => 'H:i:s',
        ],

Con esto ya tendríamos una aplicación funcionando, a la cual se puede acceder entrando en la dirección que corresponda a nuestra aplicación, por ejemplo http://localhost/shield o http://shield.local si hemos definido un host virtual.

Un complemento muy interesante de Codeigniter es Shield. Con él, podemos dotar a nuestra aplicación de funcionalidades de autenticación y autorización de forma muy sencilla. Podemos instalarla mediante Composer ejecutando dentro del directorio raíz de nuestra aplicación losl comandos:

composer require codeigniter4/shield
php spark shield:setup 

Una vez que se ejecutan estos comandos sin error, podemos visitar la página de login que se nos ha creado en http://appStarter.local/login

Si, por ejemplo, queremos que los que usen la aplicación estén obligados a identificarse antes de usarla, no tenemos más que entrar en el fichero app/Config/Filters.php y en la definición de la variable $globals poner qué páginas se pueden visitar sin estar autenticado, que serían solamente aquellas relacionadas con el proceso de identificarse o darse de alta. El archivo quedaría como vemos a continuación, donde la línea a incluir aparece macada en negrita:

    public array $globals = [
        'before' => [
            // 'honeypot',
            // 'csrf',
            // 'invalidchars',
            'session' => ['except' => ['login*', 'register', 'auth/a/*', 'logout']],
        ],
        'after' => [
            'toolbar',
            // 'honeypot',
            // 'secureheaders',
        ],
    ];

De esta forma, si navegamos de nuevo a la dirección inicial de nuestra aplicación. http://shield.local, veremos que nos dirige automáticamente a la página de login.

En la web de Codeigniter podemos consultar más información sobre el uso de Codeigniter y Shield.

Cómo desinstalar Recall en Windows 11

Recall («Recuerda») es el nuevo explorador de contenidos de Microsoft que se instalará automáticamente en todos los equipos con Windows 11, previsiblemente a finales de año o al menos a partir de la actualización 24H2. La aplicación Recall es un paso más en la utilización de la IA en nuestros equipos personales, recopilando prácticamente todo lo que hacemos, tanto en texto como en imagen, para posteriormente poder utilizarlo para hacer búsquedas más eficaces y utilizando un lenguaje natural, en lo que han venido a llamar «AI Explorer«.

Recall solo puede instalarse en los equipos más modernos, que tengan al menos 16 GB de RAM y un procesador compatible, algo que por ahora tienen muy pocos equipos. Es evidente que un uso tan intensivo de búsqueda en nuestra labor diaria tiene que tener un coste energético y presentar un problema evidente de privacidad, ante lo que Microsoft afirma que Recall solo trabaja en el entorno local y que la información que se recopila no se utiliza fuera de los equipos.

Hay que reconocer que muchas personas pueden ver esta herramienta útil y aceptar los inconvenientes que presenta, pero en el caso de que no te convenza o no le veas utilidad, la posibilidad de desinstalarla en modo gráfico no parece que vaya a estar disponible. Sin embargo, puede desinstalarse usando la terminal en modo administrador de la siguiente manera:

Dism /Online /Get-Featureinfo /Featurename:Recall

El comando anterior nos devuelve si tenemos o no instalado Recall en nuestro ordenador. Si no lo tuviéramos nos mostrará la siguiente información:

Si la tenemos instalada y queremos desinstalarla el comando para hacerlo es:

Dism /Online /Disable-Feature /Featurename:Recall

Como podemos ver en la salida del primer comando, para ver todas las características o «features» que tenemos instaladas, tecleamos:

Dism /Online /Get-Features

La salida es extensa y en ella aparecen todas las «características» instaladas, tanto las habilitadas como las deshabilitadas.

Gracias a @hareldan@mapstodon.space por publicar el truco

Cambiar la resolución en Ubuntu Server

Después de instalar Ubuntu Server 24.04 LTS en mi servidor de pruebas, la resolución del terminal por defecto (no hay entorno gráfico, solo modo terminal) mostraba caracteres demasiado grandes y resultaba incómodo. Para cambiar la resolución por defecto podemos hacerlo modificando el fichero /etc/default/grub descomentando el comando que establece la resolución del terminal. El proceso sería el siguiente:

  1. Abrimos el fichero /etc/default/grub como root con un editor de texto.
  2. Localizamos la línea que pone «GRUB_GFXMODE…»
  3. La descomentamos quitando el carácter «#» al inicio y ponemos la resolución que queremos, por ejemplo en mi caso la línea queda «GRUB_GFXMODE=1024×768»
  4. Guardamos el fichero
  5. Ejecutamos el comando «sudo update-grub»
  6. Reiniciamos el ordenador

Actualizar las conexiones de datos de una serie de hojas Excel con Python

Si tenemos una serie de hojas Excel en las que se han incorporado conexiones a bases de datos, y queremos que se actualice el contenido de las mismas para que aparezca reflejada la última información cuando se aceda a ellas, podemos hacerlo de varias maneras: podemos, por ejemplo, definir esas conexiones de forma que se actualicen cuando se abra la hoja de cálculo, pero si la actualización es lenta porque se accede a muchas tablas o se actualiza mucho contenido, provoca que haya que esperar un buen rato desde que se abre la hoja hasta que se puede empezar a trabajar con ella; podemos también ir entrando en cada una y pulsando en «Actualizar datos», pero esto puede llegar a ser tedioso si son muchas hojas las que hay que actualizar; otra manera sería con macros o VB, pero las primeras son una tecnología a abandonar, y puestos a hacerlo por programa, a mí me gusta más en Python, utilizando la función que muestro a continuación, con comentarios que explican cada uno de los pasos:

# Importamos las librerías necesarias para la ejecución
import os
import win32com.client

# Especificamos el directorio que contiene los archivos Excel
ruta_directorio = "C:\Mis Programas\"

#
# Función para la actualización automática de las conexiones de datos
#
def actualizar_conexiones(directorio):

    # Creamos una instancia de la aplicación Excel
    excel_app = win32com.client.Dispatch("Excel.Application")

    # Hacemos la aplicación invisible para el usuario
    excel_app.Visible = False

    # Recorremos todos los archivos en el directorio especificado
    for filename in os.listdir(directorio):
        # Abrir solo hojas de cálculo, evitando los archivos ocultos
        if (filename.endswith(".xlsx") or filename.endswith(".xlsm")) and not filename.startswith("~"):
            file_path = os.path.join(directorio, filename)
            print(f"Actualizando conexiones de datos en: {file_path}")

            # Creamos un libro excel en memoria con la ruta del archivo
            workbook = excel_app.Workbooks.Open(file_path)

            try:
                # Recorremos todas las conexiones de datos del libro
                for connection in workbook.Connections:
                    print(f"Habilitando contenido: {connection.Name}")
                    connection.Refresh()
                    # Para hacer esperar la ejecución hasta que termine
                    # la actualización de datos:
                    excel_app.CalculateUntilAsyncQueriesDone()
                    # Para evitar que se abran ventanas de diálogo que 
                    # pararían el proceso:
                    excel_app.DisplayAlerts = False

            except Exception as e:
                print(f"Error al actualizar la conexión")

            finally:
                # Guardamos y cerramos el libro
                workbook.Save()
                workbook.Close()

    # Cerramos la aplicación Excel 
    # Ojo, no es lo mismo que cerrar el libro excel creado
    excel_app.Quit()

    print("Actualización de conexiones de datos completada.")


# Llamada a la función para actualizar las conexiones de datos
actualizar_conexiones(ruta_directorio)

Cómo iniciar Linux sin entorno gráfico por defecto con systemd

Si tenemos un ordenador con una distribución Linux que arranca con systemd, podemos muy fácilmente conseguir que el inicio sea en modo gráfico o no, simplemente activando el servicio que corresponda.

Primero buscaremos qué gestor de pantallas se está utilizando, para eso en un terminal lanzamos el comando

cat /etc/X11/default-display-manager

El cual nos mostrará por pantalla si nuestro sistema usa gdm (lo normal en Gnome), kdm (utilizado por KDE) o sddm (usado en KDE Plasma). En mi caso me muestra «/usr/bin/sddm» porque estoy usando Debian 12 con KDE.

Para confirmar que el servicio que tenemos que modificar es el correcto lanzamos en un terminal el comando:

sudo systemctl status | grep sddm

El cual nos mostrará, si tenemos el servicio activado, algo como lo siguiente:

Al estar el servicio «enabled» se arranca automáticamente al iniciar el sistema, que lo hará, por lo tanto, en modo gráfico. Para desactivarlo, solo tenemos que lanzar el comando:

sudo systemctl disable sddm.service

De esta manera cuando arranquemos la próxima vez no se cargará el gestor de pantallas y podremos iniciar sesión directamente en modo consola.

Si en un momento dado queremos volver a estar en modo gráfico, solo tenemos que lanzar el comando:

sudo systemctl start sddm.service

Y nos aparecerá la ventana de inicio de sesión de sddm.

Más información en:

https://www.digitalocean.com/community/tutorials/how-to-use-systemctl-to-manage-systemd-services-and-units-eshttps://wiki.debian.org/es/GDM

Instalar OnlyOffice en Debian 12 Bookworm

Si intentamos instalar la aplicación de escritorio OnlyOffice en Debian 12 siguiendo las instrucciones de su página web para hacerlo mediante el método de añadir el repositorio, cuando lanzamos la instalación con apt, da un error.

dpkg: error al procesar el paquete onlyoffice-desktopeditors (--configure):
el subproceso instalado paquete onlyoffice-desktopeditors script post-installation devolvió el código de salida de error 127

No tengo claro por qué se produce este error, pero al mirar las instrucciones de esa página veo que el repositorio de Debian que indican es para la versión 6 (Squeeze) que es muy antigua. Intentando acceder al mismo repositorio pero con la versión Bookworm (Debian 12) vemos que no existe.

La forma de instalarlo y que funcione es utilizar la AppImage, siguiendo las instrucciones de la página https://helpcenter.onlyoffice.com/installation/desktop-install-appimage.aspx

Yo me he descargado la versión 8.0.1 y me ha funcionado perfectamente en Debian 12 con KDE. El fichero AppImage realmente es un ejecutable similar a los «exe» del entorno Windows, yo lo he guardado en /opt pero podría estar en cualquier lugar del disco.

Añadir el ejecutable al menú de KDE es fácil pulsando con el botón derecho sobre el lanzador de aplicaciones, eligiendo «Editar aplicaciones», botón derecho sobre «Oficina», seleccionar «añadir elemento», rellenar la información del ejecutable y guardar.

Obtener con Python el número que corresponde a la columna de una hoja de cálculo

Cuando trabajamos con hojas de cálculo a veces es necesario conocer qué número de columna se corresponde con la letra de la misma, es decir, qué posición de columna (primera, segunda, etc.) se corresponde con cada columna en letra (A, B, etc.). Tanto en Excel como en LibreOffice tenemos la función COLUMNA(«..») que nos devuelve dicho dato, pero en ocasiones necesitamos conocerlo para acceder por programa a un dato determinado dentro de una hoja de cálculo de grandes dimensiones, que hace difícil calcular mentalmente dicha información.

Para convertir la letra a su número correspondiente podemos hacerlo de la misma manera que mentalmente damos un valor numérico a una cifra de varios dígitos. Me explico: cuando vemos un número, por ejemplo 325, el valor que le damos mentalmente es 3 * 102 + 2 * 101 + 5 * 100 porque diez es la base numérica de nuestro sistema decimal.

Con las letras de la hoja de cálculo podemos hacer lo mismo, teniendo en cuenta que la base de nuestro sistema «numérico» son las letras de la A a la Z, un conjunto de 26 dígitos, es decir, es como si trabajáramos en base 26. De esta forma, el valor «numérico» de una «cifra» como «XDR» sería 24 * 263 + 4 * 261 + 18 * 260 porque X es la letra vigesimocuarta, D es la cuarta letra y R la decimoctava de un total de 26 letras.

Podemos tener ese cálculo guardado en una función con el lenguaje de programación que usemos habitualmente, por ejemplo en Python sería:

def num_from_col(col):
letras = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
rpta = n = 0
columna_aux = col[::-1].upper()
for letra in columna_aux:
valor_letra = letras.index(letra) + 1
rpta += valor_letra * len(letras) ** n
n += 1
return rpta

Para hacer el cálculo hemos dado la vuelta a la expresión a evaluar para que su posición en la cadena se corresponda con el índice al que hay que elevar la base. También hemos pasado a mayúsculas el parámetro recibido para que se corresponda con la lista de letras que usamos de base. Sin embargo, a esta función le falta cosas como el control de excepciones, la validación del dato de entrada, etc. pero la dejo así como ejemplo básico para poder adaptarlo cuando se necesite.

Cómo crear un libro Excel a partir de otro en Python conservando las imágenes y el texto enriquecido

Leer y grabar un libro Excel con Python es muy sencillo utilizando la librería openpyxl, la cual permite hacer multitud de operaciones con archivos Excel y además está muy bien documentada.

Sin embargo, si queremos que al crear un libro a partir de otro que nos sirve de plantilla se mantengan tanto las imágenes como el texto enriquecido, es necesario tener en cuenta lo siguiente:

Para que toda la funcionalidad de openpyxl esté disponible, tenemos que instalar también los paquetes pillow y lxml en el entorno virtual en el que estemos ejecutando el programa. La librería lxml es importante sobre todo para que cuando grabemos el contenido de una celda, si el texto de ésta tiene diferentes formatos (por ejemplo parte es negrita, parte es cursiva o aparecen superíndices) dicho texto se mantenga tal cual está en el original. Sin esta librería se aplicará a toda la celda un único formato de texto.

Otra cosa que hay que tener en cuenta es que al abrir el archivo para leerlo en el código, tenemos que incluir explícitamente la opción rich_text=True, porque por defecto viene a False.

from openpyxl import load_workbook
wb = load_workbook(filename=excel_base, rich_text=True)

La imágenes que existan en el archivo original se van a copiar al archivo destino solamente si en origen están como objeto de Office, si están incrustadas como imagen no se van a copiar. Para comprobarlo, la manera más fácil es abrir el archivo origen, hacer click derecho sobre la imagen y seleccionar «Modificar». Si al hacerlo nos aparece este mensaje:

Tenemos que pulsar en «Sí», de forma que la imagen se guarde como objeto de dibujo de Office. Guardamos el archivo y cuando lo copiemos ya aparecerán las imágenes en la copia.

Teniendo en cuenta estas consideraciones, podremos replicar libros Excel con Python sin perder nada del archivo original.

Montar una partición NTFS de Windows en Linux con permisos de lectura y escritura

Si tenemos un sistema compartido entre Linux y Windows, es probable que queramos poder leer y escribir algunos archivos desde ambos sistemas. Desde Windows no se puede acceder a las particiones de Linux, pero desde Linux sí que es posible leer y escribir archivos en particiones ntfs gracias a los paquetee ntfs-3g y fuse.

Primero tenemos que entrar en el sistema Windows y desactivar el inicio rápido. Esto se puede hacer tanto en Windows 10 como 11. Pulsamos en el icono de inicio de Windows y en la ventana de búsqueda ponemos «panel de control» y pulsamos en el icono que nos muestra. En la ventana que se abre pulsamos en «Hardware y sonido», a continuación en el grupo de enlaces dentro de «Opciones de energía» pulsamos en «Cambiar las acciones de los botones de inicio/apagado». En la ventana que aparece, deberemos desmarcar la casilla que indica «Activar inicio rápido (recomendado)».

A continuación reiniciamos el equipo y entramos en el sistema Linux. Tenemos que instalar los paquetes ntfs-3g y fuse usando el gestor de programas que corresponda a nuestra distribución. Por ejemplo en Fedora 39 sería:

sudo dnf install ntfs-3g fuse

A continuación necesitamos saber el UUID de nuestra unidad ntfs. Podemos encontrarla utilizando el comando:

lsblk -f

La salida de este comando nos muestra varias filas y columnas con la información de nuestras particiones. Nos interesa la columna UUID de la fila cuyo fstype sea ntfs y se corresponda con la partición a la que queremos acceder desde Linux. En la imagen podemos ver que la unidad que nos interesa (en mi equipo) es la sda3 ntfs. Apuntamos el UUID.

A continuación necesitamos el id de nuestro usuario (uid) y grupo (gid) en el sistema Linux, los cuales los obtenemos con el comando «id» el cual nos da una salida

uid=1000(myuser) gid=1000(mygroup) grupos=1000(mygroup),10(wheel)

Ahora necesitamos crear el directorio donde queremos que se monte la partición ntfs. En mi caso lo he hecho en /mnt/win pero podría ser en otro.

sudo mkdir /mnt/win

La última operación a realizar es editar el archivo /etc/fstab (hay que hacerlo como root) y añadir al final una línea con:

UUID=<uuid>   /mnt/win     ntfs-3g    uid=<uid>,gid=<gid>,umask=0022   0   0 

Donde tenemos que reemplazar <uuid> con el valor obtenido con el comando «lsblk -f»; y <uid> , <gid> con los valores obtenidos con el comando «id».

Podemos comprobar que todo está correcto verificando las particiones especificadas en el fstab con el comando

findmnt --verify

Una vez comprobado que no ha habido errores, podemos volver a montar las particiones especificadas en el fstab con el comando

mount -a

Y ya tendremos preparada la partición ntfs para leer y escribir en ella desde Linux. Cuando reiniciemos el equipo esta configuración se mantendrá, y si acaso en algún momento vemos que ya no podemos escribir en la partición, lo más seguro es que en alguna de las actualizaciones de Windows se nos haya vuelto a activar el inicio rápido, por lo que habría que volverlo a desactivar a mano.