Найти в Дзене
Сисадмин

Как сделать из старичка сервачка "качка"

У тебя в углу уже давно стоит старый списанный сервер? Горячий как чайник, медленный как улитка и с памятью, как у рыбки. Но это не повод вешать на него табличку «выведен из эксплуатации». Это повод превратить его в ночного "качка", который тихо, аккуратно и с минимальным стрессом для железа будет качать браузеры, ISO-образы Debian/Ubuntu и всё, что может понадобиться утром человеку, у которого есть руки и желание поставить ОС. Ночной план: Установка (Debian/Ubuntu): sudo apt update
sudo apt install -y wget aria2 coreutils mailutils Пример запуска с низким приоритетом: nice -n 19 ionice -c3 wget -c --limit-rate=500k "https://example.com/file.iso" Здесь 500k — максимум 500 KB/s, чтобы не забирать весь канал. /srv/nightfetch/
├─ downloads/ # сюда качаем
├─ logs/ # лог выполнения
├─ tmp/ # временные файлы
└─ hooks/ # скрипты postprocess (опц.) Создать: sudo mkdir -p /srv/nightfetch/{downloads,logs,tmp,hooks}
sudo chown -R $(whoami):$(whoa
Оглавление
Как сделать сервер для скачивания файлов
Как сделать сервер для скачивания файлов

У тебя в углу уже давно стоит старый списанный сервер? Горячий как чайник, медленный как улитка и с памятью, как у рыбки. Но это не повод вешать на него табличку «выведен из эксплуатации». Это повод превратить его в ночного "качка", который тихо, аккуратно и с минимальным стрессом для железа будет качать браузеры, ISO-образы Debian/Ubuntu и всё, что может понадобиться утром человеку, у которого есть руки и желание поставить ОС.

Идея в двух словах (и одной кружке чая)

Ночной план:

  1. Включаем загрузчик в 2–4 утра, когда сеть свободна и соседи не ругаются.
  2. Запускаем скрипт, который по расписанию качает нужные файлы (wget/aria2c).
  3. Ограничиваем I/O и CPU (ionice/nice, лимиты), чтобы сервер не умер от стресса.
  4. Проверяем контрольные суммы, записываем лог и удаляем старьё через 30 дней (для серверов у которых жим-жим с местом).
  5. Утром — свежие ISO и браузеры у тебя уже на районе.

Что нужно на сервере (минимум)

  • Linux (подойдёт любой лёгкий дистрибутив; примеры команд для Debian/Ubuntu ниже).
  • Достаточно свободного диска (средний размер 1 файла ISO ≈ 700 МБ–4 ГБ).
  • Утилиты: wget, aria2 (или только wget), screen/tmux (опционально), mailx (оповещения).
  • Права root для установки и cron/systemd.

Установка (Debian/Ubuntu):

sudo apt update
sudo apt install -y wget aria2 coreutils mailutils

Как экономно использовать ресурсы (важно для дохлика)

  • nice: уменьшает приоритет CPU.
  • ionice -c3: — background best effort с наименьшим приоритетом.
  • --limit-rate (wget) или --max-overall-download-limit (aria2) — ограничь пропускную способность.
  • --max-concurrent-downloads / --max-connection-per-server в aria2 — поставь малые значения (1–2).
  • Используй rsync для синхронизации только новых/обновлённых файлов (для зеркал).
  • Запускай ночью через cron или systemd-таймер.

Пример запуска с низким приоритетом:

nice -n 19 ionice -c3 wget -c --limit-rate=500k "https://example.com/file.iso"

Здесь 500k — максимум 500 KB/s, чтобы не забирать весь канал.

Структура каталогов (как пример)

/srv/nightfetch/
├─ downloads/ # сюда качаем
├─ logs/ # лог выполнения
├─ tmp/ # временные файлы
└─ hooks/ # скрипты postprocess (опц.)

Создать:

sudo mkdir -p /srv/nightfetch/{downloads,logs,tmp,hooks}
sudo chown -R $(whoami):$(whoami) /srv/nightfetch
chmod +x /srv/nightfetch/nightfetch-debian.sh

Сам скрипт nightfetch-debian.sh

#!/usr/bin/env bash
set -euo pipefail
# CONFIG
BASE="/srv/nightfetch"
DL="$BASE/downloads"
LOG="$BASE/logs/nightfetch-$(date +%F).log"
TMP="$BASE/tmp"
LOCKDIR="/var/lock/nightfetch-debian.lock"
MAX_AGE_DAYS=30
CDIMAGE_URL="https://cdimage.debian.org/debian-cd/current/amd64/iso-cd/"
# wget options: докачка, терпимость к сети, ограничение скорости
WGET_OPTS="--continue --tries=5 --waitretry=10 --timeout=30 --limit-rate=500k --no-verbose"
# Logging to file (append)
mkdir -p "$BASE/logs" "$BASE/tmp" "$BASE/downloads"
exec >>"$LOG" 2>&1
echo "[$(date +'%F %T')] START"
# простая блокировка (директория)
if ! mkdir "$LOCKDIR" 2>/dev/null; then
echo "Another run is active, exiting."
exit 0
fi
trap 'rmdir "$LOCKDIR"; echo "Lock removed";' EXIT
cd "$TMP"
# 1) Попытка скачать SHA256SUMS прямо (несколько вариантов)
sha_candidates=( "SHA256SUMS" "SHA256SUMS.asc" "SHA256SUMS.sign" "SHA256SUMS.txt" )
fetched_sha=""
for name in "${sha_candidates[@]}"; do
url="${CDIMAGE_URL}${name}"
echo "Trying to fetch $url"
if wget $WGET_OPTS -O "$TMP/$name" "$url" 2>/dev/null; then
# проверим, есть ли в файле ссылки на .iso (чтобы не принять HTML-страницу)
if grep -q '\.iso' "$TMP/$name"; then
fetched_sha="$TMP/$name"
echo "Fetched checksum file: $name"
break
else
echo "Downloaded $name but it doesn't contain .iso entries — removing"
rm -f "$TMP/$name"
fi
else
echo "No $name at $url"
fi
done
# 2) fallback: если SHA-файла нет — спарсить index.html и собрать список .iso
iso_list=""
if [ -z "$fetched_sha" ]; then
echo "No SHA256SUMS found — falling back to scraping index HTML"
wget $WGET_OPTS -O "$TMP/index.html" "$CDIMAGE_URL" || true
if grep -q '\.iso' "$TMP/index.html"; then
# вытащим href-ы и оставим только имена файлов
iso_list=$(grep -oP 'href="[^"]+\.iso"' "$TMP/index.html" \
| sed -E 's/href="([^"]+)"/\1/' \
| sed 's|.*/||' \
| sort -u)
if [ -z "$iso_list" ]; then
echo "No .iso links parsed from index.html, aborting."
exit 1
fi
echo "Parsed $(echo "$iso_list" | wc -l) iso entries from index.html"
else
echo "Index HTML doesn't contain .iso links — aborting."
exit 1
fi
fi
# 3) Если у нас есть SHA-файл — парсим имена iso
if [ -n "$fetched_sha" ]; then
# Преобразуем возможные форматы (удалим ведущие * или ./)
iso_list=$(awk '/\.iso/ {print $2}' "$fetched_sha" \
| sed 's/^[*]//' | sed 's|^\./||' | sort -u)
echo "Found $(echo "$iso_list" | wc -w) iso entries in $fetched_sha"
fi
# 4) Скачиваем: только отсутствующие или с неверной sha
cd "$DL"
for iso in $iso_list; do
[ -z "$iso" ] && continue
# если существует — проверим sha (только если есть файл SHA в tmp)
need_download=1
if [ -f "$DL/$iso" ] && [ -n "$fetched_sha" ]; then
expected=$(awk -v fn="$iso" '$2==fn {print $1}' "$fetched_sha" || true)
if [ -n "$expected" ]; then
actual=$(sha256sum "$DL/$iso" 2>/dev/null | awk '{print $1}' || true)
if [ "$expected" = "$actual" ]; then
echo "$iso already present and checksum OK, skipping"
need_download=0
else
echo "$iso exists but checksum mismatch (will re-download)"
mv "$DL/$iso" "$DL/$iso.part.$(date +%s)" || rm -f "$DL/$iso"
need_download=1
fi
else
echo "No checksum entry for $iso in fetched SHA file (will re-download to be safe)"
need_download=1
fi
elif [ -f "$DL/$iso" ]; then
echo "$iso already exists (no checksum available) — skipping"
need_download=0
fi
if [ "$need_download" -eq 1 ]; then
url="${CDIMAGE_URL}${iso}"
echo "Downloading $iso from $url"
# низкий приоритет CPU/I/O
nice -n 19 ionice -c3 wget $WGET_OPTS -O "$DL/$iso" "$url" || echo "wget failed for $iso" >&2
fi
done
# 5) Проверка контрольных сумм (если мы скачали SHA-файл) — запустим в каталоге download
if [ -n "$fetched_sha" ]; then
cp -f "$fetched_sha" "$DL/SHA256SUMS"
echo "Verifying checksums:"
sha256sum -c "$DL/SHA256SUMS" 2>&1 | tee -a "$LOG" || echo "Some checks failed or files missing (see output above)."
fi
# 6) Ротация (удаляем старые файлы) — опционально
if [ "$MAX_AGE_DAYS" -gt 0 ]; then
echo "Rotating files older than ${MAX_AGE_DAYS} days..."
find "$DL" -type f -mtime +"$MAX_AGE_DAYS" -print -delete || true
fi
echo "[$(date +'%F %T')] END"

Пара заметок / советы

  • Если тебе нужно всё архивное (весь archive/), лучше не парсить HTML — используй rsync://cdimage.debian.org/cdimage/archive/ с rsync. Это быстрее и надёжнее для больших зеркал.
  • Если у тебя мало диска и ты хочешь все старые и новые ISO — учитывай, что это может быть сотни гигабайт. Установи MAX_AGE_DAYS=0 чтобы не удалять (или убери блок ротации).
  • Подкорректируй скрипт и качай другие образы Linux (какие нужны) или любой другой софт, который часто обновляется и экономь свое время.
  • Ограничения nice и ionice — чтобы не портить жизнь серверу.
  • --limit-rate=500k можно уменьшать для очень медленных машин.

Планирование: cron vs systemd-timer

Cron (очень просто). Добавь в crontab -e:

0 3 * * * /srv/nightfetch/nightfetch-debian.sh

Это запустит в 03:00 каждую ночь.

Systemd-timer (чуть аккуратнее). Если хочешь логирование в journal и единичные таймеры — лучше systemd. Но cron проще для дохлика — ставь cron.

Как качать браузеры и другие файлы

  • Для браузеров часто достаточно
wget -c URL или aria2c -x1 URL
  • Если сайт даёт API/JSON с релизами (GitHub, Mozilla), можно написать небольшой curl/jq-скрипт, который парсит последнюю версию и добавляет ссылку в очередь загрузки.
  • Для нескольких файлов используй
aria2c --input-file=urls.txt --max-concurrent-downloads=2 --max-connection-per-server=1

Пример urls.txt:

https://ftp.mozilla.org/pub/firefox/releases/143.0/linux-x86_64/en-US/firefox-143.0.deb
https://releases.chromium.org/...

И запуск:

nice -n 19 ionice -c3 aria2c --max-concurrent-downloads=2 --max-connection-per-server=1 --input-file=/srv/nightfetch/urls.txt --dir=/srv/nightfetch/downloads

Мониторинг и уведомления (минимум)

  • Пиши лог в /srv/nightfetch/logs. Настрой logrotate для них.
  • Для простого оповещения при ошибке можно в конце скрипта отправлять письмо:
if grep -i "failed" "$LOG"; then
mail -s "nightfetch: errors on $(hostname) $(date +%F)" you@example.com < "$LOG"
fi
  • Или отправляй простое уведомление в Telegram через webhook (хотя нафиг он тебе нужен в 3 утра).

Полезные советы и мелкие фишки

  • Если диск маленький — монтируй внешний NAS/USB и качай туда напрямую.
  • Для контроля версий: сохраняй список скачанных URL и контрольные суммы в отдельном файле (audit).
  • Используй flock или mkdir /var/lock/... чтобы не запустить скрипт дважды.
  • Если сеть нестабильна — wget --tries=0 --waitretry=10 (бесконечные повторы с паузами).
  • Для зеркал лучше rsync (он скачивает только изменения).
  • Не качай всё сразу — дроби очереди, чтобы не перегружать диск.

Тонкая настройка под «старый и очень слабый» сервер

  • Ограничь количество одновременных загрузок до 1.
  • Ограничь пропускную способность до 100–300 KB/s (если интернет полная лажа).
  • Уменьши время ожидания и увеличь паузу между попытками (--wait=3).
  • Запускай в период, когда система обычно простаивает — 2–4 утра.
  • Проверь температуру корпуса: если сервер греется — раздели задания на несколько ночей.

Твой старый сервер — это не музейный экспонат и не обогреватель для сторожа. Это ночной робот, который тихо собирает ISO, браузеры и прочие штуки, чтобы утром ты мог спокойно ставить систему или отдавать коллегам ссылки. Немного nice, пара ionice, умная ротация и проверка SHA256 — и даже самый древний железяка будет полезен.

А как Вы используете списанное железо? Напишите в комментариях.