DevOps Academy

Linux Advanced

פערי production שהקורסים מדלגים עליהם: SSH, firewall, systemd, logs, Bash מתקדם ו-networking

תיאוריה

⏱ ~50 דקות

מדוע Linux Advanced חיוני בשוק העבודה הישראלי

לפי סריקת שוק העבודה (אפריל 2026), Linux מופיע בשיעור גבוה ממשרות ה-DevOps בישראל — כישורי Linux מתקדמים נדרשים כתנאי בסיס כמעט בכל תפקיד infrastructure, platform engineering, ו-SRE. הקורסים הרגילים מלמדים ls, grep, ו-SSH בסיסי, ועוצרים שם. אבל בראיון ובעבודה האמיתית, המראיינים בודקים: האם אתה יודע לנהל מפתחות SSH בצוות? איך מגנים על שרת מ-brute-force? איך כותבים systemd unit ל-service שלא יפול? איך מונעים disk exhaustion מ-logs? איך מבצעים debug לבעיות רשת בproduction?

הסעיפים הבאים מכסים את עשרת הפערים שסריקת המשרות הישראלית זיהתה: SSH key rotation, UFW/iptables, fail2ban, systemd units, logrotate, Bash strict mode, flock, DNS debugging, TCP/IP troubleshooting, ו-sudo least-privilege. אלה הם בדיוק הנושאים שמבדילים בין DevOps junior שיודע להפעיל שרת לבין מי שיודע להפעיל אותו בצורה בטוחה ואמינה.

SSH key rotation וניהול authorized_keys

פער production

הקורסים מלמדים ssh-keygen פעם אחת. בproduction, מפתחות SSH הם credentials לכל דבר — ולכן חייבים לנהל אותם כמו passwords: לסובב, לבדוק, ולהסיר כשהם לא רלוונטיים.

**יצירת מפתח חדש (Ed25519 — מומלץ לproduction):**

# Ed25519 קצר יותר מ-RSA-4096 אך חזק לפחות כמוהו
ssh-keygen -t ed25519 -C "deploy@myservice-$(date +%Y-%m)" -f ~/.ssh/id_ed25519_deploy

**הוספת מפתח לשרת:**

ssh-copy-id -i ~/.ssh/id_ed25519_deploy.pub user@server
# או ידנית:
cat ~/.ssh/id_ed25519_deploy.pub >> ~/.ssh/authorized_keys

**ניהול authorized_keys בצוות — המקרה שהקורסים מדלגים עליו:**
כאשר מהנדס עוזב את הצוות, יש להסיר את המפתח שלו מכל השרתים. בשרת יחיד:

# זיהוי מפתח לפי comment (email/שם המשתמש שמוגדר ב-ssh-keygen -C)
grep 'john@company' ~/.ssh/authorized_keys
# הסרה:
sed -i '/john@company/d' ~/.ssh/authorized_keys

בfleet של שרתים — השתמשו בAnsible או ב-script מרכזי. עיקרון הזהב: authorized_keys שמנוהל ידנית על כל שרת בנפרד הוא security risk.

**הגבלת scope של מפתח** — כל שורה ב-authorized_keys יכולה לכלול אפשרויות:

# מפתח שמריץ רק פקודה אחת (deploy script)
command="/opt/deploy.sh",no-pty,no-agent-forwarding ssh-ed25519 AAAA... ci@github-actions
# מפתח שמותר רק מ-IP מסוים
from="203.0.113.10",no-x11-forwarding ssh-ed25519 AAAA... admin@company

**אימות תצורת SSH daemon:**

# ודא שהגדרות אלה קיימות ב-/etc/ssh/sshd_config
grep -E '^(PermitRootLogin|PasswordAuthentication|PubkeyAuthentication)' /etc/ssh/sshd_config
# PermitRootLogin no
# PasswordAuthentication no
# PubkeyAuthentication yes

# בדיקת syntax לפני reload:
sshd -t && systemctl reload sshd

UFW ו-iptables: ניהול חוקי firewall

פער production

