EQVPS
პანელიდაწყება

როგორ დავგეგმოთ ამოცანები VPS-ზე cron-ითა და systemd-ის ტაიმერებით

გაუშვით ბექაპები, გასუფთავება და სკრიპტები განრიგით. Cron ხუთ წუთში და სამი ხაფანგი, რომლებიც ამოცანებს ჩუმად აფუჭებს, შემდეგ systemd-ის ტაიმერები: ლოგები, გამოტოვებულის დაწევა გაჩერების შემდეგ და ზუსტი დრო. ქვემოთ აღწერილი ყველა ქცევა შემოწმებულია ახალ სერვერზე Ubuntu 24.04-ით.

სერვერი თავს იმით იმართლებს, რომ მუშაობს, სანამ გძინავთ: ბექაპები, ლოგების როტაცია, სერტიფიკატების განახლება, ანგარიში ცხრა საათზე. Linux-ში ამისთვის ორი დამგეგმავია. Cron ორმოცი წლისაა და ერთ ხაზს მოითხოვს. systemd-ის ტაიმერებს ორი პატარა ფაილი სჭირდება, სამაგიეროდ ლოგებს, გაჩერების შემდეგ დაწევას და ზუსტ დროს იძლევა. ეს სახელმძღვანელო ორივეს განიხილავს Ubuntu 24.04-ზე; ყველა ქცევა შემოწმებულია ჩვენი იმიჯიდან ახალ სერვერზე, მათ შორის სამი შეცდომა, რის გამოც cron-ის ამოცანა ერთი სიტყვის გარეშე ფუჭდება.

გჭირდებათ მომხმარებელი sudo-თი; Ubuntu-ს დაყენების სახელმძღვანელო მას ქმნის.

1. Cron ხუთ წუთში

Cron დაყენებულია და მუშაობს ჩვენს Ubuntu და Debian იმიჯებზე. თითოეულ მომხმარებელს საკუთარი ამოცანების ცხრილი აქვს; თქვენი ასე შეცვალეთ:

crontab -e

ყოველი ხაზი ხუთი დროის ველი და ბრძანებაა:

# min hour day month weekday  command
  30  3    *   *     *        /usr/local/bin/backup.sh >> /var/log/backup.log 2>&1
  */5 *    *   *     *        /usr/local/bin/check.sh
  0   9    *   *     1-5      /usr/local/bin/report.sh
  @reboot                     /usr/local/bin/start-tunnel.sh

ანუ: ყოველ ღამე 03:30-ზე, ყოველ 5 წუთში, სამუშაო დღეებში 09:00-ზე და ერთხელ ყოველი ჩატვირთვის შემდეგ. */5 — ყოველი მეხუთე მნიშვნელობა, 1-5 — დიაპაზონი, 1,15 — სია. მოქმედებს სერვერის დროის სარტყელი, ჩვენს იმიჯებზე UTC; თქვენი ერთხელ დააყენეთ სახელმძღვანელოთი ჰოსტის სახელისა და დროის სარტყლის შესახებ, და cron მას გამოიყენებს.

რა გაეშვა, ნახეთ journalctl -u cron-ში. ყოველი გაშვება წერს მომხმარებელსა და ბრძანებას, და სწორედ იქ ჩანს სამი ხაფანგი.

ხაფანგი 1: გამოტანა ქრება. Cron ამოცანის გამოტანას მომხმარებელს ელფოსტით უგზავნის. ჩვენს იმიჯზე საფოსტო სერვერი არ არის, ამიტომ ჟურნალში გამოჩნდა (CRON) info (No MTA installed, discarding output) და გამოტანა დაიკარგა. გადაამისამართეთ თავად, როგორც პირველ მაგალითშია: >> /var/log/backup.log 2>&1.

