RE:NODE

VDS15 мин чтения

Команды Linux для администратора сервера: 40 важных

Команды, которые покрывают почти всю работу с VDS: файлы, логи, процессы, память, диск, systemd, права и сеть, с флагами, которые стоит запомнить.

0 прочтений

Администрирование сервера - это по большей части четыре вопроса, которые задаются по кругу: что сейчас запущено, что оно делает с машиной, что оно записало в лог и кто может до него достучаться. На эти вопросы отвечает около сорока команд, и когда они войдут в привычку, сороковая первая понадобится вам не раньше чем через несколько месяцев. В этой статье собраны именно они, с флагами, которые делают их полезными, и с ловушками, которые обходятся дорого. Подразумевается Debian или Ubuntu, потому что таких образов на VDS больше всего, но всё, кроме apt, одинаково работает в любом современном дистрибутиве.

Прежде чем начать, стоит выработать две привычки. Во-первых, man ls и ls --help быстрее поисковика и описывают ту версию, которая у вас реально стоит, а она не всегда совпадает с версией из найденного руководства. Во-вторых, нажмите Ctrl-r и начните печатать - так вы ищете по истории оболочки в обратном порядке. Почти всё, что нужно выполнить сегодня, вы уже выполняли на прошлой неделе.

Ежедневная десятка#

Эти команды вы набираете не задумываясь. Выучите флаги из правого столбца, и вы закроете большую часть рабочего дня.

КомандаЧто стоит знать
lsls -lah - подробный список со скрытыми файлами и читаемыми размерами
cdcd - возвращает в предыдущий каталог
pwdПоказывает, где вы находитесь, полезна внутри скриптов
catТолько для коротких файлов; для всего, что длиннее экрана, берите less
less/ ищет, G прыгает в конец, q выходит, -S отключает перенос строк
cpcp -a сохраняет права, владельца и временные метки
mvПереименование и перемещение - одна и та же операция
rmУ rm -rf нет отмены и нет корзины
mkdirmkdir -p a/b/c создаёт весь путь целиком
nanoРедактор, который уже установлен и не требует самоучителя

Рядом с ними есть несколько мелких команд. stat file выводит права, владельца, размер и все три временные метки, и это закрывает споры о том, правился ли конфиг на самом деле. file something сообщает, чем файл является на самом деле, а не что утверждает его расширение: так выясняется, что «zip», который кто-то загрузил, - это архив RAR. nproc печатает число процессоров, которое машина у себя насчитала, и это число нужно, чтобы правильно читать load average дальше в статье.

Чтение файлов и логов#

Большая часть работы - это чтение. Хитрость в том, чтобы не читать всё подряд.

bash
$ tail -n 200 /var/log/nginx/error.log      # last 200 lines$ tail -F /var/log/nginx/error.log          # follow, survives rotation$ head -n 40 /etc/nginx/nginx.conf          # first 40 lines$ less +G /var/log/syslog                   # open at the end$ wc -l /var/log/auth.log                   # how many lines is this

tail -f следит за файлом по открытому дескриптору. Когда ротация логов переименовывает файл у вас из-под ног, -f продолжает следить за файлом, в который больше никто не пишет, а вы сидите и думаете, что сервер затих. tail -F открывает файл заново по имени и переживает ротацию. Используйте заглавную.

Для всего, что управляется через systemd, а на современной машине это почти всё, лог - вообще не файл:

bash
$ journalctl -u nginx -f                    # follow one unit$ journalctl -u minecraft --since "30 min ago"$ journalctl -b -p err                      # errors since this boot$ journalctl -k                             # kernel messages only$ journalctl --disk-usage$ journalctl --vacuum-size=200M             # when the journal has grown

-u выбирает unit, -b ограничивает текущей загрузкой, -p err фильтрует по приоритету, а --since понимает обычные слова вроде "yesterday" или "2026-09-20 18:00". Сочетание, которое решает большинство инцидентов, - journalctl -u <name> -b --no-pager | less, а затем поиск внутри less. Если служба - игровой сервер, интересны обычно последние тридцать строк перед остановкой, а не трассировка стека в самом конце. О том, какие из этих логов стоит отправлять на постоянное хранение, рассказано в статье логи, которые стоит хранить.

