Μετάβαση στο περιεχόμενο

Ρυθμίσεις cookies

Επιλέξτε ανά κατηγορία ποια cookies επιτρέπετε. Μπορείτε να αλλάξετε την επιλογή σας οποιαδήποτε στιγμή μέσω των Ρυθμίσεων cookies στο κάτω μέρος κάθε σελίδας. Δήλωση απορρήτου

Απαραίτητα

Πάντα ενεργά

Χρειάζονται για τη σύνδεση, για να διατηρείται το καλάθι σας και για να θυμόμαστε τις επιλογές σας. Είναι πάντα ενεργά.

Ποια cookies;
  • weboke_sessie, weboke_klant, weboke_remember: η συνεδρία σας και η παραμονή σε σύνδεση
  • weboke_basket: το καλάθι σας
  • wkBtwIncl: εμφάνιση τιμών με ή χωρίς ΦΠΑ
  • wok_cookies: η επιλογή σας για τα cookies, 12 μήνες

Μετρούν ποια διαφήμιση οδηγεί σε επίσκεψη ή παραγγελία, ώστε να μην πληρώνουμε για διαφημίσεις που δεν αποδίδουν.

Ποια cookies;
  • Google Ads μέσω Google Tag Manager (_gcl_au, _gcl_aw), έως 90 ημέρες
  • OpenAI Ads, διαφημίσεις στο ChatGPT
  • wok_aff: μέσω ποιου συνεργάτη ήρθατε σε εμάς (πρόγραμμα συνεργατών), 60 ημέρες

4,6

Χώρα και γλώσσα

Κάθε χώρα έχει τη δική της ιστοσελίδα, με τιμές και ΦΠΑ της χώρας αυτής.

Προβολή

Δικές σας υπηρεσίες και timers

Ενότητα 6: Υπηρεσίες και αρχεία καταγραφής · Χρόνος ανάγνωσης: 11 λεπτά

Στόχος μαθήματος: Μετά από αυτό το μάθημα μπορείτε να εκτελείτε ένα δικό σας πρόγραμμα ως υπηρεσία systemd με δικό του χρήστη και μερικές επιλογές ασφαλείας, καθώς και να προγραμματίζετε εργασίες με ένα systemd timer ή με cron.

Βασικές έννοιες: αρχείο unit, [Unit], [Service], [Install], ExecStart, User=, WorkingDirectory, EnvironmentFile, Restart=, WantedBy, NoNewPrivileges, ProtectSystem, ProtectHome, PrivateTmp, systemd-analyze security, timer, OnCalendar, Persistent, crontab

Γιατί όχι απλώς "nohup" ή "screen";

Όποιος βάζει ένα δικό του πρόγραμμα σε έναν server (μια μικρή διαδικτυακή εφαρμογή, ένα bot, ένα script που κάνει κάτι κάθε νύχτα), την πρώτη φορά συχνά το ξεκινά με το χέρι: node server.js & ή μέσα σε μια συνεδρία screen. Αυτό λειτουργεί μέχρι να αποσυνδεθείτε, να γίνει επανεκκίνηση του server ή να καταρρεύσει το πρόγραμμα. Τότε έχει χαθεί, και κανείς δεν το αντιλαμβάνεται.

Ένα πρόγραμμα που πρέπει να εκτελείται πάντα, πρέπει να είναι υπηρεσία systemd. Τότε:

  • ξεκινά αυτόματα κατά την εκκίνηση του συστήματος·
  • το systemd το επανεκκινεί αν καταρρεύσει·
  • η έξοδός του καταγράφεται στο journal (μάθημα 6.2)·
  • εκτελείται με έναν χρήστη που επιλέγετε εσείς, με τα δικαιώματα που επιτρέπετε εσείς.

Ένα δικό σας αρχείο unit

Ας υποθέσουμε ότι έχετε μια μικρή εφαρμογή Node.js στο /opt/factuurapp, η οποία ακούει στο 127.0.0.1:3000. Αργότερα το nginx ή το Caddy θα τη δημοσιεύσει προς τα έξω (ενότητα 7).

Βήμα 1: ένας δικός της χρήστης χωρίς shell (μάθημα 3.2). Η εφαρμογή δεν χρειάζεται να είναι root και δεν χρειάζεται να συνδέεται:

