VPN ծառայությունը ձախողվում է EXEC-ում. համեմատեք unit-ը, բինար ֆայլը և sudoers-ը
EXEC քայլում ձախողումը նշանակում է, որ systemd-ը չկարողացավ գործարկել բինար ֆայլը։ Նախքան որևէ բան փոխելը համեմատեք unit-ի ուղին, տեղադրված ուղին և sudoers-ի թույլտվությունը։
Երեկ թունելը աշխատում էր, իսկ այս առավոտ unit-ը մեռած է, մատյանում կա Failed at step EXEC spawning /usr/local/bin/vpnclient։ Հավատարմագրերը, երթուղիները և հաշիվը երբեք չեն մտնում այդ նախադասության մեջ։ systemd-ը ExecStart-ը լուծեց ուղու, խնդրեց կորնելին գործարկել այն, և կորնելը մերժեց, ամենից հաճախ որովհետև այդ ուղում ոչինչ չկա կամ ֆայլը գործարկելի չէ։ Վերաբերվեք խափանմանը որպես ֆայլի և argv-ի խնդրի, քանի դեռ վերլուծված հրամանը չի ապացուցել հակառակը։
Ինչու է EXEC-ը ձախողվում մինչև նույնականացման մեկնարկը
systemd-ը ExecStart-ը չի գործարկում shell-ի միջոցով։ Այն կատարում է fork, տողից կառուցում է արգումենտների վեկտոր և execve է կանչում առաջին տարրի վրա։ Եթե այդ կանչը ձախողվի, ծառայությունը երբեք չի հասնում VPN հաճախորդի սեփական կոդին, ուստի պրոֆիլի խմբագրումը կամ հավատարմագրերի ստուգումը չեն օգնի։
Կարգավիճակի կոդը բաժանում է այս ընտանիքը սովորական խափանումներից։ status=203/EXEC-ով դուրս եկած unit-ը երբեք գործընթաց չի սկսել. unit-ը, որը սկսվում է և հետո դուրս է գալիս status=1 -ով, հնարավոր է ձախողվել է նույնականացման, DNS-ի կամ երթուղավորման փուլում։ Կոդը կարդացեք հաճախորդի մատյանից առաջ, որովհետև առաջին դեպքում հաճախորդի մատյանը դատարկ կլինի։
Մատյանի ուղին այն ուղին է, որն օգտագործել է systemd-ը, ոչ պարտադիր այն, որը դուք խմբագրել եք։ Drop-in ֆայլերը և գեներատորի ելքը կարող են վերագրանցել մատակարարի ֆայլը, իսկ հնացած daemon-reload-ը հին տողը թողնում է հիշողության մեջ։ Դրա համար առաջին ախտորոշումը systemd-ից հարցնելն է, թե ինչ է նա համարում հրամանը, այլ ոչ թե բացել այն ֆայլը, որը հիշում եք, թե փոխել եք։
Երեք տեղ, որտեղ գրվում է բինար ֆայլի ուղին
Տարածման փաթեթից, մատակարարի սկրիպտից և թողարկման tarball-ից տեղադրված VPN հաճախորդը կարող է հայտնվել երեք տարբեր նախածանցերում։ unit-ը, արտոնության կանոնը և տեղադրիչը յուրաքանչյուրը գրանցել է այդ նախածանցերից մեկը, և խափանումը հայտնվում է, երբ երեքից երկուսը չեն համընկնում։
| Record | Common value | How to read it |
|---|---|---|
| Unit or drop-in | /usr/local/bin/vpnclient | systemctl cat vpnclient.service |
| Installed binary | /usr/bin/vpnclient | command -v vpnclient, then ls -l the result |
| Sudoers grant | /opt/vpnclient/bin/vpnclient | sudo grep -r vpnclient /etc/sudoers.d/ |
Կոնկրետ անհամապատասխանությունն այսպես է՝ մատակարարի սկրիպտը տեղադրում է /usr/local/bin, tarball-ը բացվել է /opt-ի տակ, իսկ unit-ը դեռ նշում է նախորդ փաթեթի հին /usr/bin ուղին։ Այդ ֆայլերից գոյություն ունի միայն մեկը, և հազվադեպ է, որ դա ExecStart-ում եղած ֆայլն է։
Որոշեք, թե որ ուղին է կանոնական, նախքան ֆայլերից որևէ մեկը փոխելը։ Եթե բինար ֆայլը պատկանում է տարածման փաթեթին, կանոնականը փաթեթի ուղին է, և unit-ը պետք է հետևի դրան։ Եթե այն պատկանում է մատակարարի սկրիպտին, նույն կանոնը գործում է մատակարարի նախածանցի համար։ Բինար ֆայլը նախածանցերի միջև պատճենելը ստեղծում է երկու պատճեն, որոնք հաջորդ թարմացման ժամանակ կտարանջատվեն։
Երբ չակերտների մեջ դրված հրամանը դառնում է ֆայլի անուն
Երկրորդ խափանման ձևը թաքնված է մատյանի նույն տողի հետևում։ Ինչ-որ մեկը սա գրում է unit-ի մեջ և ակնկալում, որ հաճախորդը կմիանա բեռնման ընթացքում՝
ExecStart=/usr/bin/"vpnclient connect office"systemd-ը արժեքը բաժանում է բառերի, ուստի առաջին բառը դառնում է /usr/bin/vpnclient connect office, ընդ որում չակերտները հանվում են որպես խմբավորման շարահյուսություն։ Այնուհետև կորնելը փնտրում է ֆայլ, որի անվան մեջ բացատներ կան, և այդպիսին չկա։ Սխալը նույնական է բացակայող բինար ֆայլի սխալին, թեև ֆայլը տեղադրված է։
Աջակցվող ձևը իրական գործարկելի ֆայլն է, որին հաջորդում են առանձին արգումենտներ, օրինակ՝ ExecStart=/usr/bin/vpnclient connect office։ Եթե աշխատանքի հոսքը իսկապես պահանջում է խողովակ կամ շղթա, դրեք այն սկրիպտի մեջ և կանչեք սկրիպտը, որովհետև ExecStart-ը չունի &&, չունի խողովակներ և չունի glob ընդլայնում։
Ուղղեք unit-ը, ոչ թե ֆայլային համակարգը
Գայթակղիչ վերանորոգումը սիմվոլիկ հղումն է սպասվող ուղուց դեպի իրական բինար ֆայլը։ Այն աշխատում է այնքան, մինչև փաթեթը թարմացվի և հղումը ցույց տա հեռացված ֆայլի, կամ մինչև SELinux պիտակը այլևս չհամապատասխանի թիրախին։ Ավելի լավ է unit-ը խմբագրել drop-in-ի միջոցով, որպեսզի մատակարարի ֆայլը մնա անձեռնմխելի, իսկ թարմացումները՝ կանխատեսելի։
Արտոնության կանոնը պետք է համապատասխանի նույն ուղուն և նույն ենթահրամաններին։ /usr/local/bin/vpnclient-ի համար sudoers գրառումը չի լիազորում /usr/bin/vpnclient-ը, իսկ ցանկացած արգումենտ թույլատրող գրառումը թույլ է տալիս ցանկացած լոկալ գործընթացի վերակարգավորել կամ կանգնեցնել թունելը։ Տվեք այն երկու բայերը, որոնք unit-ին անհրաժեշտ են, և ապամոնտաժումը պահեք դրանից դուրս, եթե ծառայության կանգը արդեն փակում է ինտերֆեյսը։
Այստեղ է, որ համեմատությունն արդարացնում է իրեն՝ unit-ը, փաթեթների տվյալների բազան և sudoers-ը պետք է բոլորն անվանեն մեկ ուղի։ Երբ այդպես է, EXEC սխալը վերանում է առանց վերագործարկման և առանց բինար ֆայլի պատճենի երրորդ տեղում։
Ապացուցեք վերլուծված հրամանը մինչև վերագործարկումը
sudo systemctl daemon-reload
sudo systemctl cat vpnclient.service
systemctl show -p ExecStart vpnclient.service
systemd-analyze verify /etc/systemd/system/vpnclient.service
sudo systemctl restart vpnclient.service
systemctl status vpnclient.service --no-pagersystemctl show-ը վճռորոշ ելքն է, որովհետև այն տպում է այն argv-ն, որը systemd-ը իրականում վերլուծել է, ներառյալ ցանկացած drop-in։ systemd-analyze verify-ը բռնում է բացակայող կամ ոչ գործարկելի ուղին նախքան վերագործարկելը, իսկ վերագործարկումից հետո status հրամանը ասում է՝ գործընթացը հիմա գոյություն ունի՞։
Եթե unit-ը սկսվում է և հետո ձախողվում, դուք թողել եք EXEC ընտանիքը և մտել հաճախորդի սեփական սխալների մշակման մեջ։ Մատյանում փնտրեք հաճախորդի հաղորդագրությունը, ոչ թե ևս մեկ execve խափանում։ Պահեք unit-ի diff-ը և sudoers-ի diff-ը միասին փոփոխության գրառման մեջ, որպեսզի հաջորդ թարմացումը լուռ չվերադարձնի բաժանված ուղին։