Сжатые архивы можно просматривать, не распаковывая. zcat, zless и zgrep ведут себя на файлах .gz так же, как их обычные версии, поэтому zgrep "Invalid user" /var/log/auth.log.*.gz за один заход проходит по двум неделям ротированных логов.

Поиск: find, grep и which#

grep ищет внутри файлов. find ищет сами файлы. Люди постоянно хватаются не за ту команду.

bash
$ grep -rn "listen" /etc/nginx/            # recursive, with line numbers$ grep -i "error" app.log | tail -n 50     # case-insensitive$ grep -c "404" access.log                 # count instead of printing$ grep -v "healthcheck" access.log         # everything except$ grep -B2 -A5 "Exception" app.log         # with context around each hit

Пару -rn стоит запомнить: рекурсивно и с номерами строк, так что вывод имеет вид file:line: text, и файл можно открыть сразу на нужном месте. -B и -A печатают строки до и после совпадения, и это разница между «знаю, что было исключение» и «знаю, какой запрос его вызвал».

bash
$ find /home -type f -name "*.db" -size +50M$ find /var/log -type f -name "*.gz" -mtime +14 -delete$ find . -type d -name node_modules -prune -o -type f -name "*.js" -print$ which python3          # which binary will run$ command -v node        # the portable version of the same question

find читается как предложение: где искать, какого типа, с каким именем и что с найденным делать. -mtime +14 означает «изменён больше четырнадцати дней назад». -delete необратим, так что сначала запустите команду без него и прочитайте список. Эта двухшаговая схема - не показная осторожность: find с чуть неверным шаблоном -name находит больше, чем вы ожидали, примерно раз в год.

which отвечает на вопрос «что на самом деле запустится, когда я это наберу», а это важно, когда вы поставили второй Node или Python, а старый по-прежнему стоит первым в PATH. Если ответ вас удивил, выполните echo $PATH.

Занята ли машина: процессы, память и CPU#

Четыре команды показывают, в беде ли машина и в какой именно.

bash
$ uptime 14:22:01 up 12 days,  3:41,  1 user,  load average: 1.82, 1.44, 0.98$ free -h$ ps aux --sort=-%mem | head -n 12$ top          # or htop, if you installed it

Load average - это три числа: за последнюю минуту, за пять и за пятнадцать. Сравнивайте их с nproc. На машине с двумя vCPU нагрузка 2.00 означает полную занятость, 4.00 - что работа стоит в очереди, а 0.8 - что всё хорошо. Направление важно не меньше значения: 0.5 1.4 2.1 - это машина, которая приходит в себя, а 2.1 1.4 0.5 - машина, у которой вот-вот начнётся тяжёлый день. Нагрузка считает и процессы, ожидающие диска, а не только CPU, поэтому высокая нагрузка при простаивающих процессорах обычно означает проблему с хранилищем, а не с вычислениями.

free -h печатает строку, которую в основном стоит игнорировать, и столбец, который игнорировать нельзя. Столбец free почти всегда мал, потому что Linux использует свободную память как дисковый кэш и отдаёт её по первому требованию. Число, по которому видно, есть ли у вас память, - available. Если available меньше нескольких сотен мегабайт, вы в одном неудачном выделении памяти от того, что ядро что-нибудь убьёт, а это отдельная тема, разобранная в статье swap и OOM killer.

ps aux --sort=-%mem | head - самый быстрый ответ на вопрос «что съедает RAM». Замените %mem на %cpu, чтобы задать противоположный вопрос. top - живая версия; htop - то же самое с цветом, прокруткой и деревом процессов, и его стоит поставить: это займёт тридцать секунд. Внутри top нажмите M, чтобы отсортировать по памяти, P - по CPU, и 1, чтобы раскрыть вывод по ядрам.

