5 पॉइंट द्वारा GN⁺ 19 시간 전 | 1 टिप्पणियां | WhatsApp पर शेयर करें
  • systemd timers cron का एक व्यावहारिक विकल्प हैं, जो शेड्यूल के अनुसार .service जैसी units चलाते हैं और history, output, तथा environment management को अधिक स्पष्ट बनाते हैं
  • पारंपरिक cron की कमज़ोरियाँ हैं: अस्पष्ट $PATH, आसानी से गुम हो जाने वाला stdout/stderr, ट्रैक करना कठिन execution history, और पढ़ने में मुश्किल schedule syntax
  • timers, उसी stem वाली .timer और .service को जोड़ते हैं, और OnCalendar, OnBootSec, OnUnitActiveSec से समय या event-आधारित execution को व्यक्त करते हैं
  • systemd-analyze calendar और systemctl list-timers से time expressions और अगला execution time देखा जा सकता है, और WakeSystem= suspend अवस्था से भी सिस्टम को जगा सकता है
  • RandomizedOffsetSec और FixedRandomDelay= एक साथ होने वाले execution peaks को कम करते हैं, और Persistent= inactive रहने के दौरान छूटे हुए runs को online होते ही पूरा करता है

cron के विकल्प के रूप में systemd timers क्यों इस्तेमाल करें

  • cron job शब्द का व्यापक उपयोग उस computing मूलभूत तत्व के लिए भी होता है जो असली cron daemon न होने पर भी “इसे हर दिन चलाओ”, “उसे हर महीने चलाओ” जैसी schedule-आधारित jobs चलाता है
  • systemd timer एक systemd unit है जो तय schedule पर किसी दूसरी unit, आम तौर पर .service, को चलाती है, और यह पारंपरिक cron daemon का functional replacement हो सकती है
  • पारंपरिक cron में कुछ व्यावहारिक कमज़ोरियाँ हैं
    • अस्पष्ट $PATH configuration की वजह से script execution के परिणाम का अनुमान लगाना कठिन होता है
    • stdout और stderr output अक्सर ब्लैकहोल में चला जाता है या host की mail system में भेज दिया जाता है
    • execution history को ट्रैक और query करना कठिन होता है
    • 01,31 04,05 1-15 1,6 * जैसी schedule syntax इंसानों के लिए पढ़ने में आसान या intuitive नहीं होती
  • systemd timers इन समस्याओं को कम करते हैं और cron-style expressions जैसी calendar configuration भी देते हैं

बुनियादी संरचना: service और timer

  • systemd timer को चलाने के लिए कोई target चाहिए, और .service unit को तार्किक रूप से script की तरह समझा जा सकता है
  • उदाहरण के लिए, अगर /etc/systemd/system/roulette.service में यह unit रखी जाए, तो 10 में 1 संभावना के साथ कंप्यूटर बंद करने वाली service install हो जाएगी
[Unit]
Description=1 in 10 chance to break your chains

[Service]
ExecStart=/usr/bin/env bash -c '[[ $(($RANDOM % 10)) == 0 ]] && systemctl poweroff || echo LIVE ANOTHER DAY'
  • ExecCondition= conditional execution को systemd service option के रूप में व्यक्त करने का अधिक integrated तरीका है, और यह unit स्तर पर “क्या execution जारी रहना चाहिए?” को अधिक स्पष्ट दिखाता है
[Unit]
Description=1 in 10 chance to break your chains

[Service]
ExecCondition=/run/current-system/sw/bin/bash -c '[[ $(($RANDOM % 10)) == 0 ]]'
ExecStart=/run/current-system/sw/bin/systemctl poweroff
  • अगर condition पूरी नहीं होती, तो journal में अधिक स्पष्ट संदेश दर्ज होता है
May 05 11:05:32 diesel systemd[3117]: Condition check resulted in 1 in 10 chance to break your chains being skipped.
  • सामान्यतः, systemd के दिए हुए options का उपयोग करना सीधे scripting करने से बेहतर अनुभव देता है
    • OnFailure= का उपयोग service script failure पर प्रतिक्रिया देने के लिए किया जा सकता है
    • Restart= का उपयोग अस्थायी failure से recovery की कोशिश करने के लिए किया जा सकता है