anna@web1:~$ sudo adduser --system --group --home /opt/factuurapp --no-create-home factuurapp
anna@web1:~$ sudo chown -R factuurapp:factuurapp /opt/factuurapp/data

Ο ίδιος ο κώδικας μπορεί να παραμείνει ιδιοκτησία του root (η εφαρμογή δεν χρειάζεται να τροποποιεί τον εαυτό της)· μόνο ο φάκελος στον οποίο γράφει ανήκει στον χρήστη της υπηρεσίας.

Βήμα 2: το αρχείο unit. Τα δικά σας units τα τοποθετείτε στο /etc/systemd/system/:

# /etc/systemd/system/factuurapp.service
[Unit]
Description=Factuurapp (Node.js)
After=network-online.target
Wants=network-online.target

[Service]
User=factuurapp
Group=factuurapp
WorkingDirectory=/opt/factuurapp
EnvironmentFile=/etc/factuurapp/env
ExecStart=/usr/bin/node /opt/factuurapp/server.js
Restart=on-failure
RestartSec=5s

NoNewPrivileges=true
ProtectSystem=strict
ProtectHome=true
PrivateTmp=true
ReadWritePaths=/opt/factuurapp/data

[Install]
WantedBy=multi-user.target

Τα τρία τμήματα:

  • [Unit]: περιγραφή και σειρά εκκίνησης. Το After=network-online.target μαζί με το Wants= εξασφαλίζει ότι η υπηρεσία ξεκινά μόνο όταν το δίκτυο είναι διαθέσιμο.
  • [Service]: πώς εκτελείται το πρόγραμμα. Το ExecStart με την πλήρη διαδρομή (το systemd δεν χρησιμοποιεί διαδρομή αναζήτησης όπως το shell σας). Τα User= και Group= καθορίζουν με ποιον χρήστη. Το EnvironmentFile διαβάζει ρυθμίσεις, όπως έναν κωδικό πρόσβασης βάσης δεδομένων, από ένα ξεχωριστό αρχείο, ώστε να μην βρίσκονται μέσα στο unit.
  • [Install]: τι κάνει το enable. Το WantedBy=multi-user.target σημαίνει: να ξεκινά μαζί με μια κανονική εκκίνηση του συστήματος.

Βήμα 3: τα μυστικά χωριστά, με αυστηρά δικαιώματα.

anna@web1:~$ sudo mkdir /etc/factuurapp
anna@web1:~$ sudo install -m 600 -o root -g root /dev/null /etc/factuurapp/env
anna@web1:~$ sudoedit /etc/factuurapp/env

Περιεχόμενο για παράδειγμα DATABASE_URL=postgres://factuur:...@127.0.0.1/factuur. Το systemd διαβάζει το αρχείο ως root πριν μεταβεί στον χρήστη της υπηρεσίας, επομένως αρκεί 600 με ιδιοκτήτη τον root.

Βήμα 4: φόρτωση, εκκίνηση, έλεγχος.

anna@web1:~$ sudo systemctl daemon-reload
anna@web1:~$ sudo systemctl enable --now factuurapp
anna@web1:~$ systemctl status factuurapp
anna@web1:~$ journalctl -u factuurapp -f

Επιλογές ασφαλείας: μικρός κόπος, μεγάλη διαφορά

Οι τέσσερις γραμμές κάτω από το RestartSec στο παράδειγμα περιορίζουν τι μπορεί να κάνει η υπηρεσία, ακόμη κι αν κάποιος βρει ένα κενό ασφαλείας στην εφαρμογή σας:

ΕπιλογήΑποτέλεσμα
NoNewPrivileges=trueη διεργασία και οι θυγατρικές της δεν μπορούν ποτέ να αποκτήσουν περισσότερα δικαιώματα (ούτε μέσω sudo ή προγραμμάτων setuid)
ProtectSystem=strictολόκληρο το σύστημα αρχείων είναι μόνο για ανάγνωση για την υπηρεσία, εκτός από όσα επιτρέπετε με το ReadWritePaths=
ProtectHome=trueτα /home, /root και /run/user είναι αόρατα
PrivateTmp=trueένα δικό της, κενό /tmp που δεν βλέπουν άλλα προγράμματα

Το systemd μπορεί να αξιολογήσει το unit σας:

anna@web1:~$ systemd-analyze security factuurapp
...
→ Overall exposure level for factuurapp.service: 4.9 OK 🙂

