Պատահական OpenVPN ընտրություն systemd-ում՝ ինչու է ExecStart-ը ձախողվում
systemd-ը shell չէ, ուստի ExecStart-ի ներսում խառնված պատճենը մահանում է։ Տեղափոխեք ընտրությունը ExecStartPre, կամ թողեք OpenVPN-ն ինքը սերվեր ընտրի։
Մեկ երկրի համար քառասուն .ovpn ֆայլեր գալիս են մատակարարից, և պլանը թվում է ակնհայտ՝ պատահական մեկը պատճենել իր տեղը, ապա սկսել թունելը։ Երբ այն գրվում է որպես խողովակաշար ExecStart-ի ներսում, այդ պլանը մահանում է բեռնման պահին մի կարգավիճակի կոդով, որը ոչինչ չի բացատրում։ Յունիտի ֆայլը սկրիպտ չէ, և վերանորոգումը կա՛մ բացահայտ shell ներգրավելն է, կա՛մ ֆայլեր ընտրելը լիովին դադարեցնելը։
Ախտանիշը՝ յունիտ, որը մեկնարկում է և անմիջապես մահանում
Կարգավիճակը ցույց է տալիս, որ ծառայությունը ձախողվել է վայրկյանի մի մասում, և ամսագրի տողը նշում է հրաման, որը ոչ մի shell երբեք չէր ստանա։ Թունելի մասին ոչինչ չի հայտնվում, որովհետև թունելը երբեք չսկսվեց։
Ամսագրից ճշգրիտ հրամանի տողը կարդալը դա հաստատելու ամենաարագ ճանապարհն է։ systemd-ը կրկնում է այն, ինչ իրականացրել է, և տողը ցույց կտա խողովակաշարի նշանները որպես բառացի արգումենտներ, ոչ թե օպերատորներ։
Ինչու ExecStart-ը չի կարող խողովակաշար գործարկել
systemd-ն ինքն է բաժանում հրամանի տողը, կիրառում իր չակերտները և փոփոխականների փոխարինումը, ապա արդյունքն ուղղակիորեն կատարում։ Խողովակները, վերահասցեավորումը, shell-ի գլոբ ընդլայնումը և հրամանի փոխարինումը պարզապես այդ քերականության մաս չեն։ Սա նախագծային ընտրություն է, ոչ թե բացթողում՝ յունիտը հռչակագրորեն ասում է՝ ինչ գործարկել, և shell-ի տրամաբանությունը պատկանում է սկրիպտին, որը յունիտը կանչում է։ Երկու վերանորոգումներն էլ բխում են դրանից, և ոչ մեկը յունիտին ավելի շատ արտոնություններ տալ չի պահանջում։
Այն նաև բացատրում է մոլորեցնող ելքի կոդը։ Առաջին արգումենտը դիտարկվում է որպես բինար, ուստի սխալ ձևված տողը ձախողվում է նախքան ձեր տրամաբանության որևէ մասի աշխատելը։
Ընտրությունը կատարեք ExecStartPre-ում
Ուղղակի վերանորոգումը նախապատրաստական քայլ է, որը բացահայտ կանչում է shell և ընտրությունն ու մեկնարկը պահում նույն յունիտում, որպեսզի մեկի ձախողումը չթողնի մյուսին միայնակ աշխատել։
[Service]
Type=notify
ExecStartPre=/bin/bash -c "ls /etc/openvpn/profiles/au* | shuf -n 1 | xargs -r -I{} cp -f {} /etc/openvpn/%i.conf"
ExecStart=/usr/sbin/openvpn --config /etc/openvpn/%i.conf
Երեք մանրամասն որոշում է, թե արդյոք սա կդիմանա իրական մեքենայի հետ հանդիպմանը։ Անվանումը առաջին թակարդն է՝ systemd-ը փոխարինում է %i-ը յունիտը վերլուծելիս, շատ ավելի վաղ, քան bash-ը կաշխատի, ուստի սպեցիֆիկատորը պետք է կանգնի միակ չակերտներից դուրս։ xargs -r-ը թույլ չի տալիս cp-ին աշխատել առանց արգումենտի, երբ գլոբը ոչնչի չի համապատասխանում։ Իսկ ձախողված նախապատրաստական քայլը կանգնեցնում է յունիտը, և դա ճիշտ արդյունքն է՝ երեկվա կոնֆիգուրացիայով սկսելը ավելի վատ է, քան չսկսելը։ Պատահական ընտրությունը, որը միշտ վերցնում է նույն ֆայլը, սովորաբար վատ բախտ չէ։ Ստուգեք՝ արդյոք պատճենված ֆայլը վերագրվում է փաթեթի թարմացմամբ, թե գլոբը համապատասխանում է միայն մեկ հնացած գրառման։
Կամ թողեք OpenVPN-ն ընտրի վերջնակետը
OpenVPN-ն արդեն կարող է մեկ պրոֆիլում պահել մի քանի վերջնակետ և պատահականորեն ընտրել դրանցից, ինչն ամբողջությամբ հանում է shell-ը, պատճենումը և գրելու իրավունքը բեռնման ուղուց։
client
remote-random
<connection>
remote au1.example.net 1194 udp
</connection>
<connection>
remote au2.example.net 1194 udp
</connection>
Այս ձևը սերվերի ընտրությունը պահում է մատակարարի գրած ֆայլի ներսում, ուստի ֆայլերը վերանվանող ռոտացիան չի կոտրում յունիտը։ Այն նաև թեկնածուների ցանկը դարձնում է ստուգելի, ինչը պանակի վրա գլոբը երբեք չի լինում։ Խառնումը դեռ արժանի է իր տեղին, երբ պրոֆիլները տարբերվում են ավելի քան վերջնակետով՝ տարբեր վկայագրեր, տարբեր երթուղավորման հրահանգներ, տարբեր գաղտնագրման քաղաքականություն։ Այդ դեպքում ընտրությունը ամբողջական կոնֆիգուրացիաների միջև է, և shell-ի քայլը դա արտահայտելու ազնիվ ձևն է։
Կրկին կարդացեք օրինակը և այն ֆայլը, որը նա օգտագործել է
Համոզվեք, թե որ յունիտն է իրականում աշխատում, նախքան դրա բովանդակությունը վրիպազերծելը։ Փաթեթավորված մետա ծառայությունը և ձևանմուշը ենթակառուցվածք են՝ ձեր ֆայլերին համապատասխան յունիտները հենց այն օրինակներն են, որոնք կոչվում են նրանց անունով։
systemctl list-units 'openvpn*'
systemctl cat [email protected]
journalctl -u openvpn@au -n 30 --no-pager
Օրինակը, որի միացումը ոչ ոք չի հիշում, սովորաբար տանում է փաթեթի պանակում թափառող կոնֆիգուրացիայի ֆայլի։ Անջատեք հենց այդ անվանված օրինակը, ոչ թե ձևանմուշը, այլապես հաջորդ փաթեթի թարմացումը կվերադարձնի այն։ Փոփոխությունից հետո սկսեք յունիտը և կարդացեք այն հրամանի տողը, որը հաղորդում է ամսագիրը, ապա հաստատեք կոնֆիգուրացիայի ուղին, որը նա իսկապես բացել է։ Այդ մեկ ստուգումը առանձնացնում է աշխատող պատահական ընտրությունը ծառայությունից, որն անաղմուկ վերաօգտագործում է անցյալ ամսվա ֆայլը։