Risorsa Samba non più raggiungibile

Mi prendo un appunto su questo problema e la soluzione che ho trovato con GPT.

Problema

Improvvisamente (in realtà ieri ho fatto un aggiornamento di Windows) dalla mia macchina Windows non riesco più ad accedere alla risorsa ssamba montata sul mio “muletto” Ubuntu Linux jsbach. Quando tento di montare la risorsa Samba mi compare la maschera di autenticazione ma anche fornendo le credenziali corrette mi viene rifiutato l’accesso.

Soluzione

Sono necessarie modifiche da entrambe le parti (Linux/Windows)

Ubuntu

Questa è la sezione SambaShare (/etc/samba/smb.conf):

[SambaShare]
   comment = Directory Condivisa Samba
   path = /home/marcob/sambashare
   browseable = yes
   writable = yes
   guest ok = no
   read only = no
   force user = marcob
   user = marcob
   ;valid user = Marco
   public = yes

Considerando che il file smb.conf funzionava correttamente fino a poco tempo fa e il problema si è verificato solo ora, è importante distinguere tra eventuali aggiornamenti di Samba o cambiamenti nelle policy di rete Windows. Procediamo con un’analisi più approfondita


1. Direttiva non valida: user

La direttiva user in Samba non è più valida. Potrebbe essere ignorata fino a un certo punto, ma con aggiornamenti recenti di Samba (o altre librerie correlate), l’opzione non riconosciuta ora potrebbe causare errori. Per sicurezza, rimuovo e aggiorno la configurazione della condivisione come segue:

[SambaShare]
   comment = Directory Condivisa Samba
   path = /home/marcob/sambashare
   browseable = yes
   writable = yes
   guest ok = no
   read only = no
   force user = marcob
   valid users = marcob
   public = no

Modifiche principali:

  1. Rimossa user (non valida).
  2. Corretto valid users, abilitando l’utente corretto.
  3. Impostato public = no, coerente con guest ok = no (public è legato agli accessi guest).

2. Aggiorna Samba dopo la modifica

Dopo aver aggiornato il file, verifico e applico le modifiche:

  1. Verifica il file di configurazione: testparm Controlla eventuali errori o avvisi.
  2. Riavvia Samba: sudo systemctl restart smbd nmbd

3. Controlla l’utente Samba

Verifica che l’utente marcob esista nel database di Samba e che abbia una password correttamente configurata. Aggiungi o aggiorna l’utente con:

sudo smbpasswd -a marcob

Se hai già configurato l’utente, conferma semplicemente la password. Tutto OK.


Windows

Controlla le policy di sicurezza di Windows

Il messaggio di errore “i criteri di sicurezza dell’organizzazione bloccano l’accesso guest non autenticato” è spesso legato a modifiche nelle impostazioni di Windows per SMB. Recentemente, Microsoft ha rinforzato le regole per SMB1, disabilitando l’accesso guest per motivi di sicurezza.

Ecco come risolvere:

  1. Abilita l’accesso autenticato (NTLMv2):
  • Premi Win+R, digita secpol.msc e premi Invio.
  • Vai su Criteri locali -> Opzioni di sicurezza.
  • Cerca Criteri di rete: livello di autenticazione LAN Manager e impostalo su: Invia risposta NTLMv2 se negoziato
  • Riavvia il PC Windows dopo la modifica.

Testa nuovamente la connessione

Dopo aver completato i passi sopra:

  • Verifica se Windows richiede di nuovo l’autenticazione.
  • Controlla i log di Samba in /var/log/samba/ per tracciare i tentativi.

A questo punto tutto riprende a funzionare

Porting di una app Oracle a MySQL

Durante un porting ho incontrato queste differenze che ho dovuto gestire.

Function

Non può contenere istruzioni DDL (es. CREATE TABLE).

Non può nemmeno chiamare una procedura che contene istruzioni DDL.

Se si vogliono lanciare istruzioni DDL, utilizzare le procedure, non le function.

Procedure

Può contenere DDL però mi da’ un fastidioso errore alla dichiarazione di una variabile locale:

DECLARE p_count BIGINT DEFAULT 0;

Viene sollevato un errore che sembra legato alla sintassi:

Errore SQL [1064] [42000]: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '' at line 3

ma la sintassi è corretta.

Il problema qui è il client DBeaver: risulta che il driver deve avere una configurazione particolare:

Verifica configurazione della connessione DBeaver

Vai nelle impostazioni della connessione DBeaver:

Modifica la connessione:

Vai su Database > Connessioni > Modifica connessione.

Driver Properties:

Verifica che il driver MySQL utilizzi allowMultiQueries=true:

Se è false, cambia a true (è questo il mio caso)

Aggiungi questa proprietà se non esiste.

Fatta la modifica mi sconnetto e mi riconnetto allo schema e la definizione della procedura con DDL funziona (funziona anche la procedura).

Trigger

I trigger non possono contenere variabili locali, non è ammessa una sezione DECLARE. E’ ammessa solo in procedure e function.

Nei trigger però possono venire usate variabili di sessione, dichiarate con il prefisso @ davanti al nome:

SET @p_username = 'myuser';

Eventualmente spostare il codice che usa variabili locali non di sessione in una procedura e invocare la procedura dal triger.

Ancora Procedure

Nelle procedure però non è consentito l’uso di variabili di sessione, ma solo di variabili locali.

Se ad esempio dichiariamo:

DELIMITER //

CREATE PROCEDURE my_set(p_username VARCHAR(255))
BEGIN
    set @login = p_username;
    -- Restituisce il valore tramite SELECT
    SELECT @login AS result;