Όσο χαμηλότερος ο αριθμός, τόσο καλύτερα. Μια υπηρεσία χωρίς επιλογές βαθμολογείται γύρω στο 9 ("UNSAFE"). Δεν χρειάζεται να φτάσετε στο μηδέν: κάθε επιλογή που προσθέτετε μπορεί να χαλάσει κάτι που χρειάζεται η εφαρμογή. Προσθέστε τις μία μία και δοκιμάστε μετά από κάθε βήμα. Αν κάτι σταματήσει να λειτουργεί, συνήθως θα το δείτε στο journal ("Read-only file system", "Permission denied").

Προγραμματισμός εργασιών: timers

Για κάτι που πρέπει να γίνεται σε σταθερές ώρες (ένα αντίγραφο ασφαλείας, ένα script καθαρισμού, μια αναφορά) χρειάζεστε ένα timer. Ένα systemd timer αποτελείται από δύο units με το ίδιο όνομα: ένα .service που λέει τι πρέπει να γίνει και ένα .timer που λέει πότε.

# /etc/systemd/system/opruimen.service
[Unit]
Description=Oude exportbestanden opruimen

[Service]
Type=oneshot
User=factuurapp
ExecStart=/usr/bin/find /opt/factuurapp/data/export -type f -mtime +30 -delete
# /etc/systemd/system/opruimen.timer
[Unit]
Description=Dagelijks oude exportbestanden opruimen

[Timer]
OnCalendar=*-*-* 03:15:00
RandomizedDelaySec=10m
Persistent=true

[Install]
WantedBy=timers.target

Το Type=oneshot σημαίνει: το πρόγραμμα εκτελείται και μετά τελειώνει. Το OnCalendar είναι το χρονοδιάγραμμα: κάθε μέρα στις 03:15. Μπορείτε επίσης να γράψετε daily, weekly ή Mon *-*-* 02:00· το systemd-analyze calendar "Mon *-*-* 02:00" δείχνει πότε θα είναι η επόμενη φορά. Το Persistent=true είναι σημαντικό: αν ο server ήταν κλειστός στις 03:15, η εργασία εκτελείται αμέσως μετά την εκκίνηση. Το RandomizedDelaySec διασπείρει λίγο τη στιγμή έναρξης.

Την ενεργοποίηση την κάνετε με το timer, όχι με το service:

anna@web1:~$ sudo systemctl daemon-reload
anna@web1:~$ sudo systemctl enable --now opruimen.timer
anna@web1:~$ systemctl list-timers opruimen
NEXT                        LEFT     LAST PASSED UNIT           ACTIVATES
Tue 2026-11-10 03:19:42 CET 15h left -    -      opruimen.timer opruimen.service
anna@web1:~$ sudo systemctl start opruimen.service    # μία χειροκίνητη δοκιμή τώρα
anna@web1:~$ journalctl -u opruimen.service

Και το cron;

Το cron είναι το παλαιότερο, απλούστερο εργαλείο και εξακολουθεί να λειτουργεί μια χαρά. Μια γραμμή στο crontab ενός χρήστη (crontab -e):

15 3 * * * /usr/local/bin/opruimen.sh

Τα πέντε πεδία είναι λεπτό, ώρα, ημέρα του μήνα, μήνας και ημέρα της εβδομάδας. Πλεονεκτήματα και μειονεκτήματα δίπλα δίπλα:

cronsystemd timer
Ρύθμισημία γραμμήδύο αρχεία
Χαμένη εκτέλεση (server κλειστός)παραλείπεταιμε Persistent=true εκτελείται αργότερα
Έξοδος και σφάλματαμέσω email, αν ο server μπορεί να στείλει email· αλλιώς χάνονταιστο journal
Επιλογές ασφαλείας, χρήστηςμέσω του ίδιου του scriptόλα όσα προσφέρει το systemd (βλ. παραπάνω)
Πότε εκτελέστηκεδύσκολο να το δείτεsystemctl list-timers και το journal

Για έναν server που διαχειρίζεστε σοβαρά, τα timers είναι η καλύτερη επιλογή, ιδίως για αντίγραφα ασφαλείας (μάθημα 8.2): θέλετε να ξέρετε με βεβαιότητα ότι εκτελέστηκαν και τι ανέφεραν. Μια γραμμή cron που αποτυγχάνει σιωπηλά, την αντιλαμβάνεστε μόνο όταν χρειαστείτε το αντίγραφο ασφαλείας.

