SSD Nodes Learn 🎉 VPS $5.50/মাস থেকে
নির্দেশিকা Matt Connorদ্বারা Matt Connor

systemd unit start না হলে exit code কীভাবে পড়বেন

প্রথমে systemctl status পড়ুন। 203/EXEC ও 226/NAMESPACE-এর অর্থ জানুন, আর কেন unit ঠিকমতো start হয়ে এক সেকেন্ড পরেই exit করে তা বুঝুন।

systemd unit কেন start হয় না

যে systemd unit start হয় না, সেটি একটি field-এ কারণ জানায়। systemctl status <unit> চালান এবং failure report করা লাইনে code=status= খুঁজুন। 200s-এর status number-এর অর্থ হলো systemd আপনার program-এ পৌঁছাতেই পারেনি: unit file যে environment চেয়েছে, সেটি তৈরি করার সময় failure হয়েছে। 200-এর নিচের status-এর অর্থ হলো আপনার program চলেছে এবং নিজে exit করেছে। তাই unit file সম্ভবত সঠিক, কিন্তু application-এ সমস্যা আছে।

এটাই সিদ্ধান্ত নেওয়ার পথ। নিচের সবকিছু এই বিভাজন থেকে অনুসরণ করে, এবং numbers যে ক্রমে দেখা যায় সেই ক্রমেই সাজানো।

প্রশ্নটির উত্তর দেয় এমন তিনটি command, এই ক্রমে

systemctl status myapp.service
journalctl -u myapp.service -b --no-pager
systemd-analyze verify /etc/systemd/system/myapp.service

systemctl status চূড়ান্ত অবস্থা জানায়। প্রথমে Loaded: line পড়ুন। এতে systemd যে file প্রকৃতপক্ষে parse করেছে তার নাম থাকে এবং unitটি enabled, masked, নাকি একেবারেই পাওয়া যায়নি, তা জানায়। এরপর Active: line এবং তার নিচের code=status= জোড়াটি পড়ুন।

journalctl -u myapp.service -b --no-pager বিস্তারিত তথ্য দেয়। -u শুধু ওই unit-এ সীমাবদ্ধ করে, -b output-কে বর্তমান boot-এ সীমিত করে, তাই গত সপ্তাহের failure পড়তে হয় না, এবং --no-pager সরাসরি terminal-এ output দেখায়, যাতে সেটি grep-এ pipe করা যায়। status শুধু log-এর সর্বশেষ কয়েকটি line দেখায় এবং দীর্ঘ line সংক্ষিপ্ত করে। Journal-এ program বন্ধ হওয়ার আগে যে সব output দিয়েছিল, সেগুলো দেখা যায়। সাধারণত প্রকৃত error সেখানেই থাকে। আরও পুরোনো log দেখতে -n 100 যোগ করুন, অথবা unit restart করার সময় দ্বিতীয় terminal-এ -f চালান।

systemd-analyze verify কোনো unit file চালু না করেই load করে। এটি অজানা section ও directive সম্পর্কে সতর্ক করে এবং ExecStart=-এর এমন command চিহ্নিত করে যেগুলো এটি execute করতে পারে না। এতে নীরবে হওয়া দুই ধরনের ভুল ধরা পড়ে: ভুল বানানের key, যা systemd load করার সময় একটি warning দিয়ে উপেক্ষা করে এবং অধিকাংশ মানুষ সেই warning পড়ে না; এবং এমন path, যা উপস্থিত নেই।

যে কোনো unit file সম্পাদনা করার পরে sudo systemctl daemon-reload চালান। এটি না করা পর্যন্ত systemd আগে load করা copy-ই ব্যবহার করে, আর systemctl status disk-এর file পরিবর্তিত হয়েছে বলে একটি warning যোগ করে। কোনো পরিবর্তন “কাজ করেনি” মনে হলে প্রায়ই কারণ হয় systemd এখনও সেই পরিবর্তন পড়েনি।

আরও দুটি command ব্যবহার করা দরকার। systemctl cat myapp.service কার্যকর unit দেখায়, অর্থাৎ মূল file এবং /etc/systemd/system/myapp.service.d/-এর অধীনে থাকা প্রতিটি drop-in একত্রে দেখায়। systemctl show myapp.service -p ExecStart -p User -p WorkingDirectory systemd যেভাবে parse করেছে, সেভাবে ওই value-গুলো দেখায়। বাস্তবে কোন configuration চালু হবে, সেটিই এতে দেখা যায়।