END//

DELIMITER ;

incontro un errore che sembra legato alla sintassi:

Errore SQL [1064] [42000]: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '' at line 4

Nelle procedure utilizzare solo variabili locali.

In realtà ho trattato in altro modo una variabile di sessione gestendola all’interno di una tabella temporanea, che viene creata dalla procedura alla sua invocazione.

La tabella TEMPORARY così creata non viene listata né da comando

show tables;

né dall’information schema:

SELECT *
FROM information_schema.tables
WHERE table_schema = 'mydb';

per ragioni di consistenza (user diversi vedono cose diverse, e anche lo stesso utente in sessioni diverse).

Però posso interrogarla:

slect count(1)
from app_session;

-- return 1

Mirth: compilazione del Message template

Mi è capitata una anomalia che non avevo mai notato. In realtà non è un’anomalia ma è così che va Mirth: avevo scritto una query di select in un database reader ma non mi veniva compilato il message template nel transformer.

Il comportamento di Mirth dipende dal contesto tabellare della query:

  • Se il risultato è scalare (SELECT 1 AS n;), Mirth non genera automaticamente il template.
  • Se il risultato ha un contesto tabellare (SELECT 1 AS n FROM tabella;), Mirth genera correttamente il template.

Usa una clausola FROM per sfruttare il popolamento automatico della Message Template. Questo approccio garantisce compatibilità con il funzionamento di Mirth e previene problemi futuri.

Fine della pillola.

Driver Java/MySQL per Mirth Connect: dove posizionare le librerie?

MySQL 8.0
MySQL 8.0
Java
Java
Mirth Connect
Mirth Connect

Ci sono due directory in cui è possibile depositare archivi JAR (Java Archive) per estendere le funzionalità di Mirth Connect, nel mio caso la libreria che consente di connettersi a MySQL:

custom-lib/ e server-lib/database/.

Le due directory hanno scopi leggermente differenti e vengono utilizzate per gestire librerie personalizzate o di sistema in maniera modulare:

1. custom-lib/:

  • Scopo: Questa directory è destinata a contenere librerie personalizzate che potresti voler aggiungere a Mirth Connect. Ad esempio, se stai utilizzando un driver JDBC o altre librerie esterne specifiche per il tuo progetto o personalizzazioni, puoi inserirle qui.
  • Utilizzo: È particolarmente utile quando hai bisogno di integrare librerie che non sono incluse di default in Mirth Connect, come connettori o altre dipendenze che il sistema non gestisce autonomamente.

2. server-lib/database/:

  • Scopo: Questa directory è destinata alle librerie di database utilizzate da Mirth Connect per la connessione a varie tipologie di database, come MySQL, PostgreSQL, Oracle, ecc. Mirth Connect cerca automaticamente qui i driver di database necessari per i connettori Database Reader o Database Writer.
  • Utilizzo: È il percorso preferito per i driver JDBC. Se stai lavorando principalmente con database e hai bisogno di specificare i driver JDBC, questa è la directory in cui vanno posizionati.

Differenze chiave:

  • custom-lib/: Per librerie personalizzate o aggiuntive non incluse di default.
  • server-lib/database/: Per driver di database JDBC, generalmente gestiti dal sistema.

Quando usarle:

  • Se hai bisogno di aggiungere librerie specifiche per il tuo progetto o personalizzazioni (non solo JDBC), usa custom-lib/.
  • Per i driver JDBC destinati ai connettori Database Reader/Writer, il posto più appropriato è server-lib/database/.

Perché la libreria deve stare in una sola delle due directory:

Mantenere una singola versione della libreria in una sola directory evita conflitti di classpath e sovraccarico nella gestione delle classi. Se una libreria è presente in entrambe le directory, Mirth potrebbe non sapere quale utilizzare, provocando errori come il NoClassDefFoundError che ho riscontrato. Un problema silente al deploy del canale che però si verificava a runtime.

Tra i tentativi che ho fatto ci sono stati quelli di trovare una liberia compatibile con la VM ma non era qui il problema.

Scrivendo un breve programma Java, la connessione si stabiliva e si riusciva a anche a tirare le query: il problema non era la libreria in sé, né la VM

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.ResultSet;

public class MySQLConnectionTest {

