- Nitro एक अत्यंत छोटा प्रोसेस सुपरवाइज़र और init सिस्टम है, जिसे embedded, server, desktop और container—सभी पर लागू किया जा सकता है
- यह सिस्टम स्टेट को केवल RAM में संग्रहीत करता है, इसलिए read-only file system पर भी बिना दिक्कत काम करता है, और तेज़ व कुशल event-based design प्रदान करता है
- कॉन्फ़िगरेशन का तरीका सरल script directory structure है, जिससे जटिल config file या अतिरिक्त build process के बिना service management संभव है
- Parameterized services, मज़बूत restart, और हर service के लिए विश्वसनीय logging जैसी container और embedded environment के लिए अनुकूलित सुविधाएँ देता है
- nitroctl tool के ज़रिए remote control, signal-based behavior control आदि के माध्यम से उच्च लचीलापन और नियंत्रण सुनिश्चित करता है
अवलोकन
Nitro Linux पर pid 1 के रूप में भी इस्तेमाल किया जा सकने वाला अत्यंत छोटा प्रोसेस सुपरवाइज़र है
इसके प्रमुख उपयोग क्षेत्र इस प्रकार हैं
- embedded, desktop, server आदि विभिन्न उपयोगों वाली Linux मशीनों के लिए init
- Linux initramfs का init
- Docker/Podman/LXC/Kubernetes आदि container environment का init
- POSIX सिस्टम पर बिना विशेषाधिकार के चलने वाला supervision daemon
कॉन्फ़िगरेशन में directory-based script structure का उपयोग होता है, और इसका default location /etc/nitro है
आवश्यकताएँ
- kernel में Unix socket समर्थन आवश्यक
tmpfsया लिखने योग्य/rundirectory आवश्यक
अन्य सिस्टमों की तुलना में फायदे
- सभी state information केवल RAM में रखी जाती है, इसलिए read-only root file system पर भी किसी अलग तरकीब के बिना काम करता है
- event-based, polling-free operation के कारण बेहतर दक्षता
- runtime के दौरान dynamic memory allocation नहीं होता
- file descriptor अनंत रूप से consume नहीं होते
- केवल एक self-contained binary (वैकल्पिक रूप से control binary अतिरिक्त) की आवश्यकता होती है
- config file conversion और compilation की जरूरत नहीं; service बस script वाली एक सरल directory होती है
- service restart और logging chain का समर्थन
- system clock सटीक न होने पर भी सामान्य रूप से काम करता है
- FreeBSD पर
/etc/ttysके माध्यम से चलाया जा सकता है - musl libc के साथ अत्यंत छोटा static binary बनाया जा सकता है
सेवा प्रबंधन
-
हर service directory (default रूप से
/etc/nitroके भीतर) में निम्न फ़ाइलें हो सकती हैंsetup: service शुरू होने से पहले चलने वाली (वैकल्पिक) script; केवल सफल exit (0) पर ही service शुरू हो सकती हैrun: service execution script; जब तक यह समाप्त नहीं होती, service को सक्रिय माना जाता है; अगर यह implement न हो तो one-shot service माना जाता हैfinish:runके समाप्त होने के बाद चलने वाली (वैकल्पिक) script, जिसे exit status और signal value argument के रूप में दिए जाते हैंlog: किसी अन्य service directory की ओर इशारा करने वाला symbolic link;runका output उस service के input में pipe किया जाता है, जिससे logging chain का उपयोग संभव हैdown: यदि यह फ़ाइल मौजूद है, तो nitro डिफ़ॉल्ट रूप से इस service को शुरू नहीं करता- यदि directory name
'@'पर समाप्त होता है, तो इसे अनदेखा किया जाता है और parameter service के रूप में इस्तेमाल किया जा सकता है - service name 64 अक्षरों से छोटा होना चाहिए, और इसमें
/,,, या newline character शामिल नहीं हो सकते
-
runit की
chpstutility,runscript लिखने में उपयोगी है
विशेष सेवाएँ
LOG: उन सभी services के लिए default logging service जिनमें log link नहीं हैSYS:SYS/setupसभी services के शुरू होने से पहले चलता है, जिससे ordered service startup लागू किया जा सकता हैSYS/finish: पूरे shutdown चरण में प्रवेश से पहले चलता हैSYS/final: सभी processes समाप्त होने के बाद चलता हैSYS/fatal: fatal error होने पर exit के बजाय चलाया जाता है (यदि मौजूद हो)SYS/reincarnate: shutdown के बजाय चलाया जाता है, जैसे initramfs को दोबारा लागू करने जैसे उपयोगों के लिए
Parameterized services
'@'पर समाप्त होने वाली service directory को nitro अनदेखा करता है, लेकिन symbolic link याnitroctlcommand के माध्यम से इसे सीधे निर्दिष्ट किया जा सकता है'@'के बाद का parameter हर script को पहले argument के रूप में दिया जाता है- उदाहरण: यदि
agetty@/runऔरagetty@tty1symbolic link मौजूद हों, तोagetty@/run tty1चलाया जाता है nitroctl up agetty@tty2देने परagetty@/run tty2चलाया जा सकता है (चाहे directory मौजूद हो या नहीं)
- उदाहरण: यदि
ऑपरेशन मोड
- पूरा lifecycle boot, service execution (supervision), shutdown—इन तीन चरणों में बना है
- boot: यदि विशेष service
SYSमौजूद हो, तोsetupसे शुरू किया जाता है; इसके बाद सभी non-down services चलाई जाती हैं - यदि कोई service समाप्त हो जाए, तो उसे restart किया जाता है; लेकिन यदि हाल का restart बहुत तेज़ी से हुआ हो तो 2 सेकंड प्रतीक्षा की जाती है
nitroctl RebootयाShutdownसे shutdown signal भेजा जा सकता है- इस स्थिति में
SYS/finish→ सभी services को SIGTERM (अधिकतम 7 सेकंड प्रतीक्षा) → SIGKILL →SYS/final→ shutdown sequence
- इस स्थिति में
- container या unprivileged supervisor के उपयोग में केवल processes बंद किए जाते हैं
- boot: यदि विशेष service
nitroctl के माध्यम से नियंत्रण
- nitroctl CLI tool के ज़रिए दूर से nitro को नियंत्रित किया जा सकता है
कमांड उदाहरण:
- list: service सूची, state, PID, uptime, अंतिम exit status दिखाता है
- up/down/start/stop/restart: service start·stop·restart आदि नियंत्रण
- signal भेजना: p(SIGSTOP), c(SIGCONT), h(SIGHUP), a(SIGALRM), i(SIGINT), q(SIGQUIT), 1(SIGUSR1), 2(SIGUSR2), t(SIGTERM), k(SIGKILL)
- pidof: निर्दिष्ट service का PID दिखाता है
- rescan: service directory को फिर से पढ़ता है, और जोड़ी/हटाई गई services को लागू करता है
- Shutdown/Reboot: पूरे सिस्टम को बंद/रीबूट करता है
signal के माध्यम से नियंत्रण
- nitro process को सीधे signal भेजकर नियंत्रण किया जा सकता है
- SIGHUP: service rescan
- SIGINT: reboot
- SIGTERM: shutdown (यदि nitro pid 1 नहीं है)
Linux में init के रूप में nitro
- Nitro एक self-contained binary है जो Linux pid 1 के रूप में सीधे boot हो सकता है
- आवश्यकता होने पर
/dev,/runको mount करता है, और अन्य कार्यSYS/setupमें संभाले जाते हैं - Ctrl-Alt-Del event पर सुव्यवस्थित reboot trigger करता है
Docker container में init के रूप में Nitro का उपयोग
- Nitro को static build करके container में आसानी से शामिल किया जा सकता है
- default socket path का उपयोग करने के लिए container में
/runमौजूद होना चाहिए - यदि control socket को bind mount किया जाए, तो बाहर से nitroctl द्वारा remote control संभव है
FreeBSD पर Nitro
/etc/ttysमें नीचे की पंक्ति जोड़कर FreeBSD init से nitro को supervise कराया जा सकता है/etc/nitro "/usr/local/sbin/nitro" "" on
लेखक
- Leah Neukirchen leah@vuxu.org
आभार
- daemontools, freedt, runit, perp, s6 जैसे मौजूदा process supervision systems के विस्तृत विश्लेषण के आधार पर विकसित
लाइसेंस
- 0BSD लाइसेंस (विस्तृत जानकारी के लिए LICENSE फ़ाइल देखें)
1 टिप्पणियां
Hacker News टिप्पणियाँ
मैं runit के साथ तुलना देखना चाहूँगा। runit बेहद minimal होते हुए भी लगभग पूर्ण init system है। control directory, declarative नहीं होने वाली dependencies, मिलती-जुलती script संरचना, logging approach आदि में काफी समानताएँ हैं। description page में भी runit का संक्षेप में ज़िक्र है और chpst utility साथ में इस्तेमाल करने की सिफारिश की गई है। फर्क के तौर पर, एक ही service directory से कई समान processes (जैसे: agetty) को parameterize करके manage करने की संरचना अच्छी लगती है। reboot या shutdown को एक single binary (
nitroctl) से सीधे चलाया जा सकता है। दूसरी तरफ runit कई binaries वाली संरचना हैपिछले साल जब मैंने runit से processes manage कर रहे आख़िरी servers retire किए, तो थोड़ी कसक हुई। करीब 15 साल पहले जब मैंने पहली बार खुद runit services लिखी थीं, तब मुझे लगा था कि Linux में services manage करने का यही standard तरीका है। फिर 5 साल Linux से दूर रहने के बाद लौटा तो systemd default बन चुका था, और उसके बारे में कई बार बुरी बातें सुनी थीं, लेकिन धीरे-धीरे समझ आया कि उसमें काफ़ी विकृत किस्म की नाराज़गी भी शामिल है। अभी मैं reptile vivarium में Pi Zero पर camera और temperature data streaming service चला रहा हूँ, और उसे systemd से set up करना बेहद आसान था। OpenSuse desktop और काम के laptop पर भी systemd के साथ तरह-तरह की services आसानी से चला पाया। अब लगता है, ‘कोई standard होना अपने आप में अच्छी बात है’
runit और nitro की एक ठीक-ठाक minimal तुलना Leah Neukirchen की 2024 में जारी की गई presentation slides (PDF) में है
https://leahneukirchen.org/talks/#nitroyetanotherinitsy
Leah Neukirchen Void Linux community में काफ़ी सक्रिय हैं। मुझे लगता है यह project Void से काफ़ी जुड़ा रहेगा। अच्छा होगा अगर Void में nitro इस्तेमाल करने के तरीक़े पर थोड़ा और आधिकारिक लेख लिखा जाए
मैं जानना चाहता हूँ कि “declarative dependencies नहीं हैं” क्या इसे फ़ायदे के रूप में देखा जा रहा है। systemd को init के रूप में criticize करने वाली राय बहुत सुनी है, लेकिन declarative design को ही criticize करना कम ही देखा है। इसके पीछे कोई वजह है तो विस्तार से सुनना चाहूँगा
Void Linux में runit से परिचय हुआ और init system के रूप में उसे ठीक से इस्तेमाल कर रहा हूँ, लेकिन UI और documentation की कमी खलती है। खासकर logging setup सच में मुश्किल था। मैं ऐसा विकल्प आज़माना चाहूँगा जो उतना ही simple हो, लेकिन defaults ज़्यादा sensible हों, UI ज़्यादा intuitive हो, और documentation बेहतर हो
जब भी container में init system चलाने की बात देखता हूँ, हमेशा दुविधा होती है। कई बार यह सचमुच ज़रूरत के हिसाब से design किया जाता है, लेकिन कई बार चीज़ें उल्टा ज़रूरत से ज़्यादा complex हो जाती हैं (खासकर Kubernetes, cloud environments में, जहाँ असल में separation design और बेहतर होनी चाहिए थी)। कभी-कभी लगता है कि ‘सब लोग वैसे ही कर रहे हैं’ वाली स्थिति बन गई है। तब समझ नहीं आता कि ‘इसे बेहतर बनाएँ’ कहते हुए समस्या को और फैलाना अच्छा है, या लोगों को existing solutions के साथ ज़ोरदार तरीके से fail होने देना बेहतर है
मेरा मानना है कि application containers को Unix philosophy ‘एक काम करो, और वही अच्छे से करो’ का पालन करना चाहिए। लेकिन अगर किसी भी वजह से container के अंदर
forkहोता है, तो PID 1 पर एक असली init होना चाहिएrobotics में मेरे अनुभव के हिसाब से, कई containers असल में ऐसे जटिल systems होते हैं जो पहले bare metal पर चलते थे और बाद में container में लाए गए। processes के बीच unstructured RPC बहुत होता है, इसलिए उन्हें कई अलग-अलग containers में तोड़ने का ख़ास लाभ नहीं मिलता। monolithic app container के अंदर कई processes चलाने के लिए supervisor, runit, systemd, tmux तक तरह-तरह के options व्यवहार में इस्तेमाल होते हैं
मैंने Fly.io, Render, Google Cloud Run जैसी ऐसी hosting इस्तेमाल की है जहाँ billing container unit पर होती है। कीमत की वजह से अक्सर एक container में कई processes चलाने पड़ते हैं
NixOS की नई feature modular-services अब Nixpkgs में शामिल हो गई है। इससे NixOS को नए init system या नए kernel पर port करना काफ़ी आसान हो जाएगा, इसलिए मुझे लगता है कि अभी nitro जैसे experiments आज़माने का अच्छा समय है
मैं Chimera Linux में इस्तेमाल हो रहे dinit और nitro की तुलना देखना चाहूँगा। readme को जल्दी से देखने पर लगा कि service dependency management अभी शायद नहीं है
dinit: https://github.com/davmac314/dinit
Nitro services की dependencies को declarative तरीके से handle नहीं करता। एक command से services के बीच dependency graph को सुंदर ढंग से देख पाना संभव नहीं है। लेकिन अगर setup script में ज़रूरी services को declare कर दिया जाए, तो यह जाँचता है कि वे services चल रही हैं या नहीं, और अपने आप wait करके retry करता है। dependency graph देखने के लिए
grepजैसी चीज़ों से scripts खुद लिखनी पड़ेंगी। दूसरी तरफ, जब कोई service मरती है तो dependent services को chain में सही तरह से नीचे लाना भूल जाना आसान है, और nitro अपने आप ऐसा detect करने का कोई सुविधाजनक तरीका नहीं देतामैंने Artix Linux में dinit इस्तेमाल किया था, और वह सचमुच lightweight और प्रभावशाली लगा
Artix FAQ: https://artixlinux.org/faq.php
ऐसे low-level projects हमेशा दिलचस्प लगते हैं। मुझे यह बात पसंद आई कि systemd ने पारंपरिक SysV·POSIX ढाँचे से आगे बढ़कर Linux kernel-specific features का अच्छा इस्तेमाल किया। लेकिन मैं चाहता हूँ कि बात वहीं खत्म न हो, और नई ideas व innovation आते रहें। हाल ही में मैंने manufacturing automation के लिए एक setup बनाया, जिसमें UEFI firmware से सीधे netboot होने वाले Linux kernel में Go में खुद लिखा हुआ एक single init binary ही embed किया गया था। अपने लाए हुए code और high-level language से पूरा OS environment control करने में यह आज़ादी बेहद अच्छी लगी, क्योंकि तरह-तरह के subprocesses और ढेर सारी text configuration files manage करने की ज़रूरत नहीं रही
करीब 13 साल पहले मुझे C में खुद init system बनाने का अनुभव हुआ था। इसमें अनुमान से कहीं ज़्यादा मेहनत लगी, और इसका इस्तेमाल low-performance hardware पर GUI और backend को जल्दी boot कराने के लिए किया गया था। यह एक मज़ेदार programming exercise थी, लेकिन बाद में लगा कि शायद पहले से ऐसे solutions मौजूद रहे होंगे। उसी कंपनी में एक सहकर्मी ने एक और init बना लिया, इसलिए मेरा पहला version लगभग सिर्फ़ libc पर निर्भर हल्का सिस्टम था, जबकि उसके version में libevent आधारित ज़्यादा advanced features थे
यह बात थोड़ी खटकती है कि इसका नाम और functionality AWS Nitro से टकराते हैं
https://docs.aws.amazon.com/whitepapers/latest/security-design-of-aws-nitro-system/the-nitro-system-journey.html
सिर्फ़ नाम एक जैसा है; init system और hypervisor बुनियादी तौर पर पूरी तरह अलग चीज़ें हैं
मुझे नहीं लगता कि इससे कोई बड़ी समस्या होगी। एक तरफ ऐसा init system है जिसे कोई भी इस्तेमाल कर सकता है, और AWS Nitro एक KVM fork है जो कंपनी के अंदर ही इस्तेमाल होता है
मैं जानना चाहूँगा कि s6 की तुलना में nitro कैसा है। हाल में मैंने Docker container में s6 के साथ init system configure किया था, लेकिन s6-overlay के साथ काफ़ी files हाथ से बनानी पड़ीं और यह अपेक्षा से कम intuitive लगा
tini भी देख सकते हैं: https://github.com/krallin/tini
Distrust में rust में 500 lines से कम का एक बेहद simple init system खुद लिखा गया है, और security-critical enclave environments में कुछ clients उसे production में इस्तेमाल कर रहे हैं। सिर्फ़ rust standard library इस्तेमाल होने की वजह से audit करना बहुत आसान था
https://git.distrust.co/public/nit
nitसे 33% बड़ा है), लेकिन readme में सिर्फ़ build करने का तरीका है; actual interface या काम करने के तरीके की कोई व्याख्या नहीं हैdependencies specify नहीं कर सकते, user/group setting नहीं है, order हाथ से तय करना पड़ता है, parallel service execution नहीं है, resource management नहीं है। ऐसी चीज़ें न हों तो मैं इसे init system नहीं कहूँगा। यह बस एक bare-bones process supervisor है