כל שרת Ubuntu production רץ עם firewall. UFW (Uncomplicated Firewall) הוא frontend ל-iptables שמפשט את הניהול, אבל חיוני להבין גם את ה-iptables שמתחת.

**מצב UFW נוכחי:**

sudo ufw status verbose
# Status: active
# To                    Action      From
# 22/tcp                ALLOW IN    Anywhere
# 443/tcp               ALLOW IN    Anywhere
# 80/tcp                ALLOW IN    Anywhere

**הוספת כללים:**

# אפשר HTTPS מכל מקום
sudo ufw allow 443/tcp

# אפשר SSH רק מ-IP ספציפי (מומלץ לproduction)
sudo ufw allow from 203.0.113.10 to any port 22 proto tcp

# חסום IP ספציפי
sudo ufw deny from 198.51.100.0/24

# מחק כלל
sudo ufw delete allow 443/tcp

**הפעלת UFW בפעם הראשונה — סדר קריטי:**

# תמיד הוסף כלל ל-SSH לפני הפעלת UFW — אחרת תנעל את עצמך מחוץ לשרת!
sudo ufw allow 22/tcp
sudo ufw enable
# יש לאשר: Command may disrupt existing ssh connections. Proceed with operation (y|n)? y

**iptables — הבנת הבסיס:**
UFW כותב כללי iptables. להצגת הכללים בפועל:

sudo iptables -L -n -v --line-numbers
# Chain INPUT (policy DROP)
# num  pkts bytes target     prot opt in     out     source               destination
#   1  5421 2.1M  ACCEPT     all  --  lo     *       0.0.0.0/0            0.0.0.0/0
#   2  1823  98K  ACCEPT     tcp  --  *      *       0.0.0.0/0            0.0.0.0/0  tcp dpt:22

keyword חשוב: policy DROP לעומת ACCEPT. שרת production צריך INPUT policy DROP (הכחשה כברירת מחדל) עם ACCEPT רק לפורטים הנדרשים.

**debugging connection refused vs. connection timeout:**
- Connection refused: ה-firewall שולח RST — הפורט חסום בצד השרת עם REJECT
- Connection timeout: ה-packet נופל ללא תגובה — הפורט חסום עם DROP

# בדיקת ניתוב פאקטים:
sudo iptables -L INPUT -n -v | grep dpt:8080

fail2ban: הגנת brute-force על SSH

פער production

כל שרת עם פורט SSH פתוח לאינטרנט סופג ניסיונות כניסה רצופים — bots סורקים כל ה-IP space ומנסים שמות משתמש וסיסמאות ידועות. fail2ban קורא את ה-logs ועוצר תוקפים אוטומטית.

**התקנה וקינפוג בסיסי:**

sudo apt install fail2ban -y

# תמיד עבדו עם jail.local — לא jail.conf (שמוחלף בupgrades)
sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local

**הגדרת jail ל-SSH ב-jail.local:**

[sshd]
enabled  = true
port     = ssh
filter   = sshd
logpath  = /var/log/auth.log
maxretry = 3
findtime = 10m
bantime  = 1h
ignoreip = 127.0.0.1/8 ::1 203.0.113.10

הסברים:
- maxretry = 3 — לאחר 3 כשלות בתוך findtime, ה-IP נחסם
- findtime = 10m — חלון הזמן לספירת הכשלות
- bantime = 1h — משך החסימה. לproduction נוקשה: bantime = 1d או -1 (חסימה לצמיתות)
- ignoreip — IPs שלעולם לא ייחסמו (VPN של הצוות, monitoring servers)

**ניהול fail2ban בזמן אמת:**

# סטטוס כללי
sudo fail2ban-client status

# סטטוס jail ספציפי
sudo fail2ban-client status sshd
# Status for the jail: sshd
# |- Filter
# |  |- Currently failed: 2
# |  `- Total failed: 47
# `- Actions
#    |- Currently banned: 3
#    `- Total banned: 12

# שחרור IP שנחסם בטעות (למשל, המנהל שלך)
sudo fail2ban-client set sshd unbanip 203.0.113.10