Когда что-то нужно остановить:

bash
$ kill 4821             # polite: SIGTERM, lets it clean up and save$ kill -9 4821          # SIGKILL: immediate, no save, last resort$ pkill -f "valheim_server"$ pgrep -af java        # find the PID and the full command line first

Для игровых серверов это различие не академическое. SIGTERM даёт большинству из них возможность записать мир на диск; SIGKILL выбрасывает всё, что произошло с последнего автосохранения. Берите -9 только после того, как обычная остановка не сработала за минуту.

Место на диске и что его заняло#

Заполненный диск ломает всё неприятным образом: база отказывается принимать записи, лог перестаёт писаться, а служба падает с ошибкой про что-то совсем постороннее. Проверяйте место, прежде чем разбираться с любой странностью.

bash
$ df -h                        # space per filesystem$ df -i                        # inodes, when df -h says there is room$ du -sh /var/* 2>/dev/null | sort -h$ du -sh * | sort -h           # then descend into the biggest one$ ncdu /var                    # interactive, if you install it$ lsof +L1                     # deleted files still held open

du -sh * | sort -h, а затем cd в самый большой результат - вот вся техника. Три-четыре повтора выводят вас на каталог, который важен. sort -h правильно сортирует читаемые размеры, так что 2G оказывается выше 900M, а не ниже него по алфавиту.

Два сценария отказа выглядят как магия, пока вы их не видели. Первый - исчерпание inode: df -h показывает 40% занятого места, записи всё равно падают, а df -i показывает, что inode израсходованы на 100%, обычно на каталог сессий или кэш из миллионов крошечных файлов. Второй - удалённый файл, который процесс всё ещё держит открытым. Место не возвращается, пока дескриптор не закрыт, поэтому du и df расходятся друг с другом. lsof +L1 выводит ровно такие файлы; перезапуск удерживающего их процесса освобождает место мгновенно. Почти всегда это лог, который кто-то удалил вместо того, чтобы обрезать. Правильный способ опустошить используемый лог - truncate -s 0 /path/to/file, а не rm.

Службы и systemd#

Всё, что должно пережить перезагрузку, принадлежит systemd. Работу закрывают пять подкоманд.

bash
$ systemctl status nginx$ systemctl restart nginx$ systemctl enable --now fail2ban      # start it and start it at boot$ systemctl disable --now something    # stop it and stop it at boot$ systemctl daemon-reload              # after editing any unit file$ systemctl list-units --type=service --state=running$ systemctl list-timers$ systemd-analyze blame                # what made this boot slow

enable и start - разные понятия, и путаница между ними - самая частая ошибка с systemd. start запускает службу сейчас. enable заставляет её запускаться при загрузке. Служба, которую вы запустили, но не включили, пропадает при первой же перезагрузке машины, обычно через несколько месяцев, и никто не связывает два этих события. --now делает и то и другое.

systemctl status печатает под состоянием последние десять строк лога, и этого часто хватает, чтобы понять, почему запуск не удался. Если не хватает, journalctl -u <name> -n 100 --no-pager покажет остальное. После правки unit-файла нужно выполнить daemon-reload до restart, иначе systemd продолжит использовать версию, разобранную при загрузке, и вы будете отлаживать изменение, которое так и не применилось. Как писать сами unit-файлы - тема подлиннее, она разобрана в статье службы systemd для ваших приложений.

Пользователи, права и владение#

Ошибки прав дают немалую долю случаев «у меня на машине работает». Исправление почти всегда в владельце, а не в режиме доступа.

bash
$ id                                   # who am I, and in what groups$ adduser deploy                       # interactive, creates the home dir$ usermod -aG sudo deploy              # note the -a; without it you replace groups$ sudo -u minecraft -i                 # become a service user for one session$ chown -R minecraft:minecraft /srv/minecraft$ chmod 700 ~/.ssh$ chmod 600 ~/.ssh/authorized_keys$ chmod +x start.sh