ხაფანგი 2: პროცენტის ნიშანი. crontab-ში % ბრძანებას ასრულებს და დანარჩენს სტანდარტულ შეყვანად აქცევს. დავგეგმეთ date +%F > /tmp/today. ჟურნალი აჩვენებს, რა გაუშვა cron-მა სინამდვილეში: CMD (date +). ფაილი არ შეიქმნა და შეცდომა ჩვენამდე არ მოსულა. დაწერეთ \% ან ბრძანება სკრიპტში გადაიტანეთ და სკრიპტი დაგეგმეთ.

ხაფანგი 3: სხვა გარემო. Cron ამოცანებს /bin/sh-ით უშვებს და არა bash-ით, საშინაო საქაღალდეში და მწირი გარემოთი. Ubuntu 24.04-ზე PATH თავის რეპუტაციაზე უკეთესი აღმოჩნდა — სრული სისტემური გზა, /usr/local/bin-ისა და /snap/bin-ის ჩათვლით, როგორც root-ისთვის, ისე ჩვეულებრივი მომხმარებლისთვის. ისევ აკლია ყველაფერი საშინაო საქაღალდიდან: ~/.local/bin, nvm-ის node, pipx, cargo. ამოცანაში სრული გზები გამოიყენეთ ან ხაზი დაიწყეთ . $HOME/.profile;-ით.

ამოცანები, რომლებიც სისტემას ეკუთვნის და არა მომხმარებელს, /etc/cron.d/-ში დადეთ ცალკე ფაილად ერთი დამატებითი ველით — მომხმარებლით:

30 3 * * * root /usr/local/bin/backup.sh >> /var/log/backup.log 2>&1

Ubuntu ასევე უშვებს ყველაფერს /etc/cron.hourly, cron.daily, cron.weekly და cron.monthly საქაღალდეებიდან — ყოველი საათის მე-17 წუთზე, 06:25-ზე, კვირას 06:47-ზე და თვის პირველ რიცხვში 06:52-ზე. ჩადეთ იქ შესრულებადი სკრიპტი და ის დანარჩენებთან ერთად გაეშვება.

2. systemd-ის ტაიმერები

ტაიმერი ორი იუნიტია: სერვისი, რომელიც სამუშაოს ასრულებს, და ტაიმერი, რომელიც ამბობს, როდის. ჯერ შექმენით სკრიპტი, შემდეგ იუნიტები.

sudo nano /usr/local/bin/backup.sh
sudo chmod +x /usr/local/bin/backup.sh
sudo nano /etc/systemd/system/backup.service
[Unit]
Description=Nightly backup

[Service]
Type=oneshot
ExecStart=/usr/local/bin/backup.sh
sudo nano /etc/systemd/system/backup.timer
[Unit]
Description=Run the backup every night at 03:30

[Timer]
OnCalendar=*-*-* 03:30
Persistent=true
AccuracySec=1m

[Install]
WantedBy=timers.target

ჩართეთ ტაიმერი და არა სერვისი:

sudo systemctl daemon-reload
sudo systemctl enable --now backup.timer
systemctl list-timers backup.timer

list-timers აჩვენებს შემდეგ გაშვებას, რამდენი დარჩა მანამდე და ბოლო გაშვებას. ლოგებს დაყენება არ სჭირდება: journalctl -u backup.service-ში არის ყოველი დაწყება, დასრულება და გამოტანის ყოველი ხაზი დროის ნიშნულებით. ამოცანის ახლავე გასაშვებად — sudo systemctl start backup.service; ასევე უნდა შეამოწმოთ სკრიპტი, სანამ განრიგს ენდობით.

კალენდრის სინტაქსი. OnCalendar იკითხება როგორც კვირისდღე წელი-თვე-დღე საათი:წუთი:წამი, * — ნებისმიერი მნიშვნელობა. გამოყენებამდე შეამოწმეთ გამოსახულება:

systemd-analyze calendar "Mon..Fri *-*-* 03:00" --iterations 2

ბრძანება ბეჭდავს ნორმალიზებულ ფორმას და უახლოეს თარიღებს. რამდენიმე გამოსახულება, რომელიც შევამოწმეთ:

OnCalendarმნიშვნელობა
*-*-* 03:30ყოველდღე 03:30-ზე
Mon..Fri *-*-* 09:00სამუშაო დღეებში 09:00-ზე
*:0/15ყოველ 15 წუთში
weeklyორშაბათობით 00:00-ზე
*-*-01 04:00ყოველი თვის პირველ რიცხვში 04:00-ზე
*-*-* 03:00 Europe/Kyiv03:00 კიევის დროით; ჩვენთან 01:00 UTC-ზე გაეშვა

სამი პარამეტრი, რომელიც უნდა იცოდეთ. Persistent=true ბოლო გაშვებას დისკზე ინახავს და იწევს გაშვებას, რომელიც გამოტოვდა, სანამ სერვერი გამორთული ან ტაიმერი გაჩერებული იყო. ჩვენი ორწუთიანი ტაიმერი გავაჩერეთ, დაველოდეთ, სანამ დაგეგმილი გაშვება გავიდოდა, და ხელახლა ჩავრთეთ: გამოტოვებული გაშვება იმავე წამში დაიწყო. Persistent-ის გარეშე ტაიმერი უბრალოდ შემდეგ სლოტს ელოდება.

AccuracySec მთავარი სიურპრიზია. ნაგულისხმევად systemd ტაიმერებს ერთწუთიან ფანჯარაში აჯგუფებს, რომ სისტემა იშვიათად გააღვიძოს, ამიტომ ჩვენი პირველი გაშვება 07:42:18-ზე მოვიდა და არა 07:42:00-ზე. AccuracySec=1s-ით შემდეგი გაშვებები ზუსტად, წამის სიზუსტით 07:46:00-სა და 07:48:00-ზე მოხდა. დააყენეთ, როცა წუთი მნიშვნელოვანია; ღამის ბექაპისთვის ნაგულისხმევი დატოვეთ.

RandomizedDelaySec=10m განზრახ საპირისპიროს აკეთებს: სტარტს ფანჯარაში ანაწილებს, რომ ათმა სერვერმა ერთსა და იმავე ბექაპის საცავს ერთსა და იმავე წამში არ მიაწყდეს.

ერთჯერადი ამოცანისთვის ფაილები საერთოდ არ გჭირდებათ:

sudo systemd-run --on-active=30m --unit=cleanup-once /usr/local/bin/cleanup.sh

ბრძანება ქმნის დროებით ტაიმერს, რომელიც ერთხელ ამუშავდება და გაქრება; მანამდე ის ჩანს systemctl list-timers-ში.

3. რომელი ავირჩიოთ

Cronsystemd-ის ტაიმერი
დაყენება1 ხაზი2 ფაილი
ლოგებიმხოლოდ გამოტანის გადამისამართებისასjournalctl -u name.service
გამოტოვებული გაშვება, სანამ სერვერი გამორთული იყოიკარგებასრულდება ჩატვირთვისას Persistent=true-ით
ამოცანა ჯერ კიდევ მუშაობს შემდეგ ტიკზემეორე ასლი ეშვებაგამოიტოვება, სანამ პირველი არ დასრულდება
ზუსტი დროწუთამდეწამამდე AccuracySec=1s-ით
სტატუსიარ არისlist-timers, systemctl status

აირჩიეთ cron სწრაფი ხაზისთვის, რომელსაც ერთი წლის შემდეგაც იცნობთ. აირჩიეთ ტაიმერი ყველაფრისთვის, რისი ჩავარდნაც უნდა დაინახოთ, რაც არ უნდა გადაიფაროს ან რაც გადატვირთვის გამო გამოტოვების შემდეგაც უნდა შესრულდეს: ბექაპები, სერტიფიკატების განახლება, მონაცემთა ბაზების გასუფთავება. თუ cron-ის ამოცანა შეიძლება გადაიფაროს, შეფუთეთ: flock -n /tmp/backup.lock /usr/local/bin/backup.sh, და მეორე ასლი მაშინვე დასრულდება.

