ਕੱਲ੍ਹ ਟਨਲ ਕੰਮ ਕਰ ਰਿਹਾ ਸੀ, ਅਤੇ ਅੱਜ ਸਵੇਰੇ unit ਮਰਿਆ ਹੋਇਆ ਹੈ, ਜਰਨਲ ਵਿੱਚ Failed at step EXEC spawning /usr/local/bin/vpnclient ਹੈ। ਪ੍ਰਮਾਣ-ਪੱਤਰ, ਰੂਟ ਅਤੇ ਖਾਤਾ ਕਦੇ ਵੀ ਉਸ ਵਾਕ ਵਿੱਚ ਨਹੀਂ ਆਉਂਦੇ। systemd ਨੇ ExecStart ਨੂੰ ਇੱਕ ਪਾਥ ਵਿੱਚ ਬਦਲਿਆ, ਕਰਨਲ ਨੂੰ ਇਸਨੂੰ ਚਲਾਉਣ ਦੀ ਬੇਨਤੀ ਕੀਤੀ, ਅਤੇ ਕਰਨਲ ਨੇ ਮਨਾ ਕਰ ਦਿੱਤਾ, ਬਹੁਤੀਆਂ ਵਾਰ ਇਸ ਲਈ ਕਿ ਉਸ ਪਾਥ ’ਤੇ ਕੁਝ ਵੀ ਨਹੀਂ ਹੈ ਜਾਂ ਫਾਈਲ ਚਲਾਉਣ ਯੋਗ ਨਹੀਂ ਹੈ। ਵਿਸ਼ਲੇਸ਼ਿਤ ਕਮਾਂਡ ਉਲਟ ਸਾਬਤ ਨਾ ਕਰੇ ਤਦ ਤੱਕ ਇਸ ਖਰਾਬੀ ਨੂੰ ਫਾਈਲ ਅਤੇ argv ਦੀ ਸਮੱਸਿਆ ਮੰਨੋ।

ਪ੍ਰਮਾਣੀਕਰਨ ਸ਼ੁਰੂ ਹੋਣ ਤੋਂ ਪਹਿਲਾਂ EXEC ਕਿਉਂ ਫੇਲ ਹੁੰਦਾ ਹੈ

systemd ExecStart ਨੂੰ ਸ਼ੈੱਲ ਰਾਹੀਂ ਨਹੀਂ ਚਲਾਉਂਦਾ। ਇਹ fork ਕਰਦਾ ਹੈ, ਲਾਈਨ ਤੋਂ ਆਰਗਿਊਮੈਂਟ ਵੈਕਟਰ ਬਣਾਉਂਦਾ ਹੈ ਅਤੇ ਪਹਿਲੇ ਤੱਤ ’ਤੇ execve ਕਾਲ ਕਰਦਾ ਹੈ। ਜੇ ਉਹ ਕਾਲ ਫੇਲ ਹੋ ਜਾਵੇ, ਤਾਂ ਸੇਵਾ ਕਦੇ ਵੀ VPN ਕਲਾਇੰਟ ਦੇ ਆਪਣੇ ਕੋਡ ਤੱਕ ਨਹੀਂ ਪਹੁੰਚਦੀ, ਇਸ ਲਈ ਪ੍ਰੋਫਾਈਲ ਸੋਧ ਜਾਂ ਪ੍ਰਮਾਣ ਜਾਂਚ ਸਹਾਇਤਾ ਨਹੀਂ ਕਰਦੀ।

ਸਥਿਤੀ ਕੋਡ ਇਸ ਪਰਿਵਾਰ ਨੂੰ ਆਮ ਕ੍ਰੈਸ਼ਾਂ ਤੋਂ ਵੱਖਰਾ ਕਰਦਾ ਹੈ। status=203/EXEC ਨਾਲ ਬਾਹਰ ਨਿਕਲਣ ਵਾਲੇ unit ਨੇ ਕਦੇ ਵੀ ਕੋਈ ਪ੍ਰਕਿਰਿਆ ਸ਼ੁਰੂ ਨਹੀਂ ਕੀਤੀ; ਸ਼ੁਰੂ ਹੋ ਕੇ ਫਿਰ status=1 ਨਾਲ ਨਿਕਲਣ ਵਾਲਾ unit ਸ਼ਾਇਦ ਪ੍ਰਮਾਣੀਕਰਨ, DNS ਜਾਂ ਰਾਊਟਿੰਗ ਵਿੱਚ ਫੇਲ ਹੋਇਆ ਹੈ। ਕਲਾਇੰਟ ਲੌਗ ਪੜ੍ਹਨ ਤੋਂ ਪਹਿਲਾਂ ਕੋਡ ਪੜ੍ਹੋ, ਕਿਉਂਕਿ ਪਹਿਲੇ ਮਾਮਲੇ ਵਿੱਚ ਕਲਾਇੰਟ ਲੌਗ ਖਾਲੀ ਹੋਵੇਗਾ।

