Η ίδια εντολή συνδέεται από κέλυφος και πεθαίνει στο cron, οπότε το φυσικό συμπέρασμα είναι ότι φταίει η σήραγγα ή το πιστοποιητικό. Κοιτάξτε τι έχουν κοινό οι δύο εκτελέσεις πριν το πιστέψετε: το εκτελέσιμο, η διαμόρφωση και τα διαπιστευτήρια είναι ίδια, και άλλαξε μόνο το περιβάλλον της διεργασίας. Όταν το πρόγραμμα δεν βρίσκεται καν, κανένα πλήθος αποσφαλμάτωσης TLS δεν βοηθά. Η διόρθωση βρίσκεται συνήθως σε μια διαδρομή, έναν κατάλογο εργασίας και μια χούφτα μεταβλητές περιβάλλοντος, όχι στο VPN.

Το command -v openvpn στο κέλυφος που δουλεύει τυπώνει την απάντηση, και πολύ συχνά είναι το /usr/sbin/openvpn, ένας κατάλογος που το cron δεν βάζει στη διαδρομή αναζήτησής του.

Η σήραγγα δεν ξεκίνησε ποτέ, άρα η σήραγγα δεν είναι το πρόβλημα

Οι εργασίες που ξεκινά το cron κληρονομούν ελάχιστο περιβάλλον, κατά σύμβαση PATH=/usr/bin:/bin, και κανένα τερματικό ελέγχου. Ό,τι έχει εγκατασταθεί στο /usr/sbin ή στο /usr/local/sbin απλώς απουσιάζει από αυτή τη λίστα, και η γραμμή του αρχείου καταγραφής λέει openvpn: not found αντί για σφάλμα TLS. Το subprocess της Python αποτυγχάνει διαφορετικά: κληρονομεί το περιβάλλον της διεργασίας του διερμηνέα, που μπορεί να είναι πλουσιότερο από του cron αλλά δεν έχει ακόμη κέλυφος για να αναπτύξει μια περισπωμένη. Και οι δύο αποτυχίες συμβαίνουν πριν φύγει ένα και μόνο πακέτο από τον κεντρικό υπολογιστή.

Ένας γρήγορος τρόπος να τις ξεχωρίσετε είναι να διαβάσετε το πρώτο σφάλμα αντί για το τελευταίο. Ένα εκτελέσιμο που λείπει παράγει εξαίρεση κελύφους ή Python, μια κακή διαμόρφωση παράγει μήνυμα χρήσης του OpenVPN, και μια πραγματική αποτυχία χειραψίας παράγει χρονικές σφραγίδες και διευθύνσεις ομοτίμων. Μόνο η τρίτη είναι πρόβλημα σήραγγας.

Οι απόλυτες διαδρομές και οι λίστες ορισμάτων νικούν τις συμβολοσειρές κελύφους

Περάστε τη λυμένη διαδρομή ρητά και παρακάμψτε το κέλυφος εντελώς. Το subprocess.run(["/usr/sbin/openvpn", "--config", config, "--verb", "4"], capture_output=True, text=True, timeout=90) σας δίνει κωδικό επιστροφής, stdout και stderr χωρίς να ζητάτε από κέλυφος να ερμηνεύσει όνομα αρχείου. Χτίστε τη διαδρομή της διαμόρφωσης από το os.environ["HOME"] ή το pathlib.Path.home(), ώστε μια περισπωμένη να μη χρειάζεται ποτέ ανάπτυξη. Όταν πραγματικά χρειάζεστε σύνταξη κελύφους, χρησιμοποιήστε το shlex.split, γιατί ο διαχωρισμός συμβολοσειράς με το .split() σπάει σε κάθε διαδρομή που περιέχει κενό. Διαβάστε και το stderr, αφού το OpenVPN γράφει εκεί τις περισσότερες από τις πρώιμες αποτυχίες του.

Ο ίδιος κανόνας ισχύει και για το cron: η γραμμή εργασίας δεν είναι κέλυφος σύνδεσης, άρα τίποτα δεν φορτώνει το προφίλ σας και τίποτα δεν ορίζει τα ψευδώνυμά σας.

Τι κληρονομεί πραγματικά ένα crontab

Μια καταχώριση crontab παίρνει ό,τι περιβάλλον δηλώνει το crontab συν μερικές κληρονομημένες προεπιλογές, οπότε γράψτε τη διαδρομή ολόκληρη ή τυλίξτε την κλήση σε ένα σκριπτ που το κάνει. Μια γραμμή όπως το PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin στην κορυφή του αρχείου καλύπτει τις συνήθεις θέσεις εγκατάστασης, και η ανακατεύθυνση με το >> cron.log 2>&1 είναι αυτό που κάνει την επόμενη αποτυχία αναγνώσιμη. Ένα προφίλ προστατευμένο με φράση πρόσβασης δεν έχει τρόπο να ζητήσει το μυστικό του στο cron, αφού δεν υπάρχει τερματικό για να ρωτήσει. Μια τέτοια σύνδεση ανήκει σε μονάδα systemd που μπορεί να διαβάσει αρχείο διαπιστευτηρίων, όχι σε εργασία που προσποιείται ότι είναι διαδραστική.

Οι σχετικές διαδρομές είναι η δεύτερη παγίδα. Μια δοκιμαστική εκτέλεση γίνεται συχνά από τον φάκελο που κρατά το προφίλ, και μια εργασία cron ξεκινά κάπου τελείως αλλού, οπότε το --config office.ovpn λύνεται σε αρχείο που δεν υπάρχει και το μήνυμα διαβάζεται ως αρχείο που λείπει παρά ως σήραγγα που λείπει.

Αποδείξτε το γδύνοντας το περιβάλλον

Αναπαράγετε το ελάχιστο περιβάλλον απευθείας: env -i PATH=/usr/bin:/bin /usr/sbin/openvpn --config office.ovpn --verb 4. Ένα παράπονο για διαδρομή ή τερματικό από αυτή την εκτέλεση σημαίνει ότι το πρόβλημα κάθεται πάνω από το VPN. Αν συνδέεται, οι υπόλοιποι ύποπτοι είναι ο λογαριασμός με τον οποίο τρέχει, ο κατάλογος στον οποίο ξεκινά και το διαπιστευτήριο που παρουσιάζει. Οποιοδήποτε από τα δύο αποτελέσματα είναι καλύτερο από άλλον έναν γύρο ελέγχου πιστοποιητικών.

Έπειτα κάντε το περιτύλιγμα να αναφέρει τον εαυτό του. Βγείτε με ξεχωριστή κατάσταση για κάθε στάδιο που έφτασε, καταγράψτε και τις δύο ροές με χρονική σφραγίδα, και η επόμενη αποτυχία θα σας πει αν πέθανε στην επίλυση διαδρομής, στην ταυτοποίηση ή αφού η σήραγγα ήταν ήδη σηκωμένη.

Μια μονάδα χρειάζεται επίσης σωστή σειρά: το Wants=network-online.target μαζί με το After=network-online.target κρατούν τον πελάτη από το να ξεκινήσει πριν υπάρξει διεύθυνση ή προεπιλεγμένη διαδρομή, κάτι που αλλιώς εμφανίζεται ως σφάλματα πιστοποιητικού ή TLS που εξαφανίζονται σε χειροκίνητη επανεκκίνηση.

Σχετικά άρθρα