Jinsi ya kuendesha programu kama huduma ya systemd
Jifunze kuunda faili la unit ili programu yako iweze kuanza kiotomatiki wakati wa boot, kujianzisha upya ikipata hitilafu, na kuhifadhi logi zake kwenye journal ya mfumo.
Huduma ya systemd ni nini, na kwa nini unaihitaji
Huduma ya systemd ni faili dogo la maandishi linaloiambia seva yako jinsi ya kuendesha programu: ianzishe wakati wa boot, ianzishe upya ikipata hitilafu, na itume matokeo yake kwenye logi ya mfumo. Hiyo ndiyo kazi yake yote. Programu unayoianzisha kwa mkono katika kipindi cha SSH hufa mara tu unapotoka (logout) au seva inapowaka upya (reboot). Programu iliyofungwa ndani ya huduma ya systemd huendelea kufanya kazi, kwa sababu seva yenyewe ndiyo inayomiliki programu hiyo badala ya shell yako.
systemd ndiyo mfumo wa init kwenye Ubuntu, Debian, Fedora, na seva nyingi za kisasa za Linux. Huu ndio mchakato wa kwanza kuanza na ndio unaosimamia kila kitu kingine. Hali hii haikuwa hivyo kila wakati, na jinsi systemd ilivyochukua nafasi ya hati za init zilizokuwepo awali inafaa kusomwa pindi utakapoelewa kazi ya faili la unit. Unapoandika faili la huduma, unakabidhi programu yako kwa msimamizi huyo. Mwongozo huu unaonyesha unit ndogo zaidi inayofanya kazi, sehemu tatu ambazo kila unit inazo, jinsi ya kuiwasha na kusoma logi zake, jinsi ya kuiendesha kwa ratiba kwa kutumia timer, na jinsi ya kuifunga ili iendeshe kwa upendeleo mdogo iwezekanavyo.
Huduma ndogo zaidi inayofanya kazi
Faili ya huduma hukaa ndani ya /etc/systemd/system/, huishia na .service, na inahitaji mistari michache tu. Tengeneza moja kwa ajili ya programu iliyopo /usr/local/bin/myapp:
sudo nano /etc/systemd/system/myapp.service[Unit]
Description=My application
[Service]
ExecStart=/usr/local/bin/myapp
[Install]
WantedBy=multi-user.targetHiyo ni unit kamili inayofanya kazi. ExecStart ndiyo amri ya kuendesha. WantedBy=multi-user.target inamaanisha anzisha huduma hii mara tu seva inapofikia hali ya kawaida ya multi-user, jambo linaloifanya iwake wakati wa boot. Kila kitu kingine ni maboresho tu.
Sehemu tatu, na kazi ya kila moja
Kila faili ya unit imegawanywa katika sehemu zilizomo kwenye mabano ya mraba. Huduma hutumia sehemu tatu.
[Unit] inaelezea huduma na mahusiano yake. Mistari miwili utakayotumia zaidi:
[Unit]
Description=My application
After=network-online.target
Wants=network-online.targetDescription ni lebo ya kibinadamu unayoiona kwenye systemctl status. After=network-online.target inaiambia systemd isianzishe programu yako hadi mtandao uwe tayari, jambo ambalo ni muhimu kwa chochote kinachofungua port au kinachofanya muunganisho wa nje.
[Service] ni jinsi programu inavyoendeshwa. Hapa ndipo mipangilio yako mingi inapowekwa:
[Service]
ExecStart=/usr/local/bin/myapp --config /etc/myapp/config.toml
WorkingDirectory=/opt/myapp
User=myapp
Restart=on-failure
RestartSec=5
Environment=LOG_LEVEL=infoUser=myapp huendesha programu kama akaunti isiyo na upendeleo badala ya root, huu ndio mstari muhimu zaidi kwa ajili ya usalama. Hakuna mstari wa Type= hapa, kwa hivyo systemd inarudi kwenye simple na kudhani kuwa mchakato wa ExecStart unabaki mbele (foreground); programu inayojitenga (fork) kwenda nyuma (background) inahitaji Type= sahihi kulingana na jinsi inavyoanza, vinginevyo unit itaripoti kuwa inafanya kazi wakati daemon halisi imeshakufa. Restart=on-failure na RestartSec=5 zina sehemu yake hapa chini, kwa sababu ndizo sababu kuu zinazowafanya watu kuandika huduma.
[Install] ni kile kinachotokea unapowezesha huduma:
[Install]
WantedBy=multi-user.targetWantedBy=multi-user.target ndicho kinachounganisha huduma kwenye mchakato wa boot unapoendesha systemctl enable. Bila sehemu ya [Install], huduma inaweza kuanzishwa kwa mkono lakini haitajiwasha yenyewe baada ya reboot.
Iwashe na uifuatilie
Baada ya kuandika au kuhariri faili yoyote ya unit, pakia upya systemd ili isome mabadiliko hayo, kisha iwezeshe na uanzishe huduma hiyo kwa hatua moja:
sudo systemctl daemon-reload
sudo systemctl enable --now myapp.servicedaemon-reload ndiyo hatua ambayo watu husahau: systemd huhifadhi faili za unit kwenye cache, hivyo uhariri hautafanya kazi hadi utakapopakia upya. enable --now huwezesha huduma hiyo kuanza wakati wa boot na kuianzisha mara moja. Iangalie:
sudo systemctl status myapp.service* myapp.service - My application
Loaded: loaded (/etc/systemd/system/myapp.service; enabled)
Active: active (running) since Wed 2026-07-15 22:40:11 UTC; 3s ago
Main PID: 4123 (myapp)Active: active (running) na enabled ndivyo unavyotaka kuona. Ili kusoma matokeo (output) ya programu, omba journal kwa ajili ya unit hii pekee:
sudo journalctl -u myapp.service -f-f hufuatilia mistari mipya inapoingia, kama vile tail -f. Kila kitu ambacho programu yako huandika kwenye standard output au standard error huonekana hapa, bila wewe kuhitaji kusanidi mfumo wowote wa logging.
Kuanzisha upya huduma ikifeli, ndiyo sababu uko hapa
Faida kuu ya huduma ni kwamba systemd huanzisha upya programu yako pale inapokufa. Mistari miwili hufanya kazi hii:
[Service]
Restart=on-failure
RestartSec=5Restart=on-failure huanzisha upya programu pale inapotoka kwa kodi isiyo sifuri au kufa kutokana na signal ya crash kama SIGKILL au SIGSEGV. Kutoka kwa usafi, au kusimamishwa na SIGTERM, SIGINT, SIGHUP, au SIGPIPE, hakusababishi hatua hii. RestartSec=5 husubiri sekunde tano kati ya majaribio, ili programu inayokwama mara moja isizunguke kwenye loop ya haraka. Ithibitishe kwa kuua mchakato na kutazama systemd ikiuleta tena. Tumia SIGKILL: SIGTERM ya kawaida huhesabiwa kama usimamishaji safi, kwa hivyo on-failure haitaanzisha upya huduma hiyo:
sudo systemctl kill -s SIGKILL myapp.service
sudo systemctl status myapp.serviceNdani ya sekunde tano hali inaonyesha Main PID mpya na active (running) tena. Hiyo ndiyo kipengele kizima, na ndiyo sababu huduma ni bora kuliko kuacha programu ikiendelea kukimbia kwenye tmux au screen.
Iendeshe kama mtumiaji asiye na upendeleo, na uimarishe usalama wake
Huduma inayofanya kazi kama root inaweza kufanya lolote kwenye seva yako ikiwa programu hiyo itavamiwa. Iendeshe kama mtumiaji wake mwenyewe, na uipe systemd maelekezo machache ya kuifungia ndani. Kwanza tengeneza akaunti ya mfumo isiyo na uwezo wa kuingia (login) na isiyo na home directory:
sudo useradd --system --no-create-home --shell /usr/sbin/nologin myappKisha weka User=myapp na uongeze mistari ya kuimarisha usalama kwenye [Service]:
[Service]
User=myapp
NoNewPrivileges=true
PrivateTmp=true
ProtectSystem=strict
ProtectHome=trueKila mstari huondoa kitu ambacho programu haikihitaji. NoNewPrivileges=true huzuia mchakato huo kupata upendeleo mpya, hata kupitia binary ya setuid. PrivateTmp=true huipa /tmp ya faragha ambayo mchakato mwingine wowote hauwezi kuiona. ProtectSystem=strict hufanya mfumo mzima wa faili kuwa wa kusoma tu (read-only) isipokuwa kwa njia chache unazozitaja kwa ReadWritePaths=. ProtectHome=true huficha /home kutoka kwake kabisa. Hii ni dhana ileile ya upendeleo mdogo (least-privilege) kama kuweka huduma nyuma ya firewall: ipe tu kile inachohitaji. Ikiwa umesoma mwongozo wa kuziba pengo la firewall ya IPv6 kwenye VPS, hii ndiyo nusu ya wazo hilo inayotekelezwa ndani ya seva. Kwa huduma inayokabili Internet, unganisha uimarishaji huu na Fail2ban mbele ya SSH na firewall ya default-deny.
Badala ya kuandika haya yote kwa mkono na kusahau maelekezo, tengeneza unit iliyokamilika na iliyoimarishwa kisha uinakili:
Timers: mbadala wa kisasa wa cron
Systemd timer huendesha huduma kulingana na ratiba, na ndiyo mbadala wa kisasa wa cron job. Timer inajumuisha faili mbili: .service inayotekeleza kazi, na .timer inayobainisha muda. Tuseme unataka backup ifanyike saa 9 usiku kila siku. Huduma hutekeleza kazi hiyo mara moja kisha hujifunga:
# /etc/systemd/system/backup.service
[Unit]
Description=Nightly backup
[Service]
Type=oneshot
ExecStart=/usr/local/bin/backup.shType=oneshot huambia systemd kuwa programu inaendeshwa, inamaliza kazi, na inajifunga, badala ya kubaki ikiwa imewashwa. Timer hupanga ratiba yake:
# /etc/systemd/system/backup.timer
[Unit]
Description=Run the nightly backup
[Timer]
OnCalendar=*-*-* 03:00:00
Persistent=true
[Install]
WantedBy=timers.targetOnCalendar=*-*-* 03:00:00 inamaanisha saa 9 usiku kila siku. Jaribu usemi wowote wa kalenda kwa kutumia systemd-analyze calendar "*-*-* 03:00:00", ambayo huthibitisha kama usemi huo umesomwa vyema na kuonyesha nyakati zijazo ambazo kazi hiyo itatekelezwa. Persistent=true huendesha kazi iliyokosa kutekelezwa mara tu seva inapowaka ikiwa ilikuwa imezimwa saa 9 usiku, jambo ambalo cron haiwezi kufanya. Kumbuka kuwa timer huwashwa kupitia timers.target, si multi-user.target. Washa timer, si huduma:
sudo systemctl daemon-reload
sudo systemctl enable --now backup.timer
systemctl list-timerslist-timers huonyesha kila timer pamoja na muda wake wa utekelezaji ujao na uliopita, ili uweze kuona kwa haraka wakati kazi yako itakapoanza tena. Jenereta iliyo hapo juu hutengeneza jozi ya .service na .timer kwa ajili yako unapowasha hali ya timer. Ikilinganishwa na mstari wa cron, timer hukupa logi halisi kwenye journal, maelekezo sawa ya uimarishaji (hardening) kama huduma nyingine yoyote, na uwezo wa kufidia kazi zilizokosa kutekelezwa ambao Persistent=true hutoa. Cron bado inafaa kwa kazi rahisi; timer ni zana bora zaidi pindi kazi hiyo inapokuwa muhimu.
FAQ
Kuna tofauti gani kati ya systemd service na cron job?
Service huweka programu inayoendelea kufanya kazi ikiwa hai: huanza wakati wa boot, huanza upya ikifeli, na huandika kumbukumbu kwenye journal. Cron job huendesha amri fupi kwa ratiba maalum kisha hujifunga. Unapotaka ratiba lakini pia unahitaji journal logs, uimarishaji wa usalama (hardening), na uwezo wa kufanya kazi zilizokosa muda, tumia systemd timer. Hii huunganisha ratiba ya .timer na service ya oneshot na kuchukua nafasi ya cron kwa kazi nyingi za seva.
Ninaweka wapi faili yangu ya systemd service?
Weka unit zako mwenyewe ndani ya /etc/systemd/system/, ukitumia jina linalomalizia na .service. Saraka hiyo ni kwa ajili ya unit zinazoongezwa na msimamizi wa mfumo, na ina kipaumbele kuliko unit zinazokuja na vifurushi ndani ya /lib/systemd/system/. Baada ya kutengeneza au kuhariri faili hapo, endesha sudo systemctl daemon-reload ili systemd itambue mabadiliko hayo.
Ninafanyaje service ianze upya ikipata hitilafu (crash)?
Ongeza Restart=on-failure na RestartSec=5 kwenye sehemu ya [Service], kisha endesha sudo systemctl daemon-reload na uanzishe upya service hiyo. systemd huwasha upya programu inapotoka kwa code isiyo ya sifuri au kufa kutokana na signal ya crash, ikisubiri sekunde tano kati ya majaribio. Ijaribu kwa sudo systemctl kill -s SIGKILL myapp.service; SIGTERM, ambayo ni signal ya kawaida, huhesabika kama usimamishaji safi na haianzishi on-failure, na utaona systemctl status ikionyesha PID mpya ndani ya sekunde chache.
Ninaendeshaje systemd service kama mtumiaji asiye root?
Tengeneza akaunti ya mfumo kwa kutumia sudo useradd --system --no-create-home --shell /usr/sbin/nologin myapp, kisha ongeza User=myapp kwenye sehemu ya [Service]. Ongeza NoNewPrivileges=true, PrivateTmp=true, na ProtectSystem=strict ili mchakato huo uendeshwe kwa ufikiaji mdogo kadiri inavyohitajika. Kuendesha programu kama mtumiaji asiye na upendeleo (unprivileged user) ndilo badiliko muhimu zaidi unaloweza kufanya ili kuimarisha usalama wa service.
Kwa nini service yangu imeshindwa kuanza?
Endesha systemctl status myapp.service kwa muhtasari na journalctl -u myapp.service kwa matokeo kamili. Sababu za kawaida ni njia (path) isiyo sahihi katika ExecStart, WorkingDirectory iliyokosekana, hitilafu ya ruhusa kwa sababu User= haiwezi kusoma faili, au kusahau sudo systemctl daemon-reload baada ya kuhariri. Journal huonyesha ujumbe wa hitilafu wa programu yenyewe, ambao kwa kawaida hutaja tatizo moja kwa moja.