OpenVPN-ը աշխատում է shell-ում, բայց cron-ի տակ ձախողվում է. խնդիրը PATH-ն է
Shell-ից միացող հրամանը կարող է ձախողվել cron-ի կամ subprocess-ի տակ մինչև թունելի մեկնարկը։ Ուղղեք ուղին, աշխատանքային թղթապանակը և տերմինալը։
Նույն հրամանը shell-ից միանում է և մահանում cron-ի տակ, ուստի բնական եզրակացությունն այն է, որ թունելը կամ վկայագիրն է մեղավոր։ Նախքան դրան հավատալը, նայեք, թե ինչ ընդհանուր ունեն երկու գործարկումները. բինարը, կարգավորումը և հավատարմագրերը նույնական են, և փոխվել է միայն գործընթացի միջավայրը։ Երբ ծրագիրը նույնիսկ չի գտնվում, TLS-ի որևէ քանակի վրիպազերծում չի օգնում։ Ուղղումը սովորաբար ապրում է ուղու, աշխատանքային թղթապանակի և մի բուռ միջավայրի փոփոխականների մեջ, ոչ VPN-ում։
command -v openvpn աշխատող shell-ում տպում է պատասխանը, և շատ հաճախ դա /usr/sbin/openvpn է, մի թղթապանակ, որը cron-ը չի դնում իր որոնման ուղու մեջ։
Թունելը երբեք չսկսվեց, ուստի թունելը խնդիրը չէ
cron-ի կողմից սկսված աշխատանքները ժառանգում են նվազագույն միջավայր, սովորաբար PATH=/usr/bin:/bin, և չունեն կառավարող տերմինալ։ Ամեն ինչ, որ տեղադրված է /usr/sbin կամ /usr/local/sbin-ում, պարզապես բացակայում է այդ ցանկից, և մատյանի տողը կարդում է openvpn: not found TLS սխալի փոխարեն։ Python-ի subprocess-ը ձախողվում է այլ կերպ. այն ժառանգում է մեկնաբանող գործընթացի միջավայրը, որը կարող է ավելի հարուստ լինել, քան cron-ինը, բայց դեռ չունի shell՝ թիլդա նշանը ընդլայնելու համար։ Երկու ձախողումներն էլ տեղի են ունենում նախքան մեկ փաթեթի հյուրընկալողից հեռանալը։
Դրանք տարբերելու արագ ձևը վերջինի փոխարեն առաջին սխալը կարդալն է։ Բացակայող բինարը առաջացնում է shell-ի կամ Python-ի բացառություն, վատ կարգավորումը առաջացնում է OpenVPN-ի օգտագործման հաղորդագրություն, իսկ իսկական ձեռքսեղմման ձախողումը առաջացնում է ժամանակի դրոշմանիշեր և զուգընկերոջ հասցեներ։ Միայն երրորդն է թունելի խնդիր։
Բացարձակ ուղիները և արգումենտների ցանկերը հաղթում են shell-ի տողերին
Փոխանցեք լուծված ուղին բացահայտ և ամբողջությամբ բաց թողեք shell-ը։ subprocess.run(["/usr/sbin/openvpn", "--config", config, "--verb", "4"], capture_output=True, text=True, timeout=90)-ը տալիս է վերադարձի կոդ, stdout և stderr՝ առանց shell-ից պահանջելու մեկնաբանել ֆայլի անունը։ Կարգավորման ուղին կառուցեք os.environ["HOME"]-ից կամ pathlib.Path.home()-ից, որպեսզի թիլդան երբեք ընդլայնելու կարիք չունենա։ Երբ իսկապես shell-ի շարահյուսություն է պետք, օգտագործեք shlex.split-ը, որովհետև տողը .split()-ով բաժանելը կոտրվում է բացատ պարունակող ցանկացած ուղու վրա։ Կարդացեք նաև stderr-ը, քանի որ OpenVPN-ը իր վաղ ձախողումների մեծ մասը գրում է այնտեղ։
Նույն կանոնը վերաբերում է cron-ին. աշխատանքի տողը մուտքի shell չէ, ուստի ոչինչ չի բեռնում ձեր պրոֆիլը և ոչինչ չի սահմանում ձեր կեղծանունները։
Ինչ է իրականում ժառանգում 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 սխալներ, որոնք անհետանում են ձեռքով վերագործարկելիս։