-a в usermod -aG означает append, то есть «добавить». Если его пропустить, все группы пользователя заменятся той, что вы указали, и именно так люди лишают себя собственного доступа к sudo. Набирайте медленно.

Числовые режимы состоят из трёх цифр - для владельца, группы и всех остальных, где чтение равно 4, запись 2, исполнение 1. Так 644 - это чтение и запись для владельца и чтение для остальных; 755 добавляет исполнение для каталогов и скриптов; 600 - только для владельца. SSH отказывается использовать приватный ключ или файл authorized_keys, доступные кому-либо ещё, и молча переходит к запросу пароля, и это самая частая причина того, что ключ «не работает»; продолжение этой истории - в статье ключи SSH и защита.

Запускайте службы под отдельными непривилегированными пользователями, по одному на службу, а файлы отдавайте этому пользователю. Это занимает минуту при настройке и отличает один взломанный игровой сервер от взломанной машины. Когда нужно действовать от имени этого пользователя, sudo -u minecraft -i даёт вам login-оболочку под ним, и выходить из системы не приходится.

Сеть: что слушает и кто может достучаться#

netstat признан устаревшим и отсутствует в минимальных образах. Его заменила ss, и она быстрее.

bash
$ ss -tulpen                  # every TCP and UDP listener, with the process$ ss -tn state established    # current connections$ ip -brief addr              # the machine's addresses, one line each$ ip route                    # where traffic goes by default$ ufw status numbered         # what the firewall allows

ss -tulpen - самая ценная отдельная команда в этой статье. Запустите её в день, когда закончите настройку сервера, и потом раз в месяц, и держите вывод коротким. Каждая строка - это дверь. База данных, привязанная к 0.0.0.0 вместо 127.0.0.1, - второй по частоте способ взлома небольших серверов, и эта команда находит её за пять секунд. Что делать с найденными дверями, рассказано в руководстве по файрволу ufw и в статье правила файрвола, которые важны.

Для проверки снаружи:

bash
$ curl -I https://example.com                 # response headers only$ curl -sS -o /dev/null -w "%{http_code} %{time_total}s\n" https://example.com$ dig +short A example.com @1.1.1.1           # ask a specific resolver$ ping -c 4 203.0.113.10$ mtr -rwc 50 203.0.113.10                    # 50 packets, report mode$ nc -zv 203.0.113.10 25565                   # is this TCP port open

Запускайте dig к публичному резолверу через @1.1.1.1, когда вы только что изменили запись, потому что ваш собственный резолвер, скорее всего, ещё держит старый ответ, пока не истечёт его TTL. nc -zv проверяет TCP; осмысленно проверить им игровой порт UDP нельзя, потому что некому вернуть отказ. Как правильно читать отчёт mtr - отдельное умение, и в статье задержка, джиттер и потеря пакетов объяснено, какой столбец действительно важен.

Передача файлов, архивы и как не отключаться#

Как переносить файлы на машину и с неё и как держать процессы запущенными после закрытия терминала.

bash
$ scp world.zip deploy@203.0.113.10:/srv/       # one file, quick$ rsync -avh --progress /srv/world/ backup:/srv/world/$ rsync -avh --delete src/ dest/                # make dest match src exactly$ tar -czf world-2026-09-21.tar.gz worlds_local/$ tar -xzf archive.tar.gz -C /srv/target/$ unzip plugins.zip -d plugins/

rsync лучше scp для всего, что повторяется, потому что копирует только изменившееся и умеет докачивать. Правило косой черты в конце - то, на чём ошибаются все: rsync -a src/ dest/ копирует содержимое src в dest, а rsync -a src dest/ создаёт dest/src. В первый раз проверьте с --dry-run, особенно с --delete, который удалит на приёмнике всё, чего нет на источнике.

bash
$ tmux new -s valheim         # new named session  Ctrl-b then d               # detach, leaving it running$ tmux attach -t valheim      # come back later$ tmux ls                     # what sessions exist$ watch -n 5 'ss -tn state established | wc -l'