status=203/EXEC বলতে কী বোঝায়?

203/EXEC বোঝায়, systemd setup সম্পন্ন করে execve() চালানোর চেষ্টা করেছে, কিন্তু kernel তা প্রত্যাখ্যান করেছে। আপনার program-এর নিজস্ব কোনো code চালু হয়নি। প্রায় সব ক্ষেত্রে চারটি কারণের একটি দায়ী।

  1. ExecStart=-এর path ভুল, অথবা path-টি absolute নয়। Unit file-এ থাকা নির্ভুল string-এর সঙ্গে ls -l ব্যবহার করে path-টি পরীক্ষা করুন।
  2. File-টিতে execute bit নেই। sudo chmod +x /opt/myapp/run.sh এটি ঠিক করে। Archive থেকে unpack করা বা অন্য machine থেকে copy করা file-এ এই bit প্রায়ই থাকে না।
  3. Shebang line-এ সমস্যা আছে। Kernel কোনো script-এর প্রথম line পড়ে সেখানে উল্লেখ করা interpreter চালায়। তাই service PATH-এ python3 না থাকলে #!/usr/bin/env python3 ব্যর্থ হয়। Windows line ending-এ সংরক্ষিত file এমন interpreter চালানোর অনুরোধ করে যার নাম /bin/bash\r; এই interpreter সাধারণত থাকে না।
  4. File-টি এই machine-এ চালানোর উপযোগী নয়: architecture ভুল, অথবা এটি shebang ছাড়া একটি text file।

কিছু পরিবর্তন করার আগে service user হিসেবে হাতে চালিয়ে সমস্যাটি পুনরায় তৈরি করুন।

sudo -u appuser /opt/myapp/run.sh
file /opt/myapp/run.sh
head -1 /opt/myapp/run.sh | cat -A

সমস্যা line ending-এ হলে file architecture-এর নাম দেখায় এবং "with CRLF line terminators" রিপোর্ট করে। cat -A একই বিষয়টি শেষে থাকা ^M হিসেবে দেখায়। sed -i 's/\r$//' /opt/myapp/run.sh দিয়ে এগুলো সরিয়ে ফেলুন।

এই range সম্পর্কে একটি গুরুত্বপূর্ণ সীমাবদ্ধতা আছে: 200 বা তার বেশি exit code একটি convention, নিশ্চয়তা নয়। আপনার নিজের program-ও 203 দিয়ে exit করতে পারে, এবং systemd এই দুটি অবস্থার পার্থক্য করতে পারে না। systemd-analyze exit-status 203 যেকোনো code-এর নাম ও class দেখায়, যা table পড়তে সহায়তা করে। তবে আপনার application যদি 199-এর বেশি exit code ব্যবহার করে, সেগুলো পরিবর্তন করুন।

217/USER বা 216/GROUP কেন পাই?

217/USER বোঝায়, service শুরু হওয়ার সময় User=-এ উল্লেখ করা account-টি নেই। 216/GROUP হলো Group= বা SupplementaryGroups=-এর ক্ষেত্রে একই ধরনের ব্যর্থতা। প্রতিটি বিষয় একটি করে command দিয়ে নিশ্চিত করুন।

getent passwd appuser
getent group appgroup

প্রতিটি command হয় একটি line দেখায়, নয়তো কিছু না দেখিয়ে non-zero return code দেয়। কিছু না দেখানোর অর্থ হলো name-টি system-এর কাছে অজানা। তাই systemd ওই account-এ switch করতে পারে না এবং exec-এর আগেই থেমে যায়। সমাধান হলো account তৈরি করা, User=root সেট করা নয়। সর্বনিম্ন privilege-সহ dedicated system account-এর অধীনে একটি service চালানোই ওই directive ব্যবহারের মূল উদ্দেশ্য।

sudo useradd --system --no-create-home --shell /usr/sbin/nologin appuser

DynamicUser=yes ব্যবহার করলে systemd প্রতিবার start-এর সময় একটি অস্থায়ী account বরাদ্দ করে এবং সমস্যাটি এড়ানো যায়। যে service কোনো state সংরক্ষণ করে না, তার জন্য এটি উপযুক্ত। কোনো service file লিখলে এর সঙ্গে StateDirectory=-ও দিতে হবে, কারণ প্রতিবার start-এর সময় user ID বদলে যায় এবং সাধারণ path-এর অধীনে থাকা file এমন একটি account-এর মালিকানাধীন হয়ে যায়, যার আর অস্তিত্ব নেই।