timer unit को जोड़ना और चलाना

  • अगर उसी file stem के साथ /etc/systemd/system/roulette.timer रखा जाए, तो timer को roulette.service से जोड़ा जा सकता है
[Unit]
Description=impending destruction

[Timer]
OnCalendar=10:00

[Install]
WantedBy=timers.target
  • default रूप से timer की Unit= setting उसी stem में .service जुड़ी हुई service unit को चुनती है
    • इस उदाहरण में roulette.service चुनी जाएगी
    • अगर किसी दूसरे नाम की service unit चलानी हो, तो Unit= बदला जा सकता है
  • ExecStart= target default रूप से shell command के रूप में execute नहीं होता
    • absolute path target को script की तरह या string arguments लेने वाले interpreter की तरह संभालना चाहिए
    • ExecStart=/usr/bin/echo Hello | /usr/bin/awk इस संदर्भ में काम नहीं करेगा, क्योंकि pipe का यहाँ कोई अर्थ नहीं है
  • ExecStart= arguments default रूप से system manager defaults के अलावा environment variables inherit नहीं करते
    • default $PATH लगभग खाली अवस्था के क़रीब होता है
    • /usr/bin/env चलाना एक आसान safeguard है, जिससे systemctl जैसी चीज़ें उपलब्ध हो जाती हैं
    • अगर केवल ExecStart=/usr/bin/bash लिखा होता, तो $PATH में default entries आ जातीं, लेकिन env का उपयोग एक अतिरिक्त सुरक्षा है
  • service को timer के बिना भी सीधे चलाया जा सकता है
systemctl start roulette
  • जिस service में [Install] section नहीं है उसे enable नहीं किया जा सकता, और इस संरचना में timer का service को लगातार चलाना मानक तरीका है
  • systemctl बिना explicit suffix के भी default रूप से roulette.service पर काम करता है
  • .timer unit पर systemctl start लगाने से timer active हो जाता है, लेकिन वास्तविक Unit= target service तुरंत नहीं चलती
systemctl start roulette.timer
  • status से पता चलता है कि timer अगली बार कब चलेगा
systemctl status roulette.timer
Trigger: Sat 2026-04-18 10:00:00 MDT; 35min left
  • सबसे सरल flow यह है: target service बनाइए, उसी जगह schedule वाला timer रखिए, और target की बजाय timer को start कीजिए
  • अगर timer unit के [Install] में WantedBy= हो, तो boot पर भी timer चालू कराया जा सकता है
systemctl enable roulette.timer

समय की अभिव्यक्ति: calendar events और durations

  • timers में schedule expression का तरीका महत्वपूर्ण है, और recurring time intervals को calendar events या timestamps से अलग समझना चाहिए
  • systemd.time(7) manual में पर्याप्त उदाहरण हैं और timer लिखते समय यह पहला reference बन सकता है
  • systemd-analyze time expressions को validate और explain कर सकता है
systemd-analyze calendar '*-*-* *:*:*'
Normalized form: *-*-* *:*:*
    Next elapse: Sat 2026-04-18 16:44:26 MDT
       (in UTC): Sat 2026-04-18 22:44:26 UTC
       From now: 431ms left
  • systemd timers केवल recurring wall-clock times ही नहीं, बल्कि पारंपरिक cron से अलग किसी पिछले event के आधार पर दोहराई जाने वाली duration भी define कर सकते हैं
  • daily का पूरा रूप यह है कि हर साल, हर महीने, हर दिन 00:00:00 पर execute किया जाए
*-*-* 00:00:00
│ │ │ │  │  ╰── at second 00
│ │ │ │  ╰───── at minute 00
│ │ │ ╰──────── at hour 00
│ │ ╰────────── every day
│ ╰──────────── every month
╰────────────── every year
  • daily जैसे shorthand, पूरा format, और systemd.time(7) के अन्य supported values इस्तेमाल किए जा सकते हैं, और systemd-analyze से अपनी assumptions verify की जा सकती हैं