# בדיקת IP ספציפי
sudo fail2ban-client get sshd banip | grep 198.51.100.5

**fail2ban לweb applications:**

[nginx-http-auth]
enabled = true
port    = http,https
filter  = nginx-http-auth
logpath = /var/log/nginx/error.log
maxretry = 5

fail2ban כותב חוקי iptables זמניים כדי לחסום IPs — ניתן לראות אותם עם sudo iptables -L f2b-sshd -n.

systemd unit files לשירותים ארוכי טווח

פער production

כל תהליך שצריך לרוץ באופן רציף בproduction צריך systemd unit — לא nohup, לא screen, לא tmux. systemd מטפל ב-restart אוטומטי, logging, dependency ordering, ו-resource limits.

**מבנה unit file בסיסי:**

# /etc/systemd/system/myapp.service
[Unit]
Description=My Production API Service
After=network-online.target
Wants=network-online.target

[Service]
Type=simple
User=myapp
Group=myapp
WorkingDirectory=/opt/myapp
ExecStart=/opt/myapp/venv/bin/python -m uvicorn main:app --host 0.0.0.0 --port 8000
Restart=on-failure
RestartSec=5s
StandardOutput=journal
StandardError=journal
SyslogIdentifier=myapp

# משתני סביבה (אל תכניסו secrets כאן — השתמשו ב-EnvironmentFile)
EnvironmentFile=/etc/myapp/env
Environment=PYTHONUNBUFFERED=1

# Resource limits
LimitNOFILE=65536
MemoryMax=512M
CPUQuota=50%

[Install]
WantedBy=multi-user.target

**הפעלה וניהול:**

# reload הגדרות daemon (חובה אחרי כל שינוי ב-unit file)
sudo systemctl daemon-reload

# הפעלה + enable לboot
sudo systemctl enable --now myapp

# סטטוס עם logs אחרונים
sudo systemctl status myapp

# קריאת logs
sudo journalctl -u myapp -f              # follow real-time
sudo journalctl -u myapp --since today  # היום בלבד
sudo journalctl -u myapp -n 100         # 100 שורות אחרונות

**Type=simple vs. Type=forking vs. Type=notify:**
- simple — התהליך הראשי הוא ה-service. מומלץ לרוב ה-cases.
- forking — לתהליכים שמבצעים fork ועוברים לרקע (legacy daemons).
- notify — התהליך שולח sd_notify(READY=1) כשמוכן; systemd ממתין לאות זה.

**ExecStartPre לbefore-start checks:**

[Service]
ExecStartPre=/usr/bin/test -f /etc/myapp/env
ExecStartPre=/opt/myapp/scripts/check-db-connection.sh
ExecStart=/opt/myapp/venv/bin/python -m uvicorn main:app

אם ExecStartPre נכשל — systemd לא מפעיל את ה-service ורושם את השגיאה.

logrotate: ניהול application logs

פער production

ללא logrotate, application logs ממלאים את ה-disk. logrotate הוא כלי שרץ ב-cron (יומי בברירת מחדל) ומנהל rotation, compression, ושמירת היסטוריה.

**קינפוג logrotate לapplication:**