226/NAMESPACE কী?

226/NAMESPACE sandboxing directive থেকে আসে। কোনো unit-এ ProtectSystem=, ProtectHome=, PrivateTmp=, ReadWritePaths= বা অনুরূপ কোনো directive সেট করা হলে systemd program চালানোর আগে সেই service-এর জন্য একটি private mount namespace তৈরি করে। এখানে namespace বলতে একটি process-এর জন্য filesystem-এর private view বোঝায়। ওই পরিকল্পনার কোনো mount ব্যর্থ হলে start ব্যর্থ হয়, 226 error দেখা যায় এবং আপনার program কখনো চালু হয় না।

সাধারণ কারণ হলো ReadWritePaths=-এ থাকা কোনো path-এর অস্তিত্ব না থাকা। ProtectSystem=strict পুরো filesystem-কে read-only হিসেবে mount করে, আর ReadWritePaths= নির্দিষ্ট path-গুলোকে আবার write করার জন্য খোলে। systemd অস্তিত্বহীন directory আবার খুলতে পারে না। এর দুটি কার্যকর সমাধান আছে। StateDirectory= ব্যবহার করে systemd-কে directory তৈরি করতে দিন। এটি প্রতিবার start-এর সময় /var/lib/<name> তৈরি করে এবং service user-কে এর ownership দেয়। অথবা path-এর আগে - যোগ করুন। এতে source অনুপস্থিত থাকলে systemd ওই entry উপেক্ষা করবে। ভুল সমাধান হলো hardening বাদ দেওয়া। এতে পাঁচ মিনিটের সমস্যা স্থায়ী সমস্যায় পরিণত হয়।

[Service]
ProtectSystem=strict
ProtectHome=yes
StateDirectory=myapp
ReadWritePaths=-/srv/uploads

কোন line-এর কারণে সমস্যা হচ্ছে বুঝতে না পারলে পুরো hardening block সরিয়ে reload করে start করুন। service চালু হলে line-গুলো একবারে একটি করে আবার যোগ করুন এবং প্রতিটির পরে restart করুন। এই পরিবারের কাছাকাছি আরও দুটি directive হলো 233/RUNTIME_DIRECTORY এবং 238/STATE_DIRECTORY। এগুলোর অর্থ হলো RuntimeDirectory= বা StateDirectory=-এ উল্লেখ করা directory systemd তৈরি করতে বা এর ownership নিতে পারেনি। সাধারণত path-টি আগে থেকেই থাকে এবং অন্য user-এর ownership-এ থাকে।

WorkingDirectory সঠিক দেখালেও 200/CHDIR কেন দেখা যায়?

200/CHDIR বোঝায় যে chdir() থেকে WorkingDirectory=-এ প্রবেশ ব্যর্থ হয়েছে। Directory অনুপস্থিত, অথবা service user সেখানে প্রবেশ করতে পারে না। কোনো directory-তে প্রবেশ করতে সেই directory এবং তার উপরের প্রতিটি parent directory-তে execute permission প্রয়োজন। তাই /home/deploy/app সম্পূর্ণ পাঠযোগ্য হলেও সেটিতে পৌঁছানো যায় না, যখন /home/deploy-এর mode 700 এবং service appuser হিসেবে চলে।

sudo -u appuser test -x /srv/myapp && echo ok
namei -l /srv/myapp

namei -l path-এর প্রতিটি component-এর owner ও mode দেখায়। কোন directory পরবর্তী অংশে প্রবেশ আটকে দিচ্ছে, তা খুঁজে বের করার এটিই দ্রুততম উপায়। WorkingDirectory=-/srv/myapp লিখলে অনুপস্থিত directory-কে non-fatal করা হয়। যে program কোথা থেকে শুরু হচ্ছে তা নিয়ে নির্ভর করে না, তার ক্ষেত্রে এটি সঠিক। কিন্তু যে program relative path ব্যবহার করে file খোলে, তার ক্ষেত্রে এটি সঠিক নয়।

সার্ভিস শুরু হওয়ার এক সেকেন্ড পরেই বন্ধ হয়ে যায় কেন?