जब event-आधारित execution अधिक उपयुक्त हो

  • वास्तविक कामों में अक्सर “हर दिन एक ही समय पर चलाओ” से अधिक उपयुक्त “किसी दूसरे event के बाद चलाओ” होता है
  • temporary directory खाली करने वाले काम में, अगर boot के तुरंत बाद cron expression का समय निकल चुका हो, तो /tmp में साफ़ करने के लिए लगभग कुछ नहीं होगा
  • “कंप्यूटर शुरू होने के एक घंटे बाद चलाओ और उसके बाद हर घंटे चलाओ” कहने से service के वास्तविक behavior और scheduling logic में बेहतर मेल बैठता है
[Timer]
OnBootSec=1h
OnUnitActiveSec=1h
  • OnBootSec=1h का मतलब है मशीन शुरू होने के 1 घंटे बाद एक बार चलना
  • OnUnitActiveSec=1h का मतलब है Unit= के चलने के 1 घंटे बाद फिर से चलना, जिससे timer implicit रूप से लगातार दोहराता रहता है
  • ऐसी periodic duration expressions अक्सर “हर घंटे इस minute पर चलाओ” जैसे expression की तुलना में “कभी-कभार एक बार चलाओ” वाले उपयोग में अधिक फिट बैठती हैं
  • Advent of Code API को poll करने वाले Slack bot के उदाहरण में */15 cron expression API की “हर 15 मिनट” policy का पालन करता है, लेकिन अगर सभी इसी तरह poll करें तो traffic spike हो सकता है
  • code बदलने के बाद timer शुरू करके हर 15 मिनट बाद चलाना आवश्यक behavior पूरा कर सकता है और thundering herd समस्या को कम करने में मदद कर सकता है

एक नज़र में timer की स्थिति देखना

  • systemctl list-timers एक high-level command है जो मशीन पर timers की स्थिति का सारांश दिखाती है
systemctl list-timers
NEXT                                 LEFT LAST                                  PASSED UNIT                         ACTIVATES
Mon 2026-04-20 15:15:00 MDT      1min 40s Mon 2026-04-20 15:00:05 MDT        13min ago zfs-snapshot-frequent.timer  zfs-snapshot-frequent.service
Mon 2026-04-20 15:32:16 MDT         18min Mon 2026-04-20 14:22:15 MDT        51min ago fwupd-refresh.timer          fwupd-refresh.service
Mon 2026-04-20 16:00:00 MDT         46min Mon 2026-04-20 15:00:05 MDT        13min ago logrotate.timer              logrotate.service
Mon 2026-04-20 16:00:00 MDT         46min Mon 2026-04-20 15:00:05 MDT        13min ago zfs-snapshot-hourly.timer    zfs-snapshot-hourly.service
Tue 2026-04-21 00:00:00 MDT            8h Mon 2026-04-20 09:43:22 MDT     5h 29min ago zfs-snapshot-daily.timer     zfs-snapshot-daily.service
Tue 2026-04-21 07:31:28 MDT           16h Sun 2026-04-19 20:15:47 MDT           7h ago systemd-tmpfiles-clean.timer systemd-tmpfiles-clean.service
Mon 2026-04-27 00:00:00 MDT        6 days Mon 2026-04-20 09:43:22 MDT     5h 29min ago zfs-snapshot-weekly.timer    zfs-snapshot-weekly.service
Mon 2026-04-27 01:09:27 MDT        6 days Mon 2026-04-20 09:43:22 MDT     5h 29min ago fstrim.timer                 fstrim.service
Mon 2026-04-27 04:28:38 MDT        6 days Mon 2026-04-20 09:43:22 MDT     5h 29min ago zpool-trim.timer             zpool-trim.service
Fri 2026-05-01 00:00:00 MDT 1 week 3 days Wed 2026-04-01 10:07:51 MDT 1 week 1 day ago zfs-snapshot-monthly.timer   zfs-snapshot-monthly.service
Fri 2026-05-01 03:17:17 MDT 1 week 3 days Wed 2026-04-01 10:07:51 MDT 1 week 1 day ago zfs-scrub.timer              zfs-scrub.service