tmux держит процесс живым после обрыва SSH-сеанса и позволяет подключиться к тому же терминалу откуда угодно. Это подходящий инструмент для долгой сборки или миграции, за которой вы присматриваете. И неподходящий - для постоянной работы игрового сервера: процесс в tmux не запускается при загрузке, не перезапускается после сбоя и невидим для любого мониторинга, который вы настроите позже. Для всего, что должно работать постоянно, используйте unit systemd, а tmux оставьте для работы, за которой вы наблюдаете.

Наконец, поддержание самой системы в актуальном состоянии:

bash
$ apt update && apt full-upgrade -y$ apt list --upgradable$ apt autoremove --purge$ needrestart                  # which services are running old libraries

apt update обновляет списки пакетов и ничего не устанавливает, и это сбивает с толку тех, кто пришёл из других менеджеров пакетов. full-upgrade - это upgrade плюс право удалять пакет, если обновление этого требует, а именно это вам нужно на сервере, который вы собираетесь держать пропатченным. После обновления библиотеки работающие процессы держат старую копию в памяти до перезапуска; needrestart подскажет, какие именно. Весь распорядок первого дня по порядку описан в статье первый час на новом VDS.

На управляемом тарифе RE:NODE ничего из этого не применимо, потому что shell на хосте вы не получаете. Вместо этого вы получаете нефильтрованную консоль с историей команд и автодополнением по табуляции - это собственный ввод и вывод игрового или прикладного процесса, а не приглашение Linux, - а также файловый менеджер в браузере и отдельные данные для SFTP на каждый сервер. Этого хватает для настройки, загрузки файлов и чтения логов без единой команды из этой статьи. VDS - это другой обмен: полный root-доступ, и каждая команда с этой страницы становится вашей ответственностью. В статье VDS или игровая панель в цифрах показано, что дешевле в вашем случае.

FAQ#

Чем apt отличается от apt-get?

apt - более новый интерфейс для тех, кто работает в терминале, с индикатором выполнения и чуть более дружелюбным выводом. У apt-get стабильный интерфейс, рассчитанный на скрипты. В интерактивной работе они делают одно и то же; пользуйтесь apt и больше об этом не думайте.

Почему free -h показывает, что свободной памяти почти нет?

Потому что Linux использует простаивающую память как дисковый кэш, и это хорошо. Память кэша возвращается в тот момент, когда её запрашивает программа. Смотрите на столбец available, а не free, и беспокойтесь, только когда available становится мал.

Как оставить программу работать после выхода из системы?

Для всего постоянного - unit systemd с Restart=on-failure. Для разовой задачи, за которой вы следите, - tmux или nohup command &. Разница в том, что systemd перезапускает программу после сбоя и запускает её снова после перезагрузки, а tmux не делает ни того ни другого.

Как узнать, какой процесс использует порт?

ss -tulpen выводит все слушающие сокеты с именем процесса и PID в последнем столбце. Если порт занят, а ничего не видно, вы, скорее всего, не root - запустите с sudo, потому что столбец процесса скрыт для чужих процессов.

Нужно ли учить vim?

Нет. nano установлен почти в каждом дистрибутиве, показывает свои сочетания клавиш внизу экрана и прекрасно справляется с правкой конфига. Выучите из vim столько, чтобы выйти из него - Esc, затем :q!, - потому что иногда он оказывается редактором по умолчанию, а остальное оставьте на момент, когда захотите.

Что проверять первым, когда сервер тормозит?

В таком порядке: uptime - нагрузка относительно nproc, free -h - столбец available, df -h - не забит ли диск, затем ps aux --sort=-%cpu | head. Эти четыре команды занимают вместе двадцать секунд и в большинстве случаев указывают на причину.


Комментарии

Полностью анонимно: без аккаунта, без почты, без cookie. Мы храним имя, которое вы ввели, текст и время - больше ничего. Количество ссылок ограничено, разметка не отображается.

0/2000