ორივე დამგეგმავი ამოცანას უშვებს და ჩერდება. პროგრამისთვის, რომელიც უწყვეტად უნდა მუშაობდეს და ავარიის შემდეგ აღდგეს, სერვისი გჭირდებათ და არა განრიგი; იხილეთ, როგორ შევქმნათ systemd-ის სერვისი, ხოლო Windows-ისთვის — როგორ გავუშვათ სკრიპტი 24/7 Windows Server-ზე. კარგი პირველი ტაიმერია ჩვენი restic-ით ბექაპის სახელმძღვანელოდან; უსაფრთხოების ავტომატური განახლებები ტაიმერია, რომელიც Ubuntu-ს უკვე მოყვება, apt-daily-upgrade.timer, ერთ-ერთი იმ 17-დან, რომლებიც ახალ სერვერზე მუშაობს.

ხდკ

რატომ მუშაობს ამოცანა ტერმინალში, მაგრამ არა cron-ში?

სამი ჩვეული მიზეზი. Cron ამოცანას sh-ით უშვებს და არა bash-ით, ამიტომ მხოლოდ bash-ის სინტაქსი ვერ მუშაობს. საშინაო საქაღალდეში დაყენებული ხელსაწყოები, როგორიცაა nvm, pipx ან cargo, cron-ის PATH-ში არ არის, ამიტომ სრული გზები გამოიყენეთ. და ბრძანების ხაზში ნებისმიერი % ბრძანებას წყვეტს: ჩვენს სერვერზე date +%F გადაიქცა date +-ად. დაწერეთ \% ან ბრძანება სკრიპტში გადაიტანეთ.

სად მიდის cron-ის გამოტანა?

ნაგულისხმევად — ელფოსტაზე. ჩვენს იმიჯზე საფოსტო სერვერი არ არის, ამიტომ cron ჟურნალში წერს 'No MTA installed, discarding output' და გამოტანა იკარგება. დაუმატეთ ამოცანას >> /var/log/myjob.log 2>&1 ან გადადით systemd-ის ტაიმერზე, რომლის გამოტანაც თავისით ხვდება ჟურნალში.

რით სჯობს systemd-ის ტაიმერი cron-ს?

ლოგები journalctl-ში, ჯერ კიდევ მომუშავე ამოცანის მეორე ასლი არ ეშვება, Persistent=true-ით იწევს სერვერის გამორთვისას გამოტოვებული გაშვებები, და სტატუსი აჩვენებს შემდეგ და ბოლო გაშვებას. Cron სიმოკლით იგებს: ერთი ხაზი ორი ფაილის ნაცვლად.

ტაიმერი 18 წამით გვიან ამუშავდა. რატომ?

ნაგულისხმევად systemd ტაიმერებს ერთწუთიან ფანჯარაში აჯგუფებს, რომ სისტემა იშვიათად გააღვიძოს — ეს AccuracySec პარამეტრია. ჩვენი ორწუთიანი ტაიმერი 07:42:00-ის ნაცვლად 07:42:18-ზე ამუშავდა. AccuracySec=1s-ით ზუსტად 07:46:00-ზე ამუშავდა. დააყენეთ, როცა ზუსტი წუთი მნიშვნელოვანია.

რომელ დროის სარტყელში მუშაობს cron და ტაიმერები?

სერვერისაში, ჩვენს იმიჯებზე ეს UTC-ია. ერთხელ დააყენეთ timedatectl-ით, იხილეთ ჩვენი სახელმძღვანელო ჰოსტის სახელისა და დროის სარტყლის შესახებ, და cron-იც და ტაიმერებიც მას მიჰყვება. ტაიმერს საკუთარი სარტყელიც შეიძლება ჰქონდეს: OnCalendar=*-*-* 03:00 Europe/Kyiv ჩვენს ტესტში 01:00 UTC-ზე ამუშავდა.

კომენტარები

ჯერ არ არის კომენტარები. იყავით პირველი.

დატოვეთ კომენტარი

კომენტარები მოდერირდება გამოჩენამდე.