11 timers listed.
Pass --all to see loaded but inactive timers, too.
  • सिर्फ़ एक command से उन सभी चीज़ों की पूरी तस्वीर मिल सकती है जो timer schedule के अनुसार चलती हैं
  • list-timers अक्सर उपयोग होने वाले systemd subcommands की श्रृंखला का हिस्सा है
    • list-units भी उपयोगी है
    • list-paths systemctl में अपेक्षाकृत नया जोड़ा गया subcommand है

suspend से जगाकर चलाना

  • WakeSystem= expired timer के कारण system को suspend से जगा सकता है
WakeSystem=
    Takes a boolean argument. If true, an elapsing timer will
    cause the system to resume from suspend, should it be
    suspended and if the system supports this.
...
  • यह सुविधा तब उपयोगी है जब किसी महत्वपूर्ण script को चलाना हो और कोई व्यक्ति physically laptop lid खोलने वाला न हो
  • Arch या NixOS जैसी distributions, जो उपयोग से पहले package update download करने का समर्थन करती हैं, उनमें देर रात update packages पहले से fetch किए जा सकते हैं और सुबह keyboard के सामने बैठकर update किया जा सकता है
  • manual बताता है कि .service समाप्त होने के बाद system को दोबारा suspend में भेजना हो तो यह manually करना पड़ता है

execution time को फैलाना और thundering herd कम करना

  • thundering herd समस्या वह system समस्या है जो तब होती है जब कई processes एक साथ जाग जाती हैं
  • अगर दुनिया भर की Debian systems को 00:00:00 पर apt update करने के लिए hardcode कर दिया जाए, तो midnight सबके लिए खराब traffic peak बन जाएगा
  • FixedRandomDelay= और RandomizedOffsetSec= execution time को फैलाने में मदद करते हैं
FixedRandomDelay=
    Takes a boolean argument. When enabled, the randomized delay
    specified by RandomizedDelaySec= is chosen deterministically,
    and remains stable between all firings of the same timer,
    even if the manager is restarted. ...

RandomizedOffsetSec=
    Offsets the timer by a stable, randomly-selected, and evenly
    distributed amount of time between 0 and the specified time
    value. ...
  • software updates check करने वाले वास्तविक systems में ऐसी settings उपयोग की जा सकती हैं
  • executions को evenly distribute करने से thundering herd समस्या कम होती है, behavior अधिक consistent बनता है, और distributed services को coordinate करते समय daemon restart जैसी disruptive गतिविधियों से बचने में मदद मिलती है
  • timing options कुल मिलाकर बहुत configurable हैं और fine-grained control देती हैं

छूटे हुए execution को तुरंत पूरा करना

  • Persistent= उन scheduled scripts के लिए खास तौर पर उपयुक्त है जिन्हें sleeping laptop की वजह से skip नहीं होना चाहिए, लेकिन WakeSystem= तक की ज़रूरत भी नहीं है
Persistent=
    Takes a boolean argument. If true, the time when the service
    unit was last triggered is stored on disk. When the timer is
    activated, the service unit is triggered immediately if it
    would have been triggered at least once during the time when
    the timer was inactive. ...
  • अगर configuration management check-in के लिए scheduled system ने downtime झेला हो, तो .timer में सिर्फ़ Persistent= रखने से online होते ही वह सही state की ओर converge कर सकता है
  • Persistent= के बिना, आपको timer के सामान्य execution time तक इंतज़ार करना पड़ सकता है, और वह इंतज़ार लंबा हो सकता है
  • ऐसी दूसरी jobs जिनमें missed activation का पता चलने पर इंतज़ार नहीं करना चाहिए, उनमें system updates, batch job checks आदि शामिल हैं

timers लिखते समय ध्यान देने योग्य बातें

  • user manager context के timers, जिन्हें systemctl --user से संभाला जाता है, भी मान्य हैं, लेकिन [Install] में उपयोग होने वाले target पर ध्यान देना चाहिए
  • distribution के अनुसार user timers के लिए सही target default.target हो सकता है
  • cron की तरह, system clock को सही रखना ज़रूरी है—यह सामान्य सावधानी यहाँ भी लागू होती है
  • systemd उपयोगकर्ता timedatectl timesync-status से synchronization status देख सकते हैं
  • कई editors systemd unit file format को built-in support देते हैं, जो unit files बड़ी होने पर मददगार होता है
  • Emacs में emacs systemd package इस्तेमाल किया जा सकता है