    public static void main(String[] args) {
        String jdbcUrl = "jdbc:mysql://localhost:3306/mydb?useSSL=false&serverTimezone=Europe/Rome";
        String username = "myuser";
        String password = "mypassword"; 

        Connection connection = null;
        Statement statement = null;
        ResultSet resultSet = null;

        try {
            // Carica il driver MySQL
            Class.forName("com.mysql.cj.jdbc.Driver");
            System.out.println("Driver MySQL caricato correttamente.");

            // Effettua la connessione
            connection = DriverManager.getConnection(jdbcUrl, username, password);
            System.out.println("Connessione al database riuscita.");

            // Crea uno statement e esegui la query "SELECT 1"
            statement = connection.createStatement();
            resultSet = statement.executeQuery("SELECT 1");

            // Mostra i risultati
            while (resultSet.next()) {
                int result = resultSet.getInt(1);
                System.out.println("Risultato della query SELECT 1: " + result);
            }

        } catch (ClassNotFoundException e) {
            System.out.println("Errore: il driver MySQL non è stato trovato.");
            e.printStackTrace();
        } catch (SQLException e) {
            System.out.println("Errore: impossibile connettersi al database.");
            e.printStackTrace();
        } finally {
            // Chiudi il ResultSet, Statement e Connection
            try {
                if (resultSet != null) resultSet.close();
                if (statement != null) statement.close();
                if (connection != null) connection.close();
                System.out.println("Connessione chiusa.");
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
}

L’output è pulito:

$ java -cp .:/opt/mirthconnect4.2/custom-lib/mysql-connector-java-8.2.0.jar MySQLConnectionTest
Driver MySQL caricato correttamente.
Connessione al database riuscita.
Risultato della query SELECT 1: 1
Connessione chiusa.

Conclusione:

Le due directory sono utilizzate per scopi diversi e possono coesistere, ma è importante non duplicare le librerie tra di esse. Per i driver di database JDBC, come nel mio caso, server-lib/database/ è il posto più adatto!

Riferimenti

Mirth: cosa sono le Code Libraries

Il tutto parte da un avviso che mi compariva ogniqualvolta importavo un canale Mirth costruito in precedenza: un avviso che, con il codice, veniva importata anche una libreria, una fantomatica Library1.


Cosa sono le Code Libraries in Mirth Connect?

Le Code Libraries in Mirth Connect sono collezioni di funzioni, template e blocchi di codice che possono essere riutilizzati in più canali. Introdotte in versioni più recenti (come Mirth 3.3.0), le code libraries permettono agli utenti di centralizzare il codice utilizzato in vari canali, facilitando la manutenzione e la gestione del codice riutilizzabile.

A cosa servono le Code Libraries?

  1. Riutilizzo del codice:
    Le code libraries consentono agli sviluppatori di definire funzioni e blocchi di codice una sola volta e riutilizzarli su più canali e trasformatori. Invece di scrivere lo stesso codice ripetutamente in diversi canali, puoi semplicemente creare un template di codice in una libreria e richiamarlo dove necessario.
  2. Manutenzione centralizzata:
    Quando hai codice distribuito in più canali, apportare modifiche può essere complesso e dispendioso in termini di tempo. Con le code libraries, puoi aggiornare una funzione o un template centralizzato, e la modifica verrà automaticamente applicata a tutti i canali che utilizzano quella libreria.
  3. Organizzazione modulare del codice:
    Le code libraries permettono di organizzare il codice in moduli o componenti, migliorando la leggibilità e la gestione. Puoi creare librerie separate per gestire funzioni diverse, come operazioni su stringhe, trasformazioni di dati, o gestione degli errori, e associarle solo ai canali che ne hanno bisogno.
  4. Facilità di condivisione:
    Le code libraries possono essere facilmente esportate e importate, facilitando la condivisione di template e codice riutilizzabile tra diversi ambienti o team. Questo migliora l’interoperabilità e riduce la duplicazione del lavoro tra sviluppatori.
  5. Controllo sull’inclusione di librerie nei canali:
    In Mirth Connect, puoi decidere a quali canali associare specifiche code libraries. Questo ti permette di avere un controllo preciso su quali canali hanno accesso a determinate funzioni o template, evitando che tutto il codice sia incluso in ogni canale senza necessità.

Il problema della libreria vuota (Library1):

In alcuni casi, come dopo la migrazione a versioni più recenti di Mirth (ad esempio 3.3.0), potrebbe venire creata una libreria di default chiamata Library1. Questa libreria viene creata per includere eventuali code templates pre-esistenti, ma a volte potrebbe risultare vuota. Questo succede per una delle seguenti ragioni:

  • Non ci sono code templates esistenti nelle versioni precedenti.
  • I code templates non sono stati trasferiti correttamente durante la migrazione.
  • La libreria è semplicemente un placeholder creato dal sistema per gestire eventuali future aggiunte di code templates.

Dove compare l’avviso

Quando si importa un canale sviluppato altrove può accadere di vedere un avviso simile, che viene mostrato perché il canale da importare si porta dietro delle librerie oltre al codice scritto nella Source, nelle Destination e nei Transformers/Filters:

Importazione della Library 1 tra i Code Templates
Importazione della Library 1 tra i Code Templates

Nella fattispecie vedevo spesso comparire questa misteriosa Library 1 ma non sapevo cosa contenesse, al che ho pensato che fosse il caso di approfondire.

Le librerie custom di solito si possono includere in un file JAR dentro alla directory /opt/mirthconnect/cutom-library che però nel mio caso (nel Mirth di partenza) non aveva alcuna Library 1 al suo interno, anzi era addirittura vuota.

Un altro modo è gestirle da Mirtch Connect Administratore secondo il percorso:

Channels > Code Templates

Vediamo i passi da compiere per eliminare definitivamente l’avviso.

Come gestire la libreria vuota:

  • Se la libreria è vuota o non serve: Puoi ignorarla o rimuoverla, poiché non avrà alcun impatto sui canali attuali.
  • Se intendi usarla: Puoi aggiungere nuovi code templates alla libreria e associarli ai canali che necessitano di quel codice.
  • Importare nuovi template: Invece di usare Library1, potresti voler creare nuove librerie per separare meglio i tuoi code templates in base alle funzionalità (ad esempio, una libreria per operazioni su stringhe, una per trasformazioni JSON, ecc.).

Nel mio caso l’ho proprio eliminata utilizzando la GUI Mirth Connect Administrator e dai canali che la richiedevano.

Conclusione:

Le Code Libraries in Mirth Connect sono uno strumento potente per migliorare la gestione del codice, facilitando il riutilizzo e la manutenzione centralizzata. Tuttavia, in alcuni casi, come durante le migrazioni di versione, potrebbero essere create librerie vuote che possono essere rimosse o ignorate se non necessarie.


Il servizio mysqld si riavvia di continuo: un rimedio definitivo.

Un problema di configurazione mi ha tenuto bloccato per un giorno e mezzo, non voglio che perdiate tutto questo tempo.

MySQL 8.0
MySQL 8.0


Non riuscivo più ad avviare MySQL.
O meglio, il demone sembrava sempre attivo:

$ ps aux | grep my
mysql      60230  1.3  4.8 2173948 392788 ?      Ssl  11:21   0:07 /usr/sbin/mysqld

Però lo stato del servizio era questo:

# systemctl status mysql.service
● mysql.service - MySQL Community Server
     Loaded: loaded (/lib/systemd/system/mysql.service; enabled; vendor preset: enabled)
     Active: activating (start) since Tue 2024-10-15 10:09:47 CEST; 5s ago
    Process: 23150 ExecStartPre=/usr/share/mysql/mysql-systemd-start pre (code=exited, status=0/SUCCESS)
   Main PID: 23158 (mysqld)
      Tasks: 30 (limit: 9308)
     Memory: 363.2M
        CPU: 1.880s
     CGroup: /system.slice/mysql.service
             └─23158 /usr/sbin/mysqld

ott 15 10:09:47 jsbach systemd[1]: Starting MySQL Community Server...

Il log di errore inoltre stampava a ripetizione questo gruppo di righe:

2024-10-15T08:46:38.654804Z 0 [System] [MY-010116] [Server] /usr/sbin/mysqld (mysqld 8.0.39-0ubuntu0.22.04.1) starting as process 41656
2024-10-15T08:46:38.667469Z 1 [System] [MY-013576] [InnoDB] InnoDB initialization has started.
2024-10-15T08:46:40.683551Z 1 [System] [MY-013577] [InnoDB] InnoDB initialization has ended.
2024-10-15T08:46:41.490599Z 0 [Warning] [MY-010068] [Server] CA certificate ca.pem is self signed.
2024-10-15T08:46:41.490751Z 0 [System] [MY-013602] [Server] Channel mysql_main configured to support TLS. Encrypted connections are now supported for this channel.
2024-10-15T08:46:41.521372Z 0 [ERROR] [MY-010273] [Server] Could not create unix socket lock file /var/run/mysqld/mysqld.sock.lock.
2024-10-15T08:46:41.521469Z 0 [ERROR] [MY-010268] [Server] Unable to setup unix socket lock file.
2024-10-15T08:46:41.521519Z 0 [ERROR] [MY-010119] [Server] Aborting
2024-10-15T08:46:43.132674Z 0 [System] [MY-010910] [Server] /usr/sbin/mysqld: Shutdown complete (mysqld 8.0.39-0ubuntu0.22.04.1)  (Ubuntu).
2024-10-15T08:46:43.753568Z 0 [Warning] [MY-011807] [Server] Failed to connect to systemd notification socket named /run/systemd/notify. Error: 'Permission denied'

segno che il server si riavviava in continuazione.

Ora ho provato a cercare con varie chat (ChatGPT/Copilot) e tutte giustamente mi davano come suggerimenti quelli di verificare le directory

  • /var/run/mysqld
  • /run/systemd/notify

in particolare verificare che la prima fosse 755 per mysql:mysql e la seconda fosse 755 per root:root.

Cosa che era verificata.

Dopo aver vagato senza meta per molto tempo, ho capito

Il nucleo del problema

In pratica il nucleo del problema era il seguente: mysql non poteva scrivere il file di socket dentro alla directory /var/run/mysqld anche se ne era il proprietario.

Per farla breve, nei sistemi Linux esiste la possibilità di installare un modulo di sicurezza ulteriore oltre alla politica di Linux. In Ubuntu ho installato AppArmor (SELinux ha getenforce per esempio).

AppArmor

AppArmor (Application Armor) è un modulo di sicurezza del kernel Linux che consente di controllare e limitare le capacità delle applicazioni in esecuzione. Funziona applicando un modello di sicurezza di tipo MAC (Mandatory Access Control), che impone restrizioni aggiuntive rispetto al normale modello di permessi basato sugli utenti e sui gruppi.

AppArmor permette di definire profili di sicurezza per le applicazioni, specificando cosa possono e non possono fare, come:

  • Accesso a file specifici o directory
  • Utilizzo di risorse di rete
  • Esecuzione di altre applicazioni
  • Accesso a dispositivi hardware

I profili di AppArmor possono essere impostati in modalità enforcing (applicazione delle regole) o complain (solamente logging delle violazioni), rendendolo uno strumento flessibile per rafforzare la sicurezza del sistema. AppArmor è utilizzato su molte distribuzioni Linux, come Ubuntu, per fornire una protezione aggiuntiva a livello del sistema.

Alcuni vantaggi di AppArmor:

  • È relativamente semplice da configurare rispetto ad altre soluzioni come SELinux.
  • Permette un controllo granulare sulle risorse e le azioni che un’applicazione può compiere.

Esempi d’uso tipici sono limitare le azioni di processi che richiedono privilegi elevati (ad esempio, i server web) o isolare container in ambienti come Docker o LXC.

Dunque il problema era lui. L’unica cosa che non ho capito è come la directory /var/run/mysqld sia finita tra le sue grinfie da un giorno all’altro, e questo merita un ulteriore approfondimento.

Per accorgermi di questo ho dovuto lanciare il comando

# aa-status
apparmor module is loaded.
188 profiles are loaded.
178 profiles are in enforce mode.
...
/usr/sbin/mysqld    <----------- eccolo!
...

Soluzione del problema

Per fare questa operazione di togliere la directory incriminata dalle grinfie di AppArmor ho dovuto innanzitutto installare le apparmor-utils (solo aa-status funzionava):

# apt install apparmor-utils

Ho rilevato che esistevano due profili AppArmor in conflitto per MySQL.

Ecco come ho risolto il problema:
• Ho identificato e rimosso due profili duplicati. Ho rimosso il file /etc/apparmor.d/usr.sbin.mysqld.MOD e ho spostato in altra directory, per potermelo studiare a posteriori, il file /etc/apparmor.d/usr.sbin.mysqld.ORIG:

# rm /etc/apparmor.d/usr.sbin.mysqld.MOD
# mv /etc/apparmor.d/usr.sbin.mysqld.ORIG /somewhere/else/


• Dopo aver rimosso il profilo duplicato, ho disabilitato il profilo AppArmor per MySQL:

# aa-disable /usr/sbin/mysqld
Disattivazione di /usr/sbin/mysqld.

• Ho ricaricato AppArmor per applicare le modifiche:

# systemctl reload apparmor

• Ho finalmente e definitivamente riavviato il servizio MySQL per vedere se il problema era stato risolto:

# systemctl restart mysql

Dopodiché ho verificato lo stato del servizio

# systemctl status mysql
● mysql.service - MySQL Community Server
     Loaded: loaded (/lib/systemd/system/mysql.service; enabled; vendor preset: enabled)
     Active: activating (start) since Tue 2024-10-15 11:21:58 CEST; 4min 59s ago
    Process: 60222 ExecStartPre=/usr/share/mysql/mysql-systemd-start pre (code=exited, status=0/SUCCESS)
   Main PID: 60230 (mysqld)
      Tasks: 35 (limit: 9308)
     Memory: 365.2M
        CPU: 4.955s
     CGroup: /system.slice/mysql.service
             └─60230 /usr/sbin/mysqld

ott 15 11:21:58 jsbach systemd[1]: Starting MySQL Community Server...

Questo non mi ha soddisfatto del tutto perché non vedo lo stato Started ma Starting.

In ogni caso non ci sono più log di errore:

2024-10-15T09:21:58.805799Z 0 [System] [MY-010116] [Server] /usr/sbin/mysqld (mysqld 8.0.39-0ubuntu0.22.04.1) starting as process 60230
2024-10-15T09:21:58.822502Z 1 [System] [MY-013576] [InnoDB] InnoDB initialization has started.
2024-10-15T09:21:59.680416Z 1 [System] [MY-013577] [InnoDB] InnoDB initialization has ended.
2024-10-15T09:22:00.258399Z 0 [Warning] [MY-010068] [Server] CA certificate ca.pem is self signed.
2024-10-15T09:22:00.258527Z 0 [System] [MY-013602] [Server] Channel mysql_main configured to support TLS. Encrypted connections are now supported for this channel.
2024-10-15T09:22:00.326099Z 0 [System] [MY-010931] [Server] /usr/sbin/mysqld: ready for connections. Version: '8.0.39-0ubuntu0.22.04.1'  socket: '/var/run/mysqld/mysqld.sock'  port: 3306  (Ubuntu).
2024-10-15T09:22:00.389974Z 8 [Warning] [MY-013360] [Server] Plugin mysql_native_password reported: ''mysql_native_password' is deprecated and will be removed in a future release. Please use caching_sha2_password instead'

La notizia più bella è

/usr/sbin/mysqld: ready for connections. Version: ‘8.0.39-0ubuntu0.22.04.1’ socket: ‘/var/run/mysqld/mysqld.sock’ port: 3306 (Ubuntu).

Provo a collegarmi dal client in localhost:

$ mysql -u root -p
Enter password: 
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 570
Server version: 8.0.39-0ubuntu0.22.04.1 (Ubuntu)

Copyright (c) 2000, 2024, Oracle and/or its affiliates.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> 

Bingo!

Rimane da spiegare i comportamento dello status, ma per il momento sono rimasto troppo indietro con il resto dei lavori, me ne occupo un’altra volta.

Riferimenti

Guida: Risolvere i problemi di Filebeat nell’analisi dei log Mirth per Kibana

Ho pensato di analizzare i log di Mirth e rappresentarli con una applicazione Kibana per poter avere una visione d’insieme del funzionamento dei canali.
In questo articolo, esploreremo la soluzione a un problema riscontrato durante l’elaborazione dei log di Mirth usando Filebeat per la’anlidi dei log e l’invio a Elasticsearch, evidenziando le cause dei fallimenti e le azioni risolutive adottate.


Lo stack Elastic: Filebeat – Elasticsearch – Kibana


Kibana, Filebeat ed Elasticsearch sono componenti chiave all’interno dello stack Elastic, e ognuno di essi svolge un ruolo cruciale nel ciclo di gestione e visualizzazione dei log.

  1. Filebeat: È il primo elemento della catena e si occupa della raccolta dei log da varie fonti (file di log, syslog, ecc.). Filebeat legge i log e li invia a Elasticsearch per l’indicizzazione, seguendo specifiche configurazioni e pipeline di elaborazione (tokenizer, dissect, ecc.). Nel nostro caso, Filebeat è stato configurato per raccogliere i log di Mirth, applicare un tokenizer, e inviare i dati elaborati a Elasticsearch.
  2. Elasticsearch: Una volta che Filebeat invia i log, Elasticsearch li indicizza, rendendoli ricercabili e pronti per essere visualizzati. Elasticsearch archivia i dati e fornisce capacità di ricerca e analisi avanzate. Ogni documento inviato da Filebeat viene elaborato attraverso pipeline di indicizzazione per aggiungere campi e strutturare i dati in modo ottimale per le query successive.
  3. Kibana: È l’interfaccia visiva per esplorare i dati indicizzati in Elasticsearch. Con Kibana, è possibile creare dashboard, eseguire ricerche avanzate, analizzare i log in tempo reale e visualizzare metriche. Nel nostro caso, abbiamo utilizzato Kibana per verificare se i campi tokenizzati da Filebeat (come logtime e loglevel) venivano indicizzati correttamente e per monitorare i risultati della pipeline di Filebeat.

La relazione tra questi componenti è stretta: Filebeat raccoglie ed elabora i dati, Elasticsearch li indicizza e li rende disponibili per la ricerca, e Kibana fornisce gli strumenti per visualizzarli e analizzarli. Quando uno dei componenti non funziona correttamente, come nel nostro caso con Filebeat, l’intero flusso di dati ne risente, e il troubleshooting può diventare complesso. Tuttavia, una volta che il flusso è ripristinato, l’integrazione tra questi strumenti offre una piattaforma potente e scalabile per la gestione e l’analisi dei log.


Risolvere l’Errore “Failed to Access State” in Filebeat

Recentemente, abbiamo affrontato un problema critico con Filebeat che non riusciva a partire, ripetendo continuamente un errore legato all’accesso al file di stato meta.json.

# journalctl -u filebeat -b
ott 03 17:08:00 poleni systemd[1]: filebeat.service: Failed with result 'exit-code'.
ott 03 17:08:01 poleni systemd[1]: filebeat.service: Scheduled restart job, restart counter is at 1.
ott 03 17:08:01 poleni systemd[1]: Stopped Filebeat sends log files to Logstash or directly to Elasticsearch..
ott 03 17:08:01 poleni systemd[1]: Started Filebeat sends log files to Logstash or directly to Elasticsearch..
ott 03 17:08:01 poleni filebeat[33176]: Exiting: Failed to access state when attempting take over: failed to open store 'filebeat': open /var/lib/filebeat/registry/filebeat/meta.json: no such file or directory
.....
ott 03 17:08:01 poleni systemd[1]: filebeat.service: Failed with result 'exit-code'.
ott 03 17:08:02 poleni systemd[1]: filebeat.service: Scheduled restart job, restart counter is at 5.
ott 03 17:08:02 poleni systemd[1]: Stopped Filebeat sends log files to Logstash or directly to Elasticsearch..
ott 03 17:08:02 poleni systemd[1]: filebeat.service: Start request repeated too quickly.
ott 03 17:08:02 poleni systemd[1]: filebeat.service: Failed with result 'exit-code'.
ott 03 17:08:02 poleni systemd[1]: Failed to start Filebeat sends log files to Logstash or directly to Elasticsearch..

Anche arrestando il servizio, lo stato continuava a rimanere “failed” invece di passare a “dead“, complicando la risoluzione del problema:

root@poleni:/etc/filebeat# systemctl stop filebeat
root@poleni:/etc/filebeat# systemctl status filebeat
× filebeat.service - Filebeat sends log files to Logstash or directly to Elasticsearch.
     Loaded: loaded (/lib/systemd/system/filebeat.service; enabled; vendor preset: enabled)
     Active: failed (Result: exit-code) since Thu 2024-10-03 17:02:03 CEST; 5min ago
       Docs: https://www.elastic.co/beats/filebeat
   Main PID: 31207 (code=exited, status=1/FAILURE)
        CPU: 104ms

Sintomi

Ogni volta che si tentava di avviare Filebeat, nel log appariva il seguente messaggio:

Exiting: Failed to access state when attempting take over: failed to open store 'filebeat': open /var/lib/filebeat/registry/filebeat/meta.json: no such file or directory

Questo errore si ripeteva rapidamente fino a raggiungere il limite di tentativi, facendo fallire il servizio dopo cinque ripartenze consecutive.

Diagnosi e Risoluzione

  1. File di Stato Corrotto: Il problema principale risiedeva nel file di stato /var/lib/filebeat/registry/filebeat/meta.json, che risultava corrotto o mancante. Anche arrestando il servizio, lo stato non passava a “dead” come ci si aspettava.
  2. Eliminare il File di Stato: La svolta è arrivata quando abbiamo eliminato completamente la directory del registro di stato con il comando:
   sudo rm -rf /var/lib/filebeat/registry/filebeat

Questo ha forzato Filebeat a ricreare il file di stato da zero, rimuovendo ogni traccia di configurazioni o stati corrotti.

  1. Riavvio del Servizio: Una volta eliminata la directory di stato, abbiamo riavviato correttamente il servizio:
   sudo systemctl start filebeat
  1. Verifica del Funzionamento: Dopo il riavvio, Filebeat ha creato correttamente un nuovo file meta.json, e il servizio ha iniziato a funzionare normalmente senza più ripetere l’errore.

Lezioni Apprese

  • Stati Persistenti: Filebeat utilizza lo stato per tenere traccia dei file e delle loro posizioni, ma se lo stato diventa corrotto, può impedire il corretto avvio del servizio.
  • Controllare lo Stato del Servizio: Anche quando si arresta il servizio, è fondamentale verificare che lo stato sia passato correttamente a “dead” e non rimanga bloccato in “failed”. In questo caso, l’errore ripetuto era dovuto al tentativo automatico di Filebeat di riavviarsi.
  • Ripulire Manualmente lo Stato: Quando Filebeat non si avvia e continua a fallire ripetutamente, eliminare lo stato può essere una soluzione rapida e efficace.

Un’immagine Docker compatta, veloce ed efficace.

immagine docker - Dockerfile
docker – Dockerfile

Ho fatto una sintesi delle strategie per ottimizzare una immagine Docker. Di seguito trovate le considerazioni per rendere più efficiente la costruzione delle immagini.


Come ridurre la dimensione delle immagini Docker e migliorare i tempi di build

Ottimizzare una immagine Docker è essenziale per ridurre i tempi di build, migliorare l’efficienza e risparmiare spazio su disco. Le immagini più piccole sono più rapide da scaricare e distribuire, facilitando il deployment nei vari ambienti. In questo articolo ti spiegherò alcune strategie efficaci per ottenere immagini Docker più leggere e migliorare le performance di build.

1. Eliminare la documentazione dei software

Nei container Docker, la documentazione (come manuali o pagine man) raramente è necessaria. Se hai bisogno di consultare la documentazione, puoi farlo direttamente online, quindi non ha senso mantenerla all’interno delle immagini. Rimuovere la documentazione può liberare un discreto quantitativo di spazio.

Come farlo:

Puoi configurare apt per evitare di installare la documentazione. Ad esempio:

RUN apt-get install -y --no-install-recommends gnupg2 ca-certificates
RUN echo 'path-exclude=/usr/share/doc/*' > /etc/dpkg/dpkg.cfg.d/01_nodoc && \
    echo 'path-exclude=/usr/share/man/*' >> /etc/dpkg/dpkg.cfg.d/01_nodoc && \
    echo 'path-exclude=/usr/share/info/*' >> /etc/dpkg/dpkg.cfg.d/01_nodoc

Con questa configurazione, non verranno installati manuali, pagine man o altra documentazione inutile.

2. Evitare ripetizioni inutili di apt update

Quando esegui apt update, Docker scarica l’elenco aggiornato dei pacchetti dai repository. Tuttavia, eseguire più volte questo comando senza un motivo valido non solo rallenta la build, ma aumenta inutilmente la dimensione dell’immagine.

Inoltre può essere utile raggruppare il più possibile in una sola istruzione multiriga molte istruzioni Docker perché ad ogni riga viene aggiunto un layer.

Quando eseguire apt update:

  • Necessario: Prima di eseguire un’installazione (apt install) o subito dopo aver aggiunto un repository con add-apt-repository. Ogni volta che aggiungi nuovi repository, è importante aggiornare l’elenco dei pacchetti per includere le nuove fonti.
  • Non necessario: Se hai già eseguito apt update e devi solo installare nuovi pacchetti in momenti diversi. Non è necessario ripetere l’aggiornamento finché i repository non cambiano.

3. Cosa sono i layer in Docker?

Le immagini Docker sono costituite da una serie di layer impilati uno sopra l’altro. Ogni istruzione in un Dockerfile (come RUN, COPY, ADD) crea un nuovo layer. Questi layer sono immutabili e vengono memorizzati nella cache. I layer inferiori rappresentano l’immagine base, mentre quelli superiori contengono le modifiche. Ridurre il numero di layer e ottimizzarli aiuta a migliorare i tempi di build e a ridurre la dimensione dell’immagine.

Ad esempio raggruppare queste tre istruzioni

RUN apt update 
RUN apt install -y
RUN build-essential
RUN procps
RUN systemd

in una sola riga

RUN apt update && apt install -y \
    build-essential \
    procps \
    systemd \

consnte di aggiungere un solo layer anziché 4 migliorando la performance di build.

4. Pulire i file temporanei e la cache di apt

Una volta che hai installato tutto il necessario, puoi ridurre ulteriormente la dimensione della tua immagine Docker rimuovendo i file temporanei e la cache di apt. Questo passaggio aiuta a ridurre la dimensione del layer finale del container.

Comando da eseguire:

RUN apt clean && rm -rf /var/lib/apt/lists/*

Questo comando rimuove la cache di apt, che non è più necessaria una volta che i pacchetti sono stati installati. La cache può occupare una quantità significativa di spazio e non ha utilità all’interno del container.

5. Multi-stage build: attenzione agli aggiornamenti tra gli stage

Se stai usando una multi-stage build, dove hai più istruzioni FROM nel tuo Dockerfile, è importante ricordare che ogni FROM avvia un nuovo stage completamente separato. Se esegui comandi di installazione di pacchetti in più stage, dovrai eseguire apt update in ciascuno di essi.

Esempio:

FROM ubuntu:22.04 AS base
RUN apt update && apt install -y curl

FROM ubuntu:22.04 AS final
RUN apt update && apt install -y nginx

Ogni volta che utilizzi FROM, inizia un nuovo contesto, quindi dovrai aggiornare i pacchetti separatamente.

6. Evitare di copiare file non necessari

Un’altra pratica comune che può ridurre la dimensione dell’immagine è l’uso del file .dockerignore per evitare di copiare file inutili nel container. File come .git, documentazione o altri file non essenziali possono essere esclusi.

Esempio di .dockerignore:

.git
*.md

In questo modo, Docker ignorerà questi file durante il build.

Conclusione

Seguendo queste best practice, puoi migliorare significativamente la velocità di build e ridurre la dimensione delle immagini Docker. Ecco un riepilogo delle strategie:

  • Eliminare la documentazione dei software: Imposta apt per non scaricare documenti e pagine man.
  • Non ripetere apt update inutilmente: Fai apt update solo quando necessario.
  • Pulizia della cache: Usa apt clean e rimuovi i file temporanei per minimizzare lo spazio occupato.
  • Multi-stage build: Ricorda che ogni FROM richiede un aggiornamento separato.
  • Usa .dockerignore: Escludi file non necessari durante il build.

Con queste tecniche, puoi ottenere immagini Docker più piccole, più efficienti e più veloci da costruire.


Riferimenti

Personalizzare l’elenco dei bookmark del gestore di file Nautilus per Ubuntu

Ho trovato un metodo per personalizzare l’elenco dei bookmark in Nautilus, consentendo di organizzare i segnalibri per qualsivolgia criterio.

L’elenco dei segnalibri che mi presentava Nautilus era divenuto pian piano molto confuso e trovare i link relativi a risorse SFTP o Samba di rete locale mia o di qualche cliente era diventato un problema.

Divide et impera

Per prima cosa ho fatto un po’ di ordine. L’elenco dei bookmark di Nautilus si trova sotto

~/.config/gtk-3.0/bookmarks

Avevo anche il problema di sincronizzare questo elenco in tutti i miei pc, per cui sistemato un file, lo propago a tutti i computer.

Raccogliere e mescolare tutti i segnalibri

Nel tempo ho collezionato segnalibri diversi nei vari pc, occorre fare un merge. Mi porto tutti i file bookmarks di tutte le macchine in un pc ed effettuo il merge:

$ cat bookmarks.1 bookmarks.2 | sort -u > bookmarks_merged

Dopodiché sovrascrivo questo file nei vari pc:

$ scp bookmarks_merged marco@pcN:~/.config/gtk-3.0/bookmarks

Il risultato è buono. In particoalre ho fatto un sort e ho estratto 1 sola ripetizione per segnalibro (con l’opzione -u, “unique”). Ora però devo raggruppare in modo diverso i segnalibri

Organizzare i segnalibri per server

Per prima cosa raggruppo i segnalibri per server (perdendo l’ordine alfabetico che è del tutto inessenziale, utile solo per il merge dei file)

Cercando in rete non ho trovato un modo per separare i vari gruppi con una linea orizzontale, però ho trovato che posso aggiungere delle icone includendo dei caratteri UTF-8 con un semplice copia/incolla.

Posso aggiungere delle scritte oltre alle icone utilizzando la sintassi

1# Server 1 folder
Nautilus sostituirà ogni occorrenza di “#1″ con la scritta ” Server 1 folder“.
Questio comportamento è stato un po’ criptico da individuare perché commentando ogni linea con

# Server 1
...
# Server 2

quello che vedevo in nautilus era sempre

# Server 1
...
# Server 1

Quindi i separatori vanno marcati con un carattere seguito da #, la cosa più pratica è un numero seguito da # e ne possiamo fare quanti vogliamo:

1# Server 1
...
2# Server 2

L’aspetto finale è il seguente (non so se sia possibile migliorarlo ulteriormente, ma mi basta così):

Ubuntu: Personalizzare i bookmark su Nautilus
Ubuntu: Personalizzare i bookmark su Nautilus

Ovviamente se clicco sui segnaposto, Nautilus dà un errore, ma mi sono capito io…

TLP, allunga la vita della batteria del tuo laptop

TLP è un sistema per Linux che aiuta a prolungare la durata della tua batteria. Utilizzando TLP, potrai ottimizzare le impostazioni del sistema per ridurre il consumo energetico e massimizzare l’efficienza energetica. Con TLP, potrai godere di una maggiore durata della batteria per il tuo sistema Linux.

tlp - Batteria Laptop

TLP, tool per Batteria Laptop

Installazione di TLP

Su Ubuntu 22.04 Jammy Jellyfish:

$ sudo apt install tlp

Dopodiché basta avviarlo manualmente, dal prossimo boot (a meno di indicazioni contrarie) partirà da solo.

Va preventivamente avviato il servizio:

$ sudo systemctl enable tlp.service
Synchronizing state of tlp.service with SysV service script with /lib/systemd/systemd-sysv-install.
Executing: /lib/systemd/systemd-sysv-install enable tlp
insserv: script ypbind: service ypbind already provided!
...
Created symlink /etc/systemd/system/multi-user.target.wants/tlp.service → /lib/systemd/system/tlp.service.

Quindi lo avviamo:

$ sudo tlp start
TLP started in AC mode (auto).

Possiamo vedere le statistiche

$ tlp-stat -s
--- TLP 1.5.0 --------------------------------------------

+++ System Info
System         = Acer V1.20 TravelMate P216-51
BIOS           = V1.20
OS Release     = Ubuntu 22.04.4 LTS
Kernel         = 6.8.0-40-generic #40~22.04.3-Ubuntu SMP PREEMPT_DYNAMIC Tue Jul 30 17:30:19 UTC 2 x86_64
/proc/cmdline  = BOOT_IMAGE=/boot/vmlinuz-6.8.0-40-generic root=UUID=1e25e923-e1cf-4a4c-a3de-1793b4a682a4 ro quiet splash vt.handoff=7
Init system    = systemd v249 (249.11-0ubuntu3.12)
Boot mode      = UEFI

+++ TLP Status
State          = enabled
RDW state      = enabled
Last run       = 09:40:40,     10 sec(s) ago
Mode           = AC
Power source   = AC

TLP ci consente (ad esempio) di agire manualmente sui livelli di carica e scarica, ci consente cioè di impostare la carica minima al di sotto della quale parte la ricarica e la carica massima al di sopra della quale la ricarica viene interrotta. Ad esempio:

$ sudo tlp setcharge 70 90 BAT0

applica le soglie 70% – 90% alla batteria BAT0.

BAT0 seleziona la batteria principale/interna, BAT1 la batteria ausiliaria/Ultrabay da scaricare

Letteralmente, dal sito di TLP:

What does TLP stand for?

TLP is not an acronym, it’s just a three-letter name.

🙂

Riferimenti