systemd service Type: simple, forking, notify விளக்கம்
உங்கள் systemd unit active என்று காட்டியும் daemon இயங்கவில்லையா? simple, forking, notify மற்றும் oneshot ஆகியவற்றுக்கு இடையே உள்ள வேறுபாடுகளை அறிந்து, சரியான main PID-ஐ கண்டறியவும்.
செயல்முறை (process) இறந்த பிறகும் systemd ஏன் ஒரு unit-ஐ active என்று காட்டுகிறது?
ஒரு systemd service unit, systemd எதை முதன்மைச் செயல்முறை (main process) என்று கருதுகிறதோ அது உயிர்ப்புடன் இருக்கும் வரை active நிலையில் இருக்கும். [Service] பிரிவில் உள்ள Type=, எந்தச் செயல்முறையை முதன்மையாகக் கருத வேண்டும் என்பதைத் தீர்மானிக்கிறது. தவறான மதிப்பைத் தேர்ந்தெடுத்தால், நீங்கள் கண்காணிக்க விரும்பும் daemon-க்கு உள்ளேயே இறந்துவிட்டாலும், systemd ஒரு shell wrapper-ஐ அல்லது குறுகிய காலமே இயங்கும் parent process-ஐக் கண்காணித்துக் கொண்டிருக்கும். அந்த unit, தான் கண்காணிக்கச் சொல்லப்பட்ட செயல்முறையைப் பற்றிய உண்மையான தகவலையே உங்களுக்குத் தெரிவிக்கிறது.
Restart policy-ஐ மாற்றுவது இங்கே உதவாது. முதன்மைச் செயல்முறை வெளியேறும்போதுதான் Restart= செயல்படும். எனவே, முதன்மை PID (process identifier) இன்னும் இயங்கிக்கொண்டிருக்கும் ஒரு செயல்முறைக்குச் சொந்தமாக இருக்கும் வரை Restart=always ஒருபோதும் இயங்காது. முதலில் Type=-ஐச் சரிசெய்யவும். முதன்மைச் செயல்முறை உண்மையில் வெளியேறிய பிறகு systemd என்ன செய்ய வேண்டும் என்பது தனிப்பட்ட முடிவு; அது Restart= மற்றும் RestartSec= கையேட்டில் விளக்கப்பட்டுள்ளது.
Type= எதனைத் தீர்மானிக்கிறது
ஒவ்வொரு Type= மதிப்பும் ஒரே நேரத்தில் இரண்டு கேள்விகளுக்குப் பதிலளிக்கிறது. systemd எப்போது இந்த unit-ஐத் தொடங்கியதாகக் கருத வேண்டும், மற்றும் இதில் எது முதன்மையான process என்பதுதான் அவை.
முதல் பதில் வரிசைப்படுத்துதலை (ordering) கட்டுப்படுத்துகிறது. உங்கள் unit-ஐ After=-ல் குறிப்பிடும் ஒரு unit, systemd உங்கள் unit-ஐத் தொடங்கியதாக அறிவிக்கும் வரை காத்திருக்கும். மிக விரைவாக "started" என்று தெரிவிக்கும் ஒரு Type=, உங்கள் service தயாராகும் முன்பே அதனுடன் தொடர்புடைய பிற unit-களை இயங்கச் செய்துவிடும்.
இரண்டாவது பதில் கண்காணிப்பைக் (supervision) கட்டுப்படுத்துகிறது. ஒரு unit உருவாக்கும் ஒவ்வொரு process-ஐயும் systemd ஒரு cgroup-ல் (control group) வைக்கிறது. இது process-களைக் குழுவாக்கி, அவற்றைக் கட்டுப்படுத்தவும் ஒரே நேரத்தில் நிறுத்தவும் உதவும் ஒரு kernel வசதியாகும். systemctl stop எவ்வாறு cleanup செய்கிறது என்பதை இந்த cgroup தீர்மானிக்கிறது: KillMode= இயல்பாகவே control-group என்று இருப்பதால், ஒரு unit-ஐ நிறுத்தும்போது அதிலுள்ள அனைத்து process-களுக்கும் signal அனுப்பப்படும். முதன்மையான PID (main PID) என்பது குறுகிய வரம்பைக் கொண்டது. இது அந்த unit-ன் முடிவைத் தீர்மானிக்கும் ஒரே process ஆகும்; இதன் exit status-தான் அந்த unit-ன் முடிவாகக் கருதப்படும். cgroup-ஐ முதன்மையான PID-ஆகக் கருதுவதே குழப்பத்திற்கு முக்கிய காரணமாகிறது.
Type=simple என்பது binary இயங்குவதற்கு முன்பே தொடங்கப்பட்டதாகக் காட்டுகிறது
Type=simple என்பது ExecStart= அமைக்கப்பட்டு, Type= அல்லது BusName= ஆகிய இரண்டும் இல்லாதபோது இயல்பாக அமையும் அமைப்பாகும். systemd ஒரு process-ஐ உருவாக்கி, அந்த unit உடனடியாகத் தொடங்கிவிட்டதாகக் கருதி, அந்த process-ஐ முதன்மை PID-ஆகக் கொள்கிறது. service binary இயங்குவதற்கு முன்பே, அடுத்தடுத்த unit-கள் உடனடியாகத் தொடங்கத் தொடங்கிவிடும்.
இந்தக் கடைசி விவரம் ஒரு பொதுவான குழப்பத்தை விளக்குகிறது. ExecStart= பாதையில் தட்டச்சுப் பிழை (typo) இருந்தாலும், ஒரு start job வெற்றிகரமாக முடிந்ததாகவே காட்டும்; ஆனால், execution தோல்வியடையும் போதுதான் பிழை வெளிப்படும். systemd அந்தச் சூழலை exit code 203-ஆகப் பதிவு செய்கிறது; அதன் சொந்த அட்டவணை இதை EXEC என்று குறிப்பிடுகிறது, அதாவது service binary-ஐ இயக்கத் தவறியது என்று பொருள். எனவே, systemctl start பிழை இல்லாமல் முடிந்தது என்பது உங்கள் binary அங்கு உள்ளது என்பதற்குச் சான்றல்ல.
முன்புறத்தில் (foreground) இயங்கி, தன்னைத்தானே பின்புலத்திற்கு (background) மாற்றிக்கொள்ளாத நிரல்களுக்கு simple-ஐப் பயன்படுத்தவும். இது நவீன daemons மற்றும் நீங்கள் சொந்தமாக எழுதும் பெரும்பாலான நிரல்களுக்குப் பொருந்தும்.
Type=exec என்பது நிரல் தொடங்கும் வரை காத்திருக்கும்
Type=exec என்பது simple-ன் மேம்படுத்தப்பட்ட வடிவமாகும். ஒரு binary-ன் fork மற்றும் execution ஆகிய இரண்டும் வெற்றிகரமாக முடிந்த பிறகு மட்டுமே, அந்த unit தொடங்கிவிட்டதாக systemd கருதும். ஒரு binary கோப்பு விடுபட்டிருந்தாலோ அல்லது User=-ஐத் தீர்க்க முடியாவிட்டாலோ, அது வெற்றிகரமாகத் தொடங்கியதாகக் காட்டிவிட்டுச் சிறிது நேரத்தில் செயலிழப்பதற்குப் பதிலாக, தொடக்க நிலையிலேயே அந்தப் பணியைத் தோல்வியடையச் செய்யும்.
Type=exec ஆனது systemd 240 பதிப்பில் அறிமுகப்படுத்தப்பட்டது, எனவே தற்போதுள்ள அனைத்து server distribution-களிலும் இது உள்ளது. ஆகஸ்ட் 2026 நிலவரப்படி, Ubuntu 24.04-ல் systemd 255-ம், Debian 13-ல் systemd 257-ம் உள்ளன. உங்கள் பதிப்பை systemctl --version மூலம் சரிபார்க்கவும்.
இதன் விலை, தொடக்கத்தின் போது கூடுதலாக ஒரு synchronisation படிநிலையைச் செய்ய வேண்டியதுதான். இதன் பயன், systemctl start-லிருந்து துல்லியமான exit status கிடைப்பதாகும். Foreground-ல் இயங்கும் நிரல்களுக்கு, simple-க்கு பதிலாக exec-ஐப் பயன்படுத்துவது சிறந்தது.
Type=forking மற்றும் முதன்மை PID தொலைந்து போதல்
Type=forking, ExecStart=-ல் உள்ள process ஒரு child-ஐ உருவாக்கிவிட்டு, திட்டமிட்டபடி வெளியேறும் என்பதை systemd-க்கு உணர்த்துகிறது. அந்த முதல் process வெளியேறும் வரை systemd காத்திருந்து, அதன் பிறகே unit-ஐ started நிலைக்கு மாற்றும். எஞ்சியிருக்கும் child-தான் daemon ஆகும். இந்த வழக்கம் SysV காலத்திலிருந்தே தொடர்கிறது; அப்போது init script முடிந்த பிறகு daemon-ஐக் கண்காணிக்க எதுவுமில்லை, PID file மட்டுமே இயங்கும் process-ஐக் குறிக்கும் ஒரே ஆதாரமாக இருந்தது. இந்த வரம்புதான் systemd ஏன் init scripts-க்கு மாற்றாக வந்தது என்பதன் மையக் காரணமாகும்.
இதில் உள்ள சிக்கல் அடையாளத்தை உறுதிப்படுத்துவதாகும். systemd தொடங்கிய process முடிந்துவிட்டதால், எஞ்சியிருப்பவற்றில் எது முதன்மையானது என்பதை அது கண்டறிய வேண்டும். PIDFile=-ஐ daemon எழுதும் கோப்பாக அமைக்கவும், இது பொதுவாக /run-க்கு கீழ் உள்ள ஒரு பாதையாக இருக்கும்; அதிலிருந்து systemd PID-ஐ வாசிக்கும். அந்த PID இந்த service-க்கு உரியதுதானா என்பதையும் systemd சரிபார்க்கும். எனவே, தொடர்பில்லாத process-ஐக் குறிக்கும் பழைய கோப்பு நிராகரிக்கப்படும், நம்பப்படாது.
PIDFile= இல்லையெனில், GuessMainPID= பொருந்தும், இது இயல்பாகவே yes என்று இருக்கும். service ஒரே ஒரு process-ஆக நிலைபெற்றால் மட்டுமே இந்த ஊகம் நம்பகமானது. கையேடு இதன் வரம்பைத் தெளிவாகக் கூறுகிறது: daemon ஒன்றுக்கு மேற்பட்ட process-களைக் கொண்டிருந்தால், இந்த ஊகம் தவறாகலாம், மேலும் தோல்வியைக் கண்டறியும் திறன் நின்றுவிடும். ஒரு unit-ன் முதன்மை PID 0 என்று முடிவடையலாம், அதாவது systemd-ஆல் கண்காணிக்க எதுவுமே இருக்காது.
fork செய்யும் பெரும்பாலான daemon-களில் அவற்றை foreground-ல் வைத்திருக்கும் ஒரு switch இருக்கும். அந்த switch-ஐ Type=exec-உடன் பயன்படுத்தவும், PIDFile= வரியை நீக்கிவிடவும். குறைவான நகரும் பாகங்கள் இருந்தால், PID-ஐ இழப்பதற்கான வாய்ப்புகளும் குறையும்.
Type=oneshot என்பது நிறைவடையும் பணிகளுக்கானது
Type=oneshot ஒரு process இயங்கி முடிவடையும் வரை காத்திருக்கும். அந்த process வெளியேறிய பிறகுதான் systemd அந்த unit-ஐ 'started' நிலைக்குக் கொண்டுவரும். எனவே, மற்றொரு unit எதற்காகக் காத்திருக்க வேண்டுமோ, அதற்கு oneshot சரியான அமைப்பாகும். ஒரு unit-ல் Type= அல்லது ExecStart= குறிப்பிடப்படாதபோது, இதுவே இயல்பான (default) அமைப்பாகக் கருதப்படுகிறது.
oneshot-க்கு இரண்டு தனித்துவமான செயல்பாடுகள் உள்ளன. ஒன்றுக்கு மேற்பட்ட ExecStart= வரிகளை அனுமதிக்கும் ஒரே வகை இதுதான்; அந்த வரிகள் வரிசைக்கிரமமாக இயங்கும். மேலும், இதன் start timeout இயல்பாகவே முடக்கப்பட்டிருக்கும். எனவே, நீங்கள் நீங்களாகவே TimeoutStartSec=-ஐ அமைக்காதவரை, தொங்கிக்கொண்டிருக்கும் (hang) ஒரு oneshot காலவரையின்றி காத்திருக்கும்.
Process வெளியேறிய பிறகு, அந்த unit 'inactive' நிலைக்குத் திரும்பும். RemainAfterExit=yes, எந்த process-ம் இயங்காத நிலையிலும் அதை active-ஆக வைத்திருக்கும். இந்தப் பக்கத்தின் தொடக்கத்தில் குறிப்பிடப்பட்ட சிக்கலின் திட்டமிட்ட வடிவம் இதுதான். ஒரு unit-ன் பணி ஏதேனும் ஒன்றை இயங்க வைப்பதல்ல, மாறாக ஒரு நிலையை (state) உருவாக்கிவிட்டுச் செல்வது என்றால் (உதாரணமாக: firewall ruleset-ஐ ஏற்றுவது அல்லது container stack-ஐத் தொடங்குவது), இந்த முறை சரியானது. reboot-க்குப் பிறகு மீண்டும் வரும் Docker Compose stack-ன் பின்னணியில் இந்த முறைதான் உள்ளது. இதில் unit-ஆனது compose கட்டளையை இயக்கிவிட்டு வெளியேறிவிடும், ஆனால் அது தொடங்கிய containers தொடர்ந்து இயங்குவதால் அந்த unit 'active' நிலையிலேயே இருக்கும். ஒரு schedule-ஆல் தூண்டப்படும் unit-ம் oneshot வகையைச் சேர்ந்ததுதான். இது cron-க்கு பதிலாக systemd timer-ல் ஒரு பணியை இயக்குதல் என்பதன் மற்றொரு பாதியாகும்.
Type=notify என்பது ஒரு service எப்போது தயாராக உள்ளது என்பதைத் தெரிவிக்கப் பயன்படுகிறது
Type=notify இந்த முடிவெடுக்கும் பொறுப்பை service-க்கே வழங்குகிறது. service தனது process-ஐ முடித்து, READY=1 செய்தியை Unix socket வழியாக அனுப்பும் வரை systemd அந்த start job-ஐத் திறந்து வைத்திருக்கும். இந்த socket-ன் path, NOTIFY_SOCKET environment variable மூலம் பெறப்படுகிறது. இதற்கான C interface sd_notify(3) ஆகும், மேலும் பல servers இதை ஏற்கனவே ஆதரிக்கின்றன.
"service தொடங்கப்பட்டதா" என்ற கேள்விக்கு இதுவே சரியான பதிலாகும். simple மற்றும் exec ஆகியவை, service தனது configuration-ஐப் படிப்பதற்கு முன்போ அல்லது listening socket-ஐத் திறப்பதற்கு முன்போ "started" என்று தெரிவித்துவிடும். இதனால், அந்த service-ஐச் சார்ந்திருக்கும் மற்றொரு unit மிக விரைவாகத் தொடங்கி, தனது முதல் connection முயற்சியில் தோல்வியடையக்கூடும். notify, service தானாகவே தயாராக இருப்பதாகத் தெரிவிக்கும் தருணத்தில் மட்டுமே "started" என்று குறிப்பிடுகிறது.
systemd இந்தச் செய்தியை main process-லிருந்து மட்டுமே ஏற்கும், இதுவே NotifyAccess=main என்பதன் பொருளாகும், மேலும் Type=notify இதை உறுதிப்படுத்துகிறது. ஒருவேளை இந்தச் செய்தி child process அல்லது helper process-லிருந்து வந்தால், NotifyAccess=all-ஐ அமைக்க வேண்டும். ஒரு shell script systemd-notify --ready-ஐ அழைக்க முடியும், ஆனால் அது குறுகிய காலமே இயங்கும் ஒரு தனி process என்பதால், அதற்கு NotifyAccess=all தேவைப்படுகிறது. மேலும், செய்தி அனுப்பிய process ஏற்கனவே முடிந்துவிட்டதால், அந்தச் செய்தியைச் சரியான service-க்கு systemd-ஆல் ஒதுக்க முடியாமல் போகலாம். எனவே, அந்த protocol-ஐ நேரடியாகப் பேசும் ஒரு service மிகவும் நம்பகமானது.
இதனுடன் தொடர்புடைய இரண்டு அமைப்புகளைத் தெரிந்துகொள்வது பயனுள்ளது. Type=notify-reload, systemd 253 பதிப்பிலிருந்து கிடைக்கிறது; இது இதே handshake முறையை reloads-க்கும் நீட்டிக்கிறது. இதனால், signal அனுப்பப்பட்டவுடன் திரும்புவதற்குப் பதிலாக, service தனது reload பணி முடிந்துவிட்டதாகத் தெரிவிக்கும்போது systemctl reload திரும்பும். WatchdogSec=, ஒரு notifying service-ஐ குறிப்பிட்ட கால இடைவெளியில் keep-alive செய்தியை அனுப்பச் சொல்கிறது; ஒருவேளை அந்த காலக்கெடுவை service தவறவிட்டால், அதை systemd ஒரு தோல்வியாகக் கருதும்.
Type=dbus மற்றும் Type=idle
Type=dbus என்பது, system மற்றும் desktop services தங்களுக்குள் தொடர்புகொள்ளப் பயன்படுத்தும் D-Bus-ல், ஒரு service தனது பெயரைப் பதிவு செய்யும் வரை காத்திருக்கும். இதற்கு BusName= தேவைப்படுகிறது, மேலும் BusName= அமைக்கப்பட்டவுடன் இதுவே இயல்புநிலை (default) ஆகிவிடும். ஒரு service உண்மையாகவே bus name-ஐப் பதிவு செய்தால் மட்டுமே இதைப் பயன்படுத்தவும்.
Type=idle என்பது simple போலவே செயல்படும், ஆனால் வரிசையில் உள்ள பணிகள் (queued jobs) முடிவடையும் வரை இது நிரலை இயக்குவதைத் தாமதப்படுத்தும்; இதற்கு ஐந்து வினாடிகள் காலவரம்பு உண்டு. boot-ன் போது வெளியாகும் console தகவல்கள், status செய்திகளுடன் கலந்துவிடாமல் இருக்கவே இது உருவாக்கப்பட்டது. இது ஒரு வரிசைப்படுத்தும் கருவி (ordering tool) அல்ல, சாதாரண service-களுக்கு இதைப் பயன்படுத்தக்கூடாது.
wrapper script ஏன் systemd-ஐ தவறான PID-ல் நிறுத்துகிறது
இந்த அறிகுறிகளை உருவாக்கும் கட்டமைப்பு இதோ.
[Service]
Type=simple
ExecStart=/opt/app/run.sh#!/bin/bash
export APP_ENV=production
/opt/app/bin/server --config /etc/app.yaml &
/opt/app/bin/exporter --port 9101systemd, shell-ஐ முதன்மை PID-ஆகப் பதிவு செய்கிறது. exporter foreground-ல் இயங்கும்போது shell உயிர்ப்புடன் இருக்கும். server செயலிழந்தால், shell அதை கவனிக்காது; எனவே முதன்மை PID இன்னும் உயிர்ப்புடன் இருக்கும், unit இன்னும் active நிலையிலேயே இருக்கும், மேலும் Restart= செயல்படுவதற்கு ஏதுமில்லை. இரண்டு process-களும் unit-ன் cgroup-ல் தொடர்ந்து இருப்பதால், systemctl stop இன்னும் சரியாகவே cleanup செய்கிறது. மேற்பார்வை (supervision) மட்டுமே பாதிக்கப்பட்டுள்ளது, cleanup அல்ல.
இந்தச் சிக்கலைச் சரிசெய்வது, அந்த unit-ல் உண்மையில் எத்தனை நீண்டகால process-கள் இயங்குகின்றன என்பதைப் பொறுத்தது.
ஒரே ஒரு process இருந்தால், shell-க்கு பதிலாக அதை மாற்றவும்.
#!/bin/bash
export APP_ENV=production
exec /opt/app/bin/server --config /etc/app.yamlexec, shell-ஐ குறிப்பிட்ட நிரலால் (program) இடமாற்றம் செய்து அதே PID-ஐத் தக்கவைக்கும், எனவே systemd பதிவு செய்த PID இப்போது daemon-க்கு உரியதாகிவிடும். அதைவிடச் சிறந்தது, wrapper-ஐ நீக்குவதாகும். Environment= மற்றும் EnvironmentFile= மாறிகளை (variables) எடுத்துச் செல்லும், ExecStartPre= setup படியைக் கையாளும்; எனவே systemd நேரடியாக daemon-ஐத் தொடங்கி, அதன் PID-ஐ உருவாக்கத்தின்போதே தெரிந்துகொள்ள முடியும்.
இரண்டு process-கள் இருந்தால், எந்த ஒரு PID-ம் அந்த unit-ஐ முழுமையாகப் பிரதிநிதித்துவப்படுத்தாது. அவற்றை இரண்டு unit-களாகப் பிரித்து, After= மற்றும் Wants= மூலம் வரிசைப்படுத்தவும். ஒரு process-க்கு ஒரு unit என்ற அமைப்பையே systemd சிறப்பாக மேற்பார்வையிடும்; ஒவ்வொரு process-க்கும் தனித்தனி restart நடத்தை (behaviour) கிடைக்க இதுவே ஒரே வழியாகும்.
ExitType=cgroup மாற்றங்கள் என்றால் என்ன
ExitType= என்பது systemd 250 பதிப்பில் சேர்க்கப்பட்டது. இதற்கான இயல்புநிலை மதிப்பு main ஆகும்: முதன்மை process வெளியேறியவுடன், அந்த unit நிறுத்தப்பட்டதாகக் கருதப்படும். ExitType=cgroup அமைப்பைப் பயன்படுத்தினால், அதன் cgroup-ல் ஏதேனும் ஒரு process இயங்கிக்கொண்டிருக்கும் வரை அந்த unit இயங்குவதாகவே கருதப்படும்.
[Service]
Type=simple
ExitType=cgroup
ExecStart=/opt/app/launcherஇது ஒரு குறிப்பிட்ட சிக்கலைத் தீர்க்கிறது. ஒரு launcher, உண்மையான பணியைத் தொடங்கிவிட்டு வெளியேறினால், ExitType=main அமைப்பின் கீழ் systemd அந்த unit-ஐ நிறுத்திவிட்டு, எஞ்சியிருக்கும் process-களைக் கொன்றுவிடும். ExitType=cgroup அமைப்பைப் பயன்படுத்தினால், அந்த unit முழு குழுவையும் கண்காணிக்கும்.
இது எதைத் தீர்க்காது என்பதில் தெளிவாக இருக்க வேண்டும். ExitType=cgroup என்பது குறைந்தது ஒரு process இயங்கும் வரை unit-ஐ active நிலையில் வைத்திருக்கும். எனவே, இரண்டு daemons-ஐக் கொண்ட ஒரு unit-ல் ஒன்று இறந்தாலும், அது active நிலையிலேயே இருக்கும். இது launcher சிக்கலை மட்டுமே சரிசெய்கிறது. இது பல தனித்தனி process-களைக் கண்காணிக்கும் ஒரு supervisor-ஆக மாறாது. மேலும், ExitType=-ஐ Type=oneshot-உடன் இணைக்க முடியாது.
வளக் கணக்கீடு (resource accounting) cgroup-ல் தான் நடைபெறுகிறது. எனவே, முதன்மை PID-ஐப் பற்றி Type= என்ன கூறினாலும், MemoryMax= மற்றும் CPUQuota= போன்ற வரம்புகள் அந்த unit உருவாக்கிய அனைத்து process-களுக்கும் பொருந்தும். இது குறித்த கூடுதல் விவரங்கள் systemd மூலம் ஒரு service-ன் memory மற்றும் CPU-ஐக் கட்டுப்படுத்துதல் பகுதியில் உள்ளன.
systemd உண்மையில் கண்காணிக்கும் process-ஐக் கண்டறிவது எப்படி
நீங்கள் பிழைத்திருத்தம் (debugging) செய்யும் unit-ல் வரிசையாக இதைப் பின்பற்றவும். systemd எதை ஏற்றியது என்பதை முதலில் படியுங்கள், பிறகு அது எதைக் கண்காணிக்கிறது என்று பாருங்கள், இறுதியாக அதை process table-உடன் ஒப்பிட்டுப் பாருங்கள்.
systemctl cat app.service
systemctl show -p Type,ExitType,GuessMainPID,PIDFile,MainPID,RemainAfterExit app.servicesystemctl cat கட்டளையானது unit file மற்றும் அதற்குப் பொருந்தும் அனைத்து drop-in கோப்புகளையும் சேர்த்து அச்சிடும். எனவே, நீங்கள் திருத்தியதாக நினைக்கும் கோப்பை விட, systemd எதை ஏற்றுகிறதோ அதைத்தான் நீங்கள் படிக்கிறீர்கள். systemctl show கட்டளையானது, நீங்கள் குறிப்பிடாத default மதிப்புகள் உட்பட, நடைமுறையில் உள்ள அனைத்து மதிப்புகளையும் அச்சிடும். அடுத்த கட்டத்திற்குச் செல்லும் முன் MainPID-ன் மதிப்பை குறித்துக்கொள்ளுங்கள்.
systemd-cgls --unit=app.service
ps -o pid,ppid,stat,etime,args -p "$(systemctl show -p MainPID --value app.service)"systemd-cgls கட்டளையானது அந்த unit-ன் cgroup-ல் உள்ள அனைத்து process-களையும் பட்டியலிடும். ps வரியானது systemd கண்காணிக்கும் ஒற்றை process-ஐ விவரிக்கும். இரண்டையும் சேர்த்துப் படியுங்கள். MainPID-ன் மதிப்பு 0 எனில், systemd கண்காணிப்பதற்கு எந்த process-ம் இல்லை என்று பொருள். cgroup-ல் உங்கள் daemon இருக்கும்போது, MainPID ஒரு shell-ஐக் காட்டினால், அது மேலே குறிப்பிட்ட wrapper சூழலாகும். நீங்கள் எதிர்பார்த்ததை விட அதிகமான process-கள் cgroup-ல் இருந்தால், அங்கு ஒரு launcher அல்லது forking daemon செயல்படுகிறது என்று அர்த்தம்.
systemctl status app.service
journalctl -u app.service -bsystemctl status கட்டளையானது state வரியையும் cgroup மரத்தையும் ஒன்றாக அச்சிடும், எனவே இது பெரும்பாலும் இரண்டு கேள்விகளுக்கும் ஒரே நேரத்தில் பதிலளிக்கும். -b கொடியுடன் கூடிய journalctl -u கட்டளையானது, இந்த boot-ல் அந்த unit-க்காக systemd பதிவு செய்த start மற்றும் stop நிகழ்வுகளையும், அது கண்ட exit code-களையும் காட்டும். daemon தனது சொந்த log கோப்பில் எழுதினால், அதையும் படியுங்கள்; ஏனெனில் systemd தனக்குக் கிடைத்த தகவல்களை மட்டுமே பதிவு செய்ய முடியும்.
நீங்கள் Type=-ஐ மாற்றும்போது, reload மற்றும் restart செய்யவும்.
systemd-analyze verify /etc/systemd/system/app.service
sudo systemctl daemon-reload
sudo systemctl restart app.servicesystemd-analyze verify கட்டளையானது கோப்பைப் பகுப்பாய்வு செய்து, ஏற்றுக்கொள்ள முடியாத அமைப்புகளைத் தெரிவிக்கும். daemon-reload கட்டளையானது வட்டில் உள்ள unit கோப்புகளை மீண்டும் படிக்க systemd-ஐத் தூண்டும். மாற்றப்பட்ட Type= ஏற்கனவே இயங்கிக்கொண்டிருக்கும் unit-க்கு உடனடியாகப் பொருந்தாது, எனவே restart செய்வது கட்டாயமாகும், விருப்பத்தேர்வு அல்ல.
பிறகு மாற்றத்தைச் சோதிக்கவும். systemd-cgls மூலம் நீங்கள் கவனிக்க வேண்டிய process-ன் PID-ஐ எடுத்து அதை kill செய்யவும். உடனடியாக systemctl is-active app.service கட்டளையை இயக்கவும். Type= சரியாக இருந்தால், அந்த unit active நிலையிலிருந்து வெளியேறும். அது இன்னும் active நிலையிலேயே இருந்தால், systemd வேறொன்றைக் கண்காணித்துக் கொண்டிருக்கிறது என்று பொருள்.
எந்த systemd service Type=-ஐ பயன்படுத்த வேண்டும்
- foreground-ல் இயங்கும் ஒரு program:
Type=exec. - readiness notification-ஐ ஆதரிக்கும் ஒரு program:
Type=notify, மேலும் reloads-ஐயும் உறுதிப்படுத்தினால்notify-reload. - background-க்குச் செல்ல விரும்பும் ஒரு daemon:
Type=forkingஉடன்PIDFile=, அல்லது அதன் foreground switch-ஐType=execமூலம் பயன்படுத்தவும். - வேலை செய்துவிட்டு வெளியேறும் ஒரு script:
Type=oneshot, மேலும் ஒரு நிலையை (state) விட்டுச் செல்வது நோக்கமாக இருந்தால்RemainAfterExit=yes. - அதன் children தொடர்ந்து இயங்கும்போது வெளியேறும் ஒரு launcher:
Type=simpleஉடன்ExitType=cgroup.
ஒரு third party daemon-க்கு எது தேவை என்பதில் உங்களுக்கு சந்தேகம் இருந்தால், முதலில் அதன் packaged unit file-ஐப் படிக்கவும். விநியோகஸ்தர் வழங்கிய unit-ல் systemctl cat-ஐ இயக்குவது, upstream தேர்ந்தெடுத்த Type=-ஐக் காட்டும்; அந்தத் தேர்வு உங்களை விட அதிகமானவர்களால் சோதிக்கப்பட்டது.
FAQ
process இறந்த பிறகும் எனது systemd unit ஏன் active நிலையில் உள்ளது?
systemd முதன்மை process-ஆகக் கருதும் process இன்னும் இயங்கிக்கொண்டிருப்பதால் இவ்வாறு நிகழ்கிறது. unit-ன் cgroup-ல் உள்ள அனைத்து process-களையும் கண்காணிப்பதற்குப் பதிலாக, Type=-ன் படி தேர்ந்தெடுக்கப்பட்ட ஒரு PID-ஐ மட்டுமே systemd கண்காணிக்கிறது. Type=simple மூலம் தொடங்கப்பட்ட wrapper script பெரும்பாலும் இதற்குக் காரணமாகிறது: shell தான் முதன்மை PID-ஆக இருக்கும், எனவே shell பின்னணியில் இயக்கும் daemon வெளியேறினாலும் unit active நிலையிலேயே இருக்கும். systemctl show -p MainPID app.service-ஐ இயக்கி, பின் systemd-cgls --unit=app.service மூலம் unit-ன் cgroup-ஐப் பட்டியலிட்டு இரண்டையும் ஒப்பிட்டுப் பார்க்கவும்.
Type=simple மற்றும் Type=exec ஆகியவற்றிற்கு இடையே உள்ள வேறுபாடு என்ன?
Type=simple-ல், binary இயக்கப்படுவதற்கு முன்பே, systemd process-ஐ உருவாக்கியவுடன் unit தொடங்கிவிட்டதாகக் கருதும். எனவே, ExecStart=-ல் தவறான path இருந்தால், start job வெற்றிகரமாக முடிந்ததாகக் காட்டிவிட்டு, பின் தோல்வியடையும். Type=exec, execution வெற்றிகரமாக முடியும் வரை காத்திருக்கும், எனவே தோல்வி start job-லேயே தெரிவிக்கப்படும். இவை இரண்டுமே ஒரே process-ஐத்தான் முதன்மை PID-ஆகக் கருதுகின்றன. Type=exec-க்கு systemd 240 அல்லது அதற்குப் பிந்தைய பதிப்பு தேவை.
Type=forking பயன்படுத்தும்போது இன்னும் PIDFile= தேவைப்படுமா?
ஆம், daemon அதை உருவாக்கும்போதெல்லாம் தேவைப்படும். அது இல்லையெனில், systemd GuessMainPID=-க்குத் திரும்பும்; இது ஒரு ஊகம் மட்டுமே, ஒரே ஒரு process-ஆக இயங்கும் service-களுக்கு மட்டுமே இது நம்பகமானது. இந்த ஊகம் தவறாகவோ அல்லது சாத்தியமற்றதாகவோ இருக்கும்போது, அந்த unit-க்கான தோல்வி கண்டறிதல் மற்றும் தானியங்கி மறுதொடக்கம் (automatic restarting) வேலை செய்யாது. PIDFile=-ஐ daemon எழுதும் சரியான path-க்குக் குறிவைக்கவும், இது பொதுவாக /run-ன் கீழ் இருக்கும்.
RemainAfterExit=yes-ஐ எப்போது பயன்படுத்த வேண்டும்?
ஒரு process-ஐத் தொடர்ந்து இயக்குவதை விட, system-ன் நிலையை மாற்றுவதே unit-ன் நோக்கமாக இருக்கும்போது இதைப் பயன்படுத்த வேண்டும். firewall விதிகளை ஏற்றும் அல்லது container stack-ஐத் தொடங்கும் ஒரு Type=oneshot unit, தனது வேலை முடிந்ததும் வெளியேறிவிடும். RemainAfterExit=yes இல்லையெனில், unit inactive நிலைக்குச் சென்றுவிடும்; இதனால் systemctl stop-க்கு நிறுத்த எதுவுமிருக்காது, மேலும் ExecStop= cleanup-ஐ இயக்க வழியும் இருக்காது. இதைப் பயன்படுத்தினால், process-கள் இல்லாவிட்டாலும் unit active நிலையிலேயே இருக்கும், இதுவே இங்கு எதிர்பார்க்கப்படும் செயல்பாடு.
Type=-ஐ மாற்றினால் daemon-reload தேவையா?
ஆம், அத்துடன் unit-ஐ restart செய்வதும் அவசியம். systemctl daemon-reload, disk-ல் உள்ள unit கோப்புகளை systemd மீண்டும் படிக்கச் செய்யும், ஆனால் இயங்கிக்கொண்டிருக்கும் instance அது தொடங்கியபோது இருந்த Type=-ஐயே வைத்திருக்கும். சோதிப்பதற்கு முன் sudo systemctl daemon-reload-ஐ இயக்கி, பின் sudo systemctl restart app.service-ஐ இயக்கவும்; இல்லையெனில் நீங்கள் பழைய கண்காணிப்பு முறையையே (supervision behaviour) கவனித்துக் கொண்டிருப்பீர்கள்.