1 टिप्पणियां

 
Lobste.rs की राय
  • systemd परफेक्ट नहीं है, लेकिन इसकी कई डिज़ाइन decisions ऐसे लगते हैं मानो वे पुराने, ज़्यादा पारंपरिक तरीकों से मिली सीख पर आधारित हों
    मैंने हाल ही में Lennart Poettering के उस पृष्ठभूमि-समझाने वाले CRE के 2015 episode को फिर से सुना, और वह आज भी recommend करने लायक है

  • मैं systemd को बुनियादी तौर पर नापसंद करने वालों में हूँ, लेकिन systemd.timers मुझे इस प्रोडक्ट के “कम बुरे” concepts में से एक लगते हैं
    इसलिए यह थोड़ा हैरान करने वाला था कि लेखक ने वैध शिकायत रखने वाले लोगों को नीचा दिखाने के अंदाज़ में इसका बचाव किया
    फिर भी, at command के साथ इसका उपयोग अच्छा है। किसी तय समय पर एक बार चलने वाले command के लिए at, और बाकी सबके लिए systemd timers के साथ simple unit files — मैं यही करता हूँ
    जो सुधार मैं सबसे ज़्यादा देखना चाहूँगा, वह यह है कि पता चल सके कि timer कौन-सा user चला रहा है। मैं 2026 में shell box चलाने वाले कुछ गिने-चुने लोगों में से एक हूँ, लेकिन यह जानना उपयोगी होगा कि हर सेकंड disk hit करने वाला timer किस user ने बनाया है

    • इस मकसद के लिए, क्या सबको system timer install करवाने के बजाय user units इस्तेमाल नहीं किए जा सकते?
      मेरी समझ से loginctl enable-linger इस्तेमाल करने पर यह active user session के बिना भी चल सकता है। बेशक, कुछ use cases ऐसे भी होंगे जहाँ यह काफी न हो, और मुझे आपकी खास situation नहीं पता
  • काश systemd timers में, खासकर user management के मामले में, शुरुआती overhead कम होता
    जितनी configuration चाहिए होती है, उसके सामने crontab -e को मात देना सच में मुश्किल है

    • एक timer set up करने के लिए कई config files और services माँगने वाला systemd तरीका… API choice के रूप में लगभग बेहूदा है
  • मैं लंबे समय तक यह सोचता रहा कि cron script logs को व्यवस्थित ढंग से कैसे इकट्ठा किया जाए, फिर समझ आया कि बस systemd timers इस्तेमाल कर लो
    इससे logging की समस्या हल हो गई। अब cron पर वापस जाने की कोई वजह नहीं बची, और काश यह पहले पता होता

    • क्या logger में pipe करना, या log file में >> से append करना, या default वैसे ही छोड़कर email पाना काफी नहीं है?
  • चाहे इसे पुराना कह लें, लेकिन server से मुझे मिलने वाली email आज भी configured है
    इसे automate कर दो तो हर नए host पर यह अपने-आप मिल जाती है, और रोज़मर्रा में भी काफी सुविधाजनक है
    जैसे, एक multiplexer खोलो और long_running_process | mail root@localhost -s "done $?" चलाकर भूल जाओ

  • बढ़िया लेख है, और मेरे पास भी ऐसे ही एक लेख का draft था जिसे मुझे हाल में फिर से देखना पड़ा
    अगर मेरी तरह आप भी systemd की rabbit hole में उतरते हैं, तो मैं recommend करूँगा कि संबंधित project folder में मौजूद unit files और timers को /etc/systemd/system/ में symbolic link कर दें
    systemd को लेकर मेरी एक शिकायत यह है कि यह distribution द्वारा install की गई units और खुद लिखी गई units में फर्क नहीं दिखाता, लेकिन symbolic links से आप यह separation खुद बनाए रख सकते हैं

    • दरअसल, यह फर्क path ही तय करता है
      system/package/distribution units /usr/lib/systemd/system में जाती हैं, और local overrides या local units /etc/systemd/system में