Σε AlmaLinux και Rocky Linux

Τα units και τα timers λειτουργούν ακριβώς με τον ίδιο τρόπο. Μία διαφορά: το SELinux μπορεί να εμποδίσει μια δική σας υπηρεσία που διαβάζει ή γράφει αρχεία σε σημείο που το SELinux δεν περιμένει, ή που ακούει σε μια ασυνήθιστη θύρα. Το μήνυμα βρίσκεται στο /var/log/audit/audit.log. Μην απενεργοποιήσετε το SELinux για να λύσετε το πρόβλημα· βρείτε τη σωστή ετικέτα ή κανόνα (για παράδειγμα με το semanage).

Σύνοψη

  • Ένα πρόγραμμα που πρέπει να εκτελείται πάντα, πρέπει να είναι υπηρεσία systemd: αυτόματη εκκίνηση, επανεκκίνηση σε περίπτωση κατάρρευσης, αρχεία καταγραφής στο journal.
  • Δικά σας units στο /etc/systemd/system/, με User= έναν δικό τους χρήστη χωρίς shell, μυστικά σε ένα EnvironmentFile με δικαιώματα 600.
  • Τα NoNewPrivileges, ProtectSystem=strict με ReadWritePaths, ProtectHome και PrivateTmp περιορίζουν τη ζημιά σε περίπτωση κενού ασφαλείας· το systemd-analyze security αξιολογεί το unit.
  • Ένα timer είναι ένα .service συν ένα .timer με OnCalendar· το Persistent=true αναπληρώνει τις χαμένες εκτελέσεις. Ενεργοποιήστε το timer, όχι το service.
  • Το cron εξακολουθεί να λειτουργεί, αλλά τα timers δίνουν καλύτερα αρχεία καταγραφής και δεν χάνουν εκτελέσεις.

Κουίζ

1. Η εφαρμογή σας εκτελείται ως υπηρεσία με User=root. Γιατί είναι καλύτερος ένας δικός της χρήστης;



2. Δημιουργήσατε ένα .service και ένα .timer. Τι ενεργοποιείτε με το enable --now;



3. Τι κάνει το Persistent=true σε ένα timer;



4. Προσθέτετε το ProtectSystem=strict και στη συνέχεια η εφαρμογή σας εμφανίζει "Read-only file system" κατά την αποθήκευση των uploads. Ποια είναι η σωστή λύση;



5. Πού τοποθετείτε τον κωδικό πρόσβασης της βάσης δεδομένων της δικής σας υπηρεσίας;



Άσκηση

Άσκηση O6.3: Μια δική σας υπηρεσία με timer. Δημιουργήστε στον server σας μια μικρή δική σας υπηρεσία με timer, για παράδειγμα ένα script που κάθε νύχτα γράφει τον ελεύθερο χώρο στον δίσκο και το systemctl --failed σε ένα αρχείο ή στο journal. Χρησιμοποιήστε δικό της χρήστη, Type=oneshot, τουλάχιστον δύο επιλογές ασφαλείας και Persistent=true. Δοκιμάστε με systemctl start, δείτε την έξοδο στο journal και σημειώστε τη βαθμολογία του systemd-analyze security. Επικολλήστε το .service και το .timer σας και απαντήστε στις ερωτήσεις της λίστας ελέγχου.

Άσκηση O6.3: Μια δική σας υπηρεσία με timer

Αυτή την άσκηση την κάνετε μόνοι σας: κανείς δεν την ελέγχει. Σημειώστε τι έχετε κάνει και επισημάνετε την άσκηση ως ολοκληρωμένη.




Τα τικ και οι σημειώσεις σας παραμένουν μόνο σε αυτό το πρόγραμμα περιήγησης· δεν τα στέλνουμε πουθενά. Αν έχετε εγγραφεί, αποθηκεύουμε στο Τα μαθήματά μου μόνο ότι έχετε ολοκληρώσει την άσκηση.

Για περαιτέρω μελέτη

Μια στιγμή…

Ρυθμίστε τα domains σας

Ρυθμίστε για κάθε domain τους nameservers, τη σύνδεση με το hosting σας και ποιος θα είναι ο κάτοχος.

Φόρτωση των domains σας…