# /etc/logrotate.d/myapp
/var/log/myapp/*.log {
    daily
    rotate 14
    compress
    delaycompress
    missingok
    notifempty
    copytruncate
    dateext
    dateformat -%Y%m%d
    su myapp myapp
}

הסברים:
- daily — rotate כל יום. חלופות: weekly, monthly, size 100M
- rotate 14 — שמור 14 קבצים היסטוריים (2 שבועות)
- compress — דחס קבצים ישנים עם gzip
- delaycompress — אל תדחס את ה-rotate האחרון מיד (אפליקציות שמחזיקות file handle פתוח)
- missingok — אל תתריע אם הקובץ לא קיים
- notifempty — אל תבצע rotate לקובץ ריק
- copytruncate — העתק ואז truncate (לאפליקציות שלא תומכות ב-SIGHUP reopen)
- dateext + dateformat — שמות קבצים עם תאריך: app.log-20260417.gz

**הרצה ידנית לבדיקה:**

# dry-run: ראה מה יקרה בלי לבצע
sudo logrotate -d /etc/logrotate.d/myapp

# הרצה מיידית (bypass בדיקת 24 שעות)
sudo logrotate -f /etc/logrotate.d/myapp

# בדיקת סטטוס (מתי בוצע rotate לאחרונה)
cat /var/lib/logrotate/status | grep myapp

**postrotate לSIGHUP:**
אפליקציות שכותבות ישירות לקובץ צריכות לקבל SIGHUP כדי לפתוח קובץ חדש:

/var/log/myapp/*.log {
    daily
    rotate 14
    compress
    delaycompress
    postrotate
        systemctl reload myapp 2>/dev/null || true
    endscript
}

Bash strict mode ו-trap: scripts שלא מתפוצצים בשקט

פער production

הבעיה עם Bash scripts שנכתבים בלי strict mode: פקודה שנכשלת לא עוצרת את ה-script. ב-CI/CD pipeline, deployment script שמדלג בשקט על שגיאה יכול להשאיר סביבת production במצב חלקי.

**strict mode — template סטנדרטי:**

#!/usr/bin/env bash
set -euo pipefail
IFS=$'\n\t'

הסבר כל דגל:
- set -e (errexit) — עצור ה-script כאשר פקודה מחזירה exit code שאינו 0
- set -u (nounset) — עצור כאשר משתנה לא מוגדר משמש (מונע rm -rf $TYPO/)
- set -o pipefail — pipe נכשל אם אחת מהפקודות בו נכשלה (בלי דגל זה, false | true מחזיר 0)
- IFS=$'\n\t' — Internal Field Separator מוגדר ל-newline ו-tab (לא space) — מונע split שגוי על שמות קבצים עם רווחים

**trap לcleanup:**
trap מאפשר לרשום function שתרוץ כשה-script יוצא — בין אם בהצלחה, בשגיאה, או ב-Ctrl+C.

#!/usr/bin/env bash
set -euo pipefail

# Cleanup function
cleanup() {
    local exit_code=$?
    echo "[cleanup] Script exited with code: $exit_code"
    # מחיקת קבצים זמניים
    rm -f /tmp/deploy_lock_$$
    rm -f /tmp/deploy_payload_$$.json
    if [[ $exit_code -ne 0 ]]; then
        echo "[ERROR] Deployment failed — rolling back"
        # rollback logic here
    fi
}

# רשום cleanup לכל מקרי יציאה
trap cleanup EXIT
trap 'echo "[SIGINT] Interrupted"; exit 130' INT
trap 'echo "[SIGTERM] Terminated"; exit 143' TERM

# ... שאר ה-script ...
TMP_FILE=$(mktemp /tmp/deploy_payload_$$.json)
echo '{"version": "1.4.2"}' > "$TMP_FILE"
# trap יטפל במחיקה בכל מקרה

**דוגמה מבוססת production — deploy script עם strict mode:**

#!/usr/bin/env bash
set -euo pipefail

APP_DIR="/opt/myapp"
BACKUP_DIR="/opt/myapp-backups"

cleanup() {
    echo "Cleaning temp files..."
    rm -f /tmp/new_release_$$.tar.gz
}
trap cleanup EXIT

if [[ $# -lt 1 ]]; then
    echo "Usage: $0 <version>" >&2
    exit 1
fi

VERSION="$1"
echo "Deploying version: $VERSION"

# כל שגיאה כאן תפסיק ותריץ cleanup
cp -r "$APP_DIR" "$BACKUP_DIR/$VERSION-$(date +%s)"

Bash flock: מניעת הרצה מקבילה של scripts

פער production

בעיה קלאסית: cron job שרץ כל דקה, אך לפעמים לוקח 90 שניות להשלמה. ללא הגנה, שני instances רצים במקביל ויוצרים race condition. flock פותר זאת.

**שיטה 1: flock בתוך ה-script:**

#!/usr/bin/env bash
set -euo pipefail

LOCK_FILE="/var/lock/myapp-sync.lock"

# נסה לקבל lock. -n = non-blocking (אל תחכה)
if ! flock -n "$LOCK_FILE" true; then
    echo "Another instance is already running. Exiting."
    exit 0
fi

# כאן בטוח שרק instance אחד רץ
exec flock -n "$LOCK_FILE" bash << 'SCRIPT'
    echo "Doing exclusive work..."
    sleep 10
    echo "Done."
SCRIPT

**שיטה 2: flock כ-wrapper בcron (מומלץ יותר):**

# /etc/cron.d/myapp-sync
* * * * * myapp flock -n /var/lock/myapp-sync.lock /opt/myapp/scripts/sync.sh >> /var/log/myapp/sync.log 2>&1

**שיטה 3: שימוש ב-file descriptor (הנפוצה ביותר):**

#!/usr/bin/env bash
set -euo pipefail

exec 9>/var/lock/myapp-sync.lock

if ! flock -n 9; then
    echo "Script already running (PID $(cat /var/lock/myapp-sync.lock)). Exiting." >&2
    exit 0
fi

# שמור PID לקובץ ה-lock לdebug
echo $$ >&9

echo "Running sync at $(date)"
# ... עבודה בלעדית ...

**בדיקת lock קיים:**

# בדוק אם process מחזיק lock
fuser /var/lock/myapp-sync.lock
# 12345  <- PID המחזיק ב-lock

# או:
lsof /var/lock/myapp-sync.lock

flock מבוסס על kernel-level advisory locks — עובד בין processes שונים על אותו host, לא ב-distributed environments. לlock מבוזר (multi-server), יש להשתמש ב-Redis SET NX או Zookeeper.

DNS debugging עם dig ו-TTL propagation

פער production

DNS הוא אחד הנושאים שהכי הרבה DevOps אנשים מסתבכים בו בproduction. deployment שכולל שינוי DNS record יכול לקחת דקות עד שעות להתפשט — והמוקד צריך לדעת למה.

**dig — כלי ה-DNS הבסיסי לproduction:**

# שאילתה בסיסית
dig example.com A

# הצג רק את ה-answer section (ללא noise)
dig +short example.com A
# 203.0.113.10

# שאילתה לservers ספציפי (עוקף local cache)
dig @8.8.8.8 example.com A        # Google DNS
dig @1.1.1.1 example.com A        # Cloudflare DNS
dig @ns1.example.com example.com A # שאל את ה-authoritative server ישירות

# הצג TTL
dig +ttl example.com A
# example.com.    300    IN  A  203.0.113.10
#                 ^^^--- TTL בשניות (5 דקות)

# רשומות נוספות
dig example.com MX    # mail exchange
dig example.com NS    # nameservers
dig example.com TXT   # SPF, DKIM, verification
dig example.com AAAA  # IPv6

**TTL propagation — הסבר לproduction:**
TTL (Time To Live) הוא הזמן שב-resolver (הDNS של ISP המשתמש) שומר את התשובה ב-cache. אם TTL = 3600 (שעה) ומשנים את ה-A record, חלק מהמשתמשים יראו את הrecord הישן עד שעה!

אסטרטגיה לפני migration:

# שלב 1 (24-48 שעות לפני): הורד TTL ל-300 שניות (5 דקות)
# שלב 2: בצע את ה-migration
# שלב 3: לאחר ווידוא, הגבה TTL בחזרה ל-3600

# בדוק את ה-TTL הנוכחי:
dig +ttl example.com A | grep -v '^;' | grep 'IN  A'

**trace מלא של DNS resolution:**

# +trace מראה כל שלב: root → TLD → authoritative
dig +trace example.com A

**debugging נפוץ:**

# בדוק מה ה-resolver המקומי מחזיר
dig example.com A

# אם שונה ממה שאתה מצפה — שאל authoritative ישירות
dig @ns1.example.com example.com A

# flush local DNS cache (Ubuntu/systemd-resolved)
sudo resolvectl flush-caches
# או:
sudo systemd-resolve --flush-caches

TCP/IP troubleshooting עם ss ו-tcpdump

פער production

כשמשהו לא עובד ברשת בproduction, ss ו-tcpdump הם הכלים הראשונים שמגיעים.

**ss — replacement מודרני ל-netstat:**

# כל ה-listening ports (TCP)
ss -tlnp
# State   Recv-Q  Send-Q  Local Address:Port   Peer Address:Port   Process
# LISTEN  0       128     0.0.0.0:22            0.0.0.0:*           users:(("sshd",pid=1234,fd=3))
# LISTEN  0       511     0.0.0.0:443           0.0.0.0:*           users:(("nginx",pid=5678,fd=6))

# כל החיבורים הפעילים
ss -tnp

# connections ל-port ספציפי
ss -tnp sport = :8080

# connections מ-IP ספציפי
ss -tnp dst 203.0.113.10

# הצג socket statistics (drops, errors)
ss -s

פירוש flags:
- -t — TCP (השתמשו -u ל-UDP)
- -l — listening sockets בלבד
- -n — numeric (אל תפשור שמות)
- -p — הצג process name ו-PID

**tcpdump — capture packets בזמן אמת:**

# צפה בכל traffic על ממשק eth0
sudo tcpdump -i eth0

# filter ל-port ספציפי
sudo tcpdump -i eth0 port 8080

# filter ל-IP ספציפי
sudo tcpdump -i eth0 host 203.0.113.10

# שמור ל-file לanalysis בWireshark
sudo tcpdump -i eth0 port 443 -w /tmp/capture.pcap

# קרא pcap file (Wireshark GUI, או בcli:)
tcpdump -r /tmp/capture.pcap

**debugging flow מוכח לproduction:**

# שלב 1: האם process מאזין?
ss -tlnp | grep ':8080'

# שלב 2: האם firewall חוסם?
sudo iptables -L INPUT -n | grep 8080

# שלב 3: האם ה-connection מגיע?
sudo tcpdump -i any port 8080 -n -c 10

# שלב 4: מה ה-response?
curl -v http://localhost:8080/health

**ESTABLISHED connections תקועים:**

# ראה connections ב-state ESTABLISHED עם זמן
ss -tnp state established | awk 'NR>1 {print $4, $5, $6}'

# TIME_WAIT connections מרובים — סימן לthroughput גבוה
ss -tn state time-wait | wc -l

Linux users ו-sudo: least-privilege management

פער production

עיקרון least-privilege: כל user ו-process צריך רק את ההרשאות המינימליות הנדרשות למשימתו. בproduction, הרצת services כ-root היא anti-pattern מסוכן.

**יצירת service user ייעודי:**

# יצירת system user (ללא home directory, ללא login shell)
sudo useradd --system --no-create-home --shell /usr/sbin/nologin --comment "MyApp Service Account" myapp

# ודא שנוצר נכון
getent passwd myapp
# myapp:x:998:998:MyApp Service Account:/:/usr/sbin/nologin

# הגדר בעלות על application directory
sudo chown -R myapp:myapp /opt/myapp
sudo chmod 750 /opt/myapp

**sudo configuration — /etc/sudoers:**

# תמיד ערוך עם visudo (בדיקת syntax אוטומטית)
sudo visudo

# או קובץ נפרד ב-/etc/sudoers.d/ (מומלץ)
sudo visudo -f /etc/sudoers.d/deploy-team

**דוגמאות sudoers production:**

# מאפשר ל-deploy user לrestart service ספציפי בלבד
deploy ALL=(ALL) NOPASSWD: /usr/bin/systemctl restart myapp

# מאפשר ל-monitoring user לקרוא logs בלבד
monitor ALL=(ALL) NOPASSWD: /usr/bin/journalctl -u myapp *

# מאפשר ל-CI/CD user לreload nginx בלבד
ci ALL=(ALL) NOPASSWD: /usr/bin/systemctl reload nginx

**audit של users והרשאות:**

# מי הusers עם login shell (אמורים להיות בני אדם בלבד)
grep -v '/nologin\|/false' /etc/passwd | cut -d: -f1,6,7

# מי יש ב-sudo group
getent group sudo

# בדיקת SUID/SGID files (פוטנציאל privilege escalation)
find / -perm -4000 -o -perm -2000 2>/dev/null | grep -v proc

# בדיקת world-writable directories
find /opt /etc /var -type d -perm -002 2>/dev/null

**umask ל-service accounts:**

# הוסף ל-/etc/systemd/system/myapp.service
[Service]
UMask=0027  # קבצים חדשים: rw-r----- (640), directories: rwxr-x--- (750)

security summary: שרת production לא אמור להיות ניתן לlogin כ-root ישירות (PermitRootLogin no), כל service צריך user משלו ללא login shell, וסיסמאות ב-sudo (NOPASSWD) מוגבלות לפקודות ספציפיות בלבד.


תרגול מעשי

1. ניתוח קובץ authorized_keys ואיתור מפתחות ללא הגבלת scope

פער production

קובץ authorized_keys מדומה מכיל 4 מפתחות SSH. עבד אותו עם grep ו-awk כדי לזהות: (1) כמה מפתחות כוללים הגבלת command= (מפתחות מוגבלי scope), (2) כמה מפתחות אין להם שום אפשרות — גישה מלאה בלי הגבלה. הדפס PASS או FAIL לכל בדיקה. זוהי ביקורת authorized_keys — משימה שגרתית לאחר offboarding של מהנדס.

2. ניתוח systemd unit file ואימות הגדרות production

פער production

unit file מדומה מכיל הגדרות service. עבד אותו עם grep ו-python3 כדי לאמת: (1) Restart מוגדר ל-on-failure, (2) User מוגדר ולא root, (3) EnvironmentFile קיים (ולא environment variables מוגדרים ישירות בunit), (4) LimitNOFILE מוגדר מעל 1024. כל בדיקה תדפיס PASS או FAIL. זו ביקורת unit file לפני פריסה ל-production.

3. ניתוח /etc/passwd לזיהוי service accounts ללא login shell

פער production

קרא את /etc/passwd וזהה: (1) כמה users מוגדרים עם login shell אמיתי (/bin/bash או /bin/sh) — אלה אמורים להיות בני אדם בלבד, (2) כמה users מוגדרים עם /usr/sbin/nologin או /bin/false (service accounts תקניים), (3) אם יש service accounts חשודים — users עם UID מעל 999 (non-system) שמוגדרים עם login shell. הדפס ממצאים ו-PASS/FAIL לכל בדיקה.


שאלות חיבור

חבר את מה שלמדת בנושא זה לנושאים קודמים. אין תשובה אחת נכונה — חשיבה ביקורתית היא המטרה.

שאלת חיבור 1

ב-Linux Advanced למדת על systemd unit files לניהול שירותים ארוכי טווח — כולל Restart=on-failure, EnvironmentFile לsecrets, ו-ExecStartPre לvalidation. ב-Docker למדת על Docker Compose עם restart: unless-stopped, env_file, ו-depends_on עם condition: service_healthy. כיצד שתי הגישות משלימות זו את זו בסביבת production שמריצה גם containers וגם native processes, ומה עדיין נשאר באחריות systemd גם כשרוב האפליקציות כבר ב-Docker?

מחבר ל:
Docker

שאלת חיבור 2

ב-Linux Advanced למדת על Bash strict mode (set -euo pipefail) ו-trap cleanup handlers. ב-CI/CD pipelines (GitHub Actions, Jenkins) כל step הוא בעצם Bash script שרץ בסביבה מבוקרת. כיצד היעדר strict mode ב-deployment scripts גורם לbugs שקשה לאתר ב-CI/CD, ואיך trap משתלב עם הדרישה של pipelines לrollback אוטומטי כשstep נכשל?

מחבר ל:
CI/CD

מוכן לבחינה?

בצע הערכה תיאורטית, תרגול CLI ושאלות חיבור כדי לסיים את הנושא.