Un traceback compare quando parte un comando di gestione VPN, e il primo istinto corre a installare un Python diverso o a puntare il default di sistema altrove. Quell'istinto mescola due runtime che non hanno nulla a che vedere l'uno con l'altro. Uno appartiene al sistema operativo e ai suoi strumenti pacchettizzati; l'altro appartiene a qualunque progetto tu stia costruendo. Cambiare il primo per soddisfare il secondo è il modo in cui un desktop funzionante perde il suo gestore di pacchetti.

Il confronto che vale la pena fare è tra il componente che ha davvero fallito e il runtime che hai il diritto di cambiare. Non sono quasi mai lo stesso oggetto.

Due domande su Python che sembrano una

La prima domanda è: quale interprete ha eseguito il programma che ha stampato il traceback? La seconda è: quale interprete dovrebbe usare il mio progetto? Sembrano identiche in un terminale perché a entrambe si risponde digitando python3, e hanno proprietari diversi, percorsi di aggiornamento diversi e raggi di esplosione diversi.

Uno strumento di sistema è legato all'interprete con cui è stato distribuito, insieme ai moduli compilati costruiti contro l'ABI di quell'interprete. Un progetto è legato a qualunque ambiente tu crei per esso. Spostare il default di sistema cambia il primo per ogni strumento della macchina in una volta; creare un ambiente cambia il secondo per una sola directory.

Solo una di queste azioni è reversibile in un minuto. Non è la prima.

Quale componente ha prodotto l'errore

Leggi la prima riga del traceback e l'eseguibile che l'ha prodotto prima di leggere qualsiasi altra cosa. Il frontend da riga di comando, il servizio privilegiato e i binding API sono pezzi separati, e solo alcuni di essi sono Python.

command -v openvpn3
head -n 1 "$(command -v openvpn3)"
dpkg -S "$(command -v openvpn3)" 2>/dev/null
systemctl status openvpn3-service-client --no-pager

La prima riga di uno script nomina l'interprete che userà, ed è l'interprete da cui è venuto il traceback. L'interrogazione dei pacchetti ti dice chi possiede il file, il che decide chi è autorizzato a cambiarlo. Lo stato del servizio risponde a una domanda del tutto diversa: se il backend privilegiato che stabilisce davvero le sessioni è in esecuzione.

Un errore di importazione di un modulo, un rifiuto di attivazione D-Bus e una credenziale rifiutata sono tre stadi diversi. Un errore di importazione avviene prima che esista qualsiasi sessione, quindi nessuna quantità di configurazione VPN lo risolverà, e nemmeno un servizio funzionante lo risolverà. Collocare il messaggio in uno di quei tre stadi è il vero primo passo.

Cosa un ambiente di progetto può e non può riparare

Un ambiente di progetto risolve un problema di progetto: le versioni esatte delle librerie che serve a una applicazione, isolate da tutto il resto. È davvero utile, ed è lo strumento giusto quando il programma che fallisce è uno script tuo.

uv run --python 3.11 app.py
python3 -c 'import openvpn3; print(openvpn3.__file__)'

Il secondo comando mostra quale copia dei binding vede un dato interprete, ed è il modo più rapido per distinguere un pacchetto mancante da uno ombreggiato. Eseguilo con l'interprete che usa lo script che fallisce, non con un altro che per caso funziona.

Ciò che un ambiente di progetto non può fare è riparare un frontend pacchettizzato dalla distribuzione. Le dipendenze di quel programma sono state costruite per l'interprete scelto dal gestore di pacchetti, ed eseguirlo dentro l'ambiente del tuo progetto o fallisce o produce un misto che nessuno supporta. Iniettargli dei percorsi con una variabile d'ambiente è lo stesso errore con passaggi in più: hai cambiato ciò che lo strumento carica senza cambiare ciò contro cui è stato collaudato. Quello scambio sembra una correzione esattamente per il tempo che serve a incontrare la prossima importazione.

Perché ripuntare l'interprete di sistema è una trappola

Cambiare l'interprete predefinito è attraente perché sembra correggere il traceback con un solo comando. Rompe anche il presupposto su cui è stato costruito ogni strumento Python pacchettizzato sull'host, e i guasti arrivano più tardi e in luoghi non correlati.

I meccanismi di selezione delle alternative sono stati progettati per passare tra implementazioni equivalenti, non per installare un linguaggio più nuovo sotto moduli compilati più vecchi. Le estensioni compilate sono costruite per uno specifico ABI, quindi un modulo che ieri si importava oggi può non caricarsi senza che sia stato rimosso un solo pacchetto.

C'è anche una trappola di denominazione nei consigli che la gente trova. Il comando python senza versione non ha un significato universale tra distribuzioni e ambienti, e trattarlo come sinonimo fisso di una particolare versione maggiore produce correzioni che funzionano solo sulla macchina dove sono state scritte. Leggi la politica del sistema che hai davanti invece di quella nel post del blog.

Test di accettazione separati

Due test vanno alla fine, e superarne uno non dice nulla sull'altro. Il primo è che il comando client supportato funzioni con l'interprete per cui è stato pacchettizzato. Il secondo è che il servizio privilegiato stabilisca una sessione e che il tunnel trasporti traffico.

openvpn3 sessions-list
openvpn3-service-client --help 2>/dev/null | head -n 3
ip -4 addr show tun0

Mantieni un modo indipendente per entrare nella macchina mentre lavori, soprattutto se la VPN porta il tuo unico accesso amministrativo. Una modifica a un interprete di sistema è esattamente il tipo di intervento che può togliere quell'accesso a metà.

Se il guasto è un modulo mancante per uno strumento di sistema, la correzione è un'operazione sui pacchetti tramite il flusso di lavoro supportato. Se il guasto è un conflitto di versioni nel tuo progetto, la correzione è un ambiente. Scegliere tra i due è l'intera decisione, ed è decisa da quale programma ha stampato il traceback.

Articoli correlati