ਜਰਨਲ ਵਿੱਚਲਾ ਪਾਥ systemd ਨੇ ਵਰਤਿਆ ਸੀ, ਜ਼ਰੂਰੀ ਨਹੀਂ ਕਿ ਤੁਸੀਂ ਸੋਧਿਆ ਹੋਇਆ ਪਾਥ ਹੋਵੇ। Drop-in ਫਾਈਲਾਂ ਅਤੇ ਜਨਰੇਟਰ ਦਾ ਆਉਟਪੁੱਟ ਵਿਕਰੇਤਾ ਦੀ ਫਾਈਲ ਨੂੰ ਬਦਲ ਸਕਦੇ ਹਨ, ਅਤੇ ਪੁਰਾਣਾ daemon-reload ਪੁਰਾਣੀ ਲਾਈਨ ਨੂੰ ਮੈਮੋਰੀ ਵਿੱਚ ਛੱਡ ਦਿੰਦਾ ਹੈ। ਇਸ ਲਈ ਪਹਿਲਾ ਨਿਦਾਨ ਇਹ ਹੈ ਕਿ ਤੁਸੀਂ ਯਾਦ ਰੱਖਦੇ ਹੋ ਬਦਲੀ ਹੋਈ ਫਾਈਲ ਖੋਲ੍ਹਣ ਦੀ ਬਜਾਏ systemd ਨੂੰ ਪੁੱਛੋ ਕਿ ਉਹ ਕਮਾਂਡ ਨੂੰ ਕੀ ਮੰਨਦਾ ਹੈ।

ਬਾਈਨਰੀ ਦਾ ਪਾਥ ਲਿਖਿਆ ਹੋਣ ਵਾਲੀਆਂ ਤਿੰਨ ਥਾਵਾਂ

ਡਿਸਟ੍ਰੀਬਿਊਸ਼ਨ ਪੈਕੇਜ, ਵਿਕਰੇਤਾ ਸਕ੍ਰਿਪਟ ਅਤੇ ਰਿਲੀਜ਼ tarball ਤੋਂ ਇੰਸਟਾਲ ਕੀਤਾ VPN ਕਲਾਇੰਟ ਤਿੰਨ ਵੱਖਰੇ ਪ੍ਰੀਫਿਕਸਾਂ ਵਿੱਚ ਪੈ ਸਕਦਾ ਹੈ। unit, ਵਿਸ਼ੇਸ਼ ਅਧਿਕਾਰ ਨਿਯਮ ਅਤੇ ਇੰਸਟਾਲਰ ਨੇ ਇਹਨਾਂ ਵਿੱਚੋਂ ਇੱਕ-ਇੱਕ ਪ੍ਰੀਫਿਕਸ ਦਰਜ ਕੀਤਾ, ਅਤੇ ਤਿੰਨਾਂ ਵਿੱਚੋਂ ਦੋ ਨਾ ਮਿਲਣ ’ਤੇ ਖਰਾਬੀ ਦਿਸਦੀ ਹੈ।

RecordCommon valueHow to read it
Unit or drop-in/usr/local/bin/vpnclientsystemctl cat vpnclient.service
Installed binary/usr/bin/vpnclientcommand -v vpnclient, then ls -l the result
Sudoers grant/opt/vpnclient/bin/vpnclientsudo 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-pager

systemctl show ਨਿਰਣਾਇਕ ਆਉਟਪੁੱਟ ਹੈ, ਕਿਉਂਕਿ ਇਹ ਉਹ argv ਛਾਪਦਾ ਹੈ ਜੋ systemd ਨੇ ਅਸਲ ਵਿੱਚ ਵਿਸ਼ਲੇਸ਼ਿਤ ਕੀਤਾ, ਕਿਸੇ ਵੀ drop-in ਸਮੇਤ। systemd-analyze verify ਰੀਸਟਾਰਟ ਤੋਂ ਪਹਿਲਾਂ ਗੁੰਮ ਜਾਂ ਨਾ ਚੱਲਣ ਯੋਗ ਪਾਥ ਫੜ ਲੈਂਦਾ ਹੈ, ਅਤੇ ਰੀਸਟਾਰਟ ਤੋਂ ਬਾਅਦ status ਕਮਾਂਡ ਦੱਸਦੀ ਹੈ ਕਿ ਪ੍ਰਕਿਰਿਆ ਹੁਣ ਮੌਜੂਦ ਹੈ ਜਾਂ ਨਹੀਂ।

ਜੇ unit ਸ਼ੁਰੂ ਹੋ ਕੇ ਫਿਰ ਫੇਲ ਹੋ ਜਾਵੇ, ਤਾਂ ਤੁਸੀਂ EXEC ਪਰਿਵਾਰ ਛੱਡ ਕੇ ਕਲਾਇੰਟ ਦੇ ਆਪਣੇ ਗਲਤੀ ਪ੍ਰਬੰਧਨ ਵਿੱਚ ਦਾਖਲ ਹੋ ਗਏ ਹੋ। ਜਰਨਲ ਵਿੱਚ ਕਲਾਇੰਟ ਦਾ ਸੰਦੇਸ਼ ਲੱਭੋ, ਕੋਈ ਹੋਰ execve ਫੇਲ ਨਹੀਂ। unit ਦਾ diff ਅਤੇ sudoers ਦਾ diff ਬਦਲਾਅ ਰਿਕਾਰਡ ਵਿੱਚ ਇਕੱਠੇ ਰੱਖੋ, ਤਾਂ ਜੋ ਅਗਲਾ ਅੱਪਗਰੇਡ ਵੰਡੇ ਹੋਏ ਪਾਥ ਨੂੰ ਚੁੱਪਚਾਪ ਵਾਪਸ ਨਾ ਲਿਆਵੇ।

ਸੰਬੰਧਿਤ ਲੇਖ