এখানে 200-series code থাকে না, এবং অনেক সময় কোনো error text-ও থাকে না। শুরু হওয়ার পরেই unit-এর অবস্থা inactive (dead) দেখা যায়, অথবা এটি activating (auto-restart) অবস্থাগুলোর মধ্যে ঘুরতে থাকে। systemd environment সঠিকভাবে তৈরি করেছে। সমস্যা হলো, আপনার program যে আচরণ করছে এবং Type= অনুযায়ী তার যে আচরণ করার কথা, তার মধ্যে অমিল।

Type=simple, যা default, নির্দেশ করে যে program foreground-এ চলবে। এমন কোনো daemon দিলে, যা background-এ fork করে এবং নিজে শেষ হয়ে যায়, systemd ধরে নেয় যে main process শেষ হয়েছে এবং service-কে সম্পন্ন হিসেবে চিহ্নিত করে। অধিকাংশ daemon-এ foreground-এ থাকার জন্য একটি flag থাকে, যেমন nginx -g 'daemon off;'

Type=forking নির্দেশ করে যে child ready হওয়ার পর প্রথম process শেষ হবে। এখানে foreground program দিলে start job TimeoutStartSec= শেষ হওয়া পর্যন্ত অপেক্ষা করে। Default হিসেবে এই সময় 90 seconds। এরপর systemd process-টি বন্ধ করে এবং timeout log করে।

Type=notify নির্দেশ করে যে program readiness জানাতে sd_notify() call করে। এই support না থাকা program কোনো readiness signal পাঠায় না। ফলে start timeout হয় এবং journal ফলাফলটিকে protocol failure হিসেবে record করে।

Program বাস্তবে কী করে, তার ভিত্তিতে type নির্বাচন করুন। simple, forking, oneshot এবং notify-এর পার্থক্য পড়লেই এই ধরনের পুরো সমস্যার জন্য প্রয়োজনীয় সিদ্ধান্ত নেওয়া যায়।

কোনো service বারবার exit করলে systemd চেষ্টা করা বন্ধ করে এবং জানায় যে start request খুব দ্রুত পুনরাবৃত্ত হয়েছে। Rate limit-এর সময়সীমা শেষ না হওয়া পর্যন্ত, অথবা আপনি sudo systemctl reset-failed myapp.service চালানো পর্যন্ত, unit failed অবস্থায় থাকে। Limit বাড়ালে শুধু লক্ষণটি আড়াল হয়। শেষ failure-এর বদলে প্রথম failure থেকে journal পড়ুন। পরিবর্তন করার আগে Restart=on-failure আসলে কী retry করে দেখুন।

কোনো error ছাড়াই unit কেন inactive থাকে?

কোনো unit start না হয়ে skip হতে পারে। Condition* directive নীরবে কাজ করে: check ব্যর্থ হলে systemd job-টিকে successful হিসেবে চিহ্নিত করে এবং আর কিছু করে না। ConditionPathExists=/etc/myapp/config.yml থাকা কোনো unit সংশ্লিষ্ট file অনুপস্থিত থাকলে কখনো start হবে না, তবে কোনো error-ও report করবে না।

systemctl show myapp.service -p ConditionResult -p ConditionTimestamp
journalctl -u myapp.service -b --no-pager | grep -i condition

ConditionResult=no skip হওয়ার বিষয়টি নিশ্চিত করে, এবং journal-এ কোন check সফল হয়নি তা উল্লেখ থাকে। কোনো prerequisite অনুপস্থিত থাকলে সেটিকে স্পষ্ট error হিসেবে দেখাতে Assert* directive ব্যবহার করুন। Conditions, asserts এবং unit ordering-এ কোন check কোথায় ব্যবহার করতে হবে তা ব্যাখ্যা করা হয়েছে।

আরও কয়েকটি নীরব case কাছাকাছি দেখা যায়। "could not be found" error সাধারণত বোঝায় যে file-টি ভুল directory-তে আছে অথবা আপনি reload করেননি: আপনার তৈরি করা unit file /etc/systemd/system/-এ থাকতে হবে। Mask করা unit প্রতিটি start request প্রত্যাখ্যান করে, যতক্ষণ না sudo systemctl unmask myapp.service সেটি unmask করে। আর systemctl enable এমন unit-এ ব্যর্থ হয় যেখানে [Install] section নেই; তাই সেখানে WantedBy=multi-user.target দিন।

ব্যর্থ হওয়ার পরিবর্তে process-টি বন্ধ করে দেওয়া হলে কী হবে?

code=killed এবং code=exited আলাদা বিষয়। Process-টির বাইরের কোনো কিছু সেটিকে বন্ধ করেছে। status=9/KILL সাধারণত out of memory (OOM) killer-এর ইঙ্গিত দেয়, এবং journal-এ বেছে নেওয়া process-টির নাম থাকে। আপনি নিজে নির্ধারণ করা কোনো limit cgroup (control group)-এর ভেতর একই কাজ করে। তাই free -m দিয়ে host-এর free memory পরীক্ষা করুন এবং unit-এ MemoryMax= আছে কি না দেখুন। MemoryMax, CPUQuota এবং অন্যান্য cgroup limit-এ কোন limit process বন্ধ করে এবং কোনটি শুধু process ধীর করে, তা ব্যাখ্যা করা হয়েছে।

Start attempt-এর ঠিক পরে status=15/TERM দেখা গেলে সাধারণত বোঝায় systemd start-এর জন্য নির্ধারিত সময়সীমা পার হওয়ায় process-টি বন্ধ করেছে। তখন আবার Type=-এ ফিরে যান।

এই ব্যর্থতাগুলোর বেশিরভাগ প্রতিরোধ করে এমন দুটি অভ্যাস

সব জায়গায় absolute path ব্যবহার করুন। systemd আপনার login shell চালায় না। তাই কোনো .bashrc থাকে না, কোনো .profile থাকে না, এবং কোনো activated virtual environment-ও থাকে না। একটি system service-এর জন্য $PATH হলো সংক্ষিপ্ত built-in তালিকা। এতে /opt বা কোনো language version manager-এর shim থাকবে না। /usr/bin/python3 বা /opt/myapp/venv/bin/python সম্পূর্ণ path-সহ লিখুন। আপনার shell-এ command -v myapp চালালে paste করার মতো path দেখায়। একই নিয়ম WorkingDirectory=, EnvironmentFile= এবং ReadWritePaths=-এর প্রতিটি path-এর ক্ষেত্রেও প্রযোজ্য।

ExecStart= কোনো shell নয়। systemd লাইনটিকে শব্দে ভাগ করে নিজেই execve()-কে কল করে। Pipe, redirection, glob, &&, backtick এবং ~-এর কোনো অর্থ systemd বোঝে না। এগুলো আপনার program-এর কাছে literal argument হিসেবে পৌঁছে যায়। ExecStart=/usr/bin/myapp --flag > /tmp/out.log, > এবং /tmp/out.log-কে myapp-এর কাছে পাঠায়। এরপর myapp usage error দিয়ে বন্ধ হয়ে যায়, যা systemd সমস্যার মতো দেখায় না। Shell feature প্রয়োজন হলে একটি shell চালানোর নির্দেশ দিন।

ExecStart=/bin/sh -c '/usr/bin/myapp --flag | /usr/bin/tee -a /var/log/myapp.log'

শুধু output-এর জন্য এটি প্রয়োজন নেই। Service-এর output ডিফল্টভাবে journal-এ যায়, এবং StandardOutput=append:/var/log/myapp.log কোনো shell ছাড়াই একটি file-এ লেখে।

Variable expansion-ও একইভাবে সীমিত। $MYVAR এবং ${MYVAR}, Environment=EnvironmentFile= থেকে প্রতিস্থাপিত হয়। অন্য কিছু expand হয় না। কোনো system service-এর জন্য $HOME সেট থাকে না, যদি না আপনি এটি সেট করেন। একটি EnvironmentFile=-ও shell script নয়। এতে export ব্যবহার করা যায় না। এর quoting rules bash-এর থেকে আলাদা। এবং path-এর আগে - না লিখলে missing file fatal error ঘটায়।

লাইভ সার্ভারে ধাপে ধাপে যাচাই

কোড পড়ুন, কারণের প্রমাণ সংগ্রহ করুন, একটি পরিবর্তন করুন, তারপর restart করুন। কোন পরিবর্তন কাজে এসেছে তা বোঝার সুযোগ নষ্ট করে একসঙ্গে তিনটি অনুমানভিত্তিক সম্পাদনা করা থেকে বিরত রাখে বলে এই ক্রমটি প্রতিটি সংখ্যা জানার চেয়েও গুরুত্বপূর্ণ। আপনি নিজে তৈরি করেননি এমন unit-এর ক্ষেত্রেও একই পদ্ধতি প্রযোজ্য। যে timer কখনও চালু হয় না, সেটি এমন একটি service যা কখনও শুরু হয়নি। তাই প্রথমে service debug করুন: একটি systemd timer এবং এটি যে service চালু করে উপরের একই সমস্যায় ব্যর্থ হয়। journal-এ output দেখতে চাইলে তবেই timer সেটি প্রকাশ করে।

FAQ

systemctl status-এ status=203/EXEC বলতে কী বোঝায়?

systemd unit-এর জন্য প্রয়োজনীয় সবকিছু প্রস্তুত করেছে, কিন্তু execve() call ব্যর্থ হয়েছে। তাই আপনার program কখনো start হয়নি। ধারাবাহিকভাবে চারটি বিষয় পরীক্ষা করুন: ExecStart=-এ থাকা path বিদ্যমান এবং absolute কি না, file-এ execute bit আছে কি না, shebang-এ এমন interpreter-এর নাম আছে কি না যা service-এর PATH-এ বিদ্যমান, এবং file-এ Unix line ending ব্যবহার করা হয়েছে কি না। শেষ বিষয়টির ক্ষেত্রে file "with CRLF line terminators" দেখায়। এর ফলে interpreter-এর নাম /bin/bash\r হয়ে যায় এবং kernel file-টি চালাতে অস্বীকার করে।

আমার service start হওয়ার পরপরই বন্ধ হয়ে যায় কেন?

unit file এমন আচরণের প্রতিশ্রুতি দিচ্ছে যা program-এ নেই। Type=simple ব্যবহার করলে systemd আশা করে program-টি foreground-এ চলতে থাকবে। তাই background-এ fork করা daemon fork করার সঙ্গে সঙ্গেই শেষ হয়ে গেছে বলে মনে হয়। Type=forking ব্যবহার করলে systemd প্রথম process exit করার জন্য অপেক্ষা করে। ফলে foreground program TimeoutStartSec= শেষ না হওয়া পর্যন্ত start job আটকে থাকে। Type=-কে program-এর আচরণের সঙ্গে মিলিয়ে দিন। Program foreground flag দিলে সেই flag-টি default Type=simple-এর সঙ্গে ব্যবহার করুন।

সংক্ষিপ্ত status output-এর বদলে প্রকৃত error কীভাবে দেখব?

systemctl status শুধু journal-এর শেষ কয়েকটি line দেখায় এবং দীর্ঘ line সংক্ষিপ্ত করে। এই boot চলাকালে unit যে সব log লিখেছে সেগুলো পেতে journalctl -u myapp.service -b --no-pager চালান। বড় সময়সীমা পেতে -n 200 যোগ করুন, অথবা output-টি grep-এ pipe করুন। Application নিজস্ব log file-এ লিখলে সেটিও পড়ুন। কারণ systemd শুধু program-এর standard output এবং standard error-এ পাঠানো তথ্য capture করে।

কোনো error message ছাড়াই আমার unit inactive কেন?

সাধারণত কোনো Condition* directive unit-টিকে এড়িয়ে গেছে। এই check-গুলো নীরবে কাজ করে। কোনো condition ব্যর্থ হলেও start job সফল হিসেবে চিহ্নিত হয়। systemctl show myapp.service -p ConditionResult চালিয়ে ConditionResult=no খুঁজুন। এরপর যে journal line-এ check-টির নাম আছে সেটি পড়ুন। আরেকটি সাধারণ কারণ হলো masked unit। sudo systemctl unmask mask সরানো পর্যন্ত এটি কোনো start operation গ্রহণ করে না।

প্রতিবার unit file পরিবর্তন করলে কি daemon-reload দরকার?

হ্যাঁ, unit file বা drop-in-এ যেকোনো পরিবর্তনের পরে এটি দরকার। sudo systemctl daemon-reload systemd-কে disk থেকে file-গুলো আবার পড়তে বলে। এরপর sudo systemctl restart myapp.service চলমান service-এ সেই পরিবর্তন প্রয়োগ করে। systemctl edit-এর পরে এটি দরকার নেই, কারণ ওই command নিজেই reload করে। Application-এর configuration file পরিবর্তন করলেও এটি দরকার নেই, যদি file-টি systemd-এর নয়, application-এর হয়।

#systemd#troubleshooting#journalctl#exit-codes#linux-fundamentals