Błąd Pythona w OpenVPN 3: napraw narzędzie, a nie systemowy Python
Traceback wskazuje interpreter, który uruchomił frontend, a nie usługę, która posiada tunel. Porównaj oba, zanim cokolwiek przekierujesz w całym systemie.
Traceback pojawia się, gdy startuje polecenie zarządzania VPN, a pierwszy odruch biegnie ku instalacji innego Pythona albo skierowaniu systemowej wartości domyślnej gdzie indziej. Ten odruch miesza dwa środowiska uruchomieniowe, które nie mają ze sobą nic wspólnego. Jedno należy do systemu operacyjnego i jego zapakowanych narzędzi; drugie należy do dowolnego projektu, który budujesz. Zmiana pierwszego, by zadowolić drugie, to sposób, w jaki działający pulpit traci menedżera pakietów.
Porównanie, które warto zrobić, dotyczy komponentu, który faktycznie zawiódł, i środowiska uruchomieniowego, które wolno ci zmienić. Prawie nigdy nie są tym samym obiektem.
Dwa pytania o Pythona, które wyglądają jak jedno
Pierwsze pytanie brzmi: który interpreter uruchomił program, który wypisał traceback? Drugie: którego interpretera powinien używać mój projekt? W terminalu wyglądają identycznie, bo na oba odpowiada się, wpisując python3, a mają różnych właścicieli, różne ścieżki aktualizacji i różny zasięg skutków.
Narzędzie systemowe jest związane z interpreterem, z którym dostarczyła je dystrybucja, oraz ze skompilowanymi modułami zbudowanymi pod ABI tego interpretera. Projekt jest związany z dowolnym środowiskiem, które dla niego utworzysz. Przeniesienie systemowej wartości domyślnej zmienia to pierwsze dla każdego narzędzia na maszynie naraz; utworzenie środowiska zmienia to drugie dla jednego katalogu.
Tylko jedną z tych czynności da się cofnąć w ciągu minuty. To nie jest ta pierwsza.
Który komponent wywołał błąd
Przeczytaj pierwszą linię tracebacku i plik wykonywalny, który go wywołał, zanim przeczytasz cokolwiek innego. Frontend wiersza poleceń, usługa uprzywilejowana i wiązania API to osobne części, a tylko niektóre z nich są w ogóle Pythonem.
command -v openvpn3
head -n 1 "$(command -v openvpn3)"
dpkg -S "$(command -v openvpn3)" 2>/dev/null
systemctl status openvpn3-service-client --no-pagerPierwsza linia skryptu nazywa interpreter, którego użyje, i to z tego interpretera pochodzi traceback. Zapytanie o pakiet mówi, do kogo należy plik, co decyduje, kto może go zmienić. Status usługi odpowiada na zupełnie inne pytanie: czy działa uprzywilejowany backend, który faktycznie otwiera sesje.
Błąd importu modułu, odmowa aktywacji D-Bus i odrzucone dane uwierzytelniające to trzy różne etapy. Błąd importu zdarza się, zanim istnieje jakakolwiek sesja, więc żadna ilość konfiguracji VPN go nie naprawi, a działająca usługa też go nie naprawi. Zakwalifikowanie komunikatu do jednego z tych trzech etapów jest prawdziwym pierwszym krokiem.
Co środowisko projektu może, a czego nie może naprawić
Środowisko projektu rozwiązuje problem projektu: dokładne wersje bibliotek potrzebne jednej aplikacji, odizolowane od wszystkiego innego. To naprawdę przydatne i jest właściwym narzędziem, gdy zawodzący program to twój własny skrypt.
uv run --python 3.11 app.py
python3 -c 'import openvpn3; print(openvpn3.__file__)'Drugie polecenie pokazuje, którą kopię wiązań widzi dany interpreter, i to najszybszy sposób odróżnienia brakującego pakietu od przesłoniętego. Uruchom je interpreterem, którego używa zawodzący skrypt, a nie innym, który przypadkiem działa.
Środowisko projektu nie potrafi naprawić frontendu zapakowanego przez dystrybucję. Zależności tego programu zbudowano pod interpreter wybrany przez menedżera pakietów, a uruchamianie go w środowisku projektu albo zawodzi, albo daje mieszankę, której nikt nie wspiera. Wstrzykiwanie do niego ścieżek zmienną środowiskową to ten sam błąd z dodatkowymi krokami: zmieniłeś to, co narzędzie ładuje, nie zmieniając tego, na czym je testowano. Ten zamiennik wygląda jak poprawka dokładnie tak długo, jak długo trwa dotarcie do następnego importu.
Dlaczego przekierowanie interpretera systemowego to pułapka
Zmiana domyślnego interpretera kusi, bo wygląda na naprawę tracebacku jednym poleceniem. Łamie też założenie, na którym zbudowano każde zapakowane narzędzie Pythona na hoście, a awarie pojawiają się później i w niepowiązanych miejscach.
Mechanizmy wyboru alternatyw powstały, by przełączać między równoważnymi implementacjami, a nie po to, by pod starszymi skompilowanymi modułami instalować nowszy język. Skompilowane rozszerzenia buduje się pod konkretne ABI, więc moduł, który wczoraj się importował, dziś może się nie załadować, choć nie usunięto ani jednego pakietu.
W radach, które ludzie znajdują, jest też pułapka nazewnicza. Polecenie python bez wersji nie ma jednego uniwersalnego znaczenia w różnych dystrybucjach i środowiskach, a traktowanie go jako stałego synonimu konkretnej wersji głównej daje poprawki działające tylko na maszynie, na której je napisano. Czytaj politykę systemu, który masz przed sobą, a nie tę z wpisu na blogu.
Osobne testy akceptacyjne
Na końcu należą się dwa testy, a zdanie jednego nic nie mówi o drugim. Pierwszy to działanie obsługiwanego polecenia klienta z interpreterem, dla którego je zapakowano. Drugi to ustanowienie sesji przez usługę uprzywilejowaną i przenoszenie ruchu przez tunel.
openvpn3 sessions-list
openvpn3-service-client --help 2>/dev/null | head -n 3
ip -4 addr show tun0Zachowaj niezależną drogę na maszynę, gdy pracujesz, zwłaszcza jeśli VPN przenosi twój jedyny dostęp administracyjny. Zmiana interpretera systemowego to właśnie ten rodzaj edycji, który może odebrać ten dostęp w połowie.
Jeśli awaria to brakujący moduł dla narzędzia systemowego, poprawką jest operacja na pakiecie przez obsługiwany przepływ pracy. Jeśli awaria to konflikt wersji we własnym projekcie, poprawką jest środowisko. Wybór między tymi dwoma to cała decyzja, a rozstrzyga ją to, który program wypisał traceback.