Терминал
Linux-команды, которые нужны при разборе продакшена и настройке серверов.
#Процессы
ps aux | grep -i nginx
ps -eo pid,ppid,rss,pcpu,comm --sort=-rss | head -15
pgrep -a java
pidof nginx
--sort=-rss сразу показывает, кто ест память. rss в килобайтах.
top -o %MEM
htop
btop
Интерактивно. В top: M — сортировка по памяти, P — по CPU, 1 — раскладка по ядрам.
kill 12345 # SIGTERM, вежливо
kill -9 12345 # SIGKILL, без шансов на очистку
pkill -f "python.*worker"
killall -u www-data
pkill -f матчит по всей командной строке — осторожно, шаблон может попасть в собственную оболочку.
Практический случай: pkill -f script.sh, запущенный из bash -c, убивает и сам вызывающий процесс, потому что шаблон есть в его cmdline.
lsof -p 12345 | head -20
lsof -i :8443
lsof +D /var/log | head
ls -l /proc/12345/fd | wc -l
Что держит процесс: файлы, сокеты, порты. Последняя команда — счётчик открытых дескрипторов, растёт при утечке.
nohup ./long-task.sh > out.log 2>&1 &
disown
jobs
fg %1
Отвязать задачу от сессии. Для чего-то серьёзного лучше systemd-юнит или tmux.
strace -p 12345 -f -e trace=network 2>&1 | head -40
strace -c -p 12345
Что процесс делает с системой. -c — сводка по syscall'ам, быстро показывает, где процесс завис.
#Файлы, поиск, права
find /var/log -type f -size +50M -exec ls -lh {} \;
find . -name "*.kt" -newermt "-3 days"
find . -type d -name build -prune -o -name "*.log" -print
find /tmp -type f -mtime +7 -delete
-prune исключает каталоги из обхода — без него find лезет в build и node_modules.
grep -rn "TODO" --include="*.kt" src/
grep -rl "apiKey" . | head
grep -c ERROR app.log
grep -A3 -B3 "Exception" app.log | head -40
grep -Ev "^\s*(#|$)" nginx.conf
-l только имена файлов, -c счётчик, -A/-B контекст. Последняя команда убирает комментарии и пустые строки из конфига.
du -xh --max-depth=2 / 2>/dev/null | sort -rh | head -15
du -sh /var/log/*
df -h
df -i # иноды, если «нет места», а место есть
-x не уходит на другие ФС. Кончившиеся иноды выглядят как No space left при свободных гигабайтах.
chmod 640 secret.key
chmod +x script.sh
chown www-data:adm /var/log/app.log
umask 027
Числа: владелец/группа/остальные, 4=r, 2=w, 1=x. 640 — владельцу чтение-запись, группе чтение, остальным ничего.
tar czf backup.tar.gz -C /etc nginx
tar xzf backup.tar.gz -C /tmp/restore
tar tzf backup.tar.gz | head
zcat app.log.1.gz | grep ERROR
-C меняет каталог до упаковки — так в архиве не будет лишних уровней путей. zcat/zgrep читают .gz без распаковки.
ln -s /var/www/site /srv/current
readlink -f /srv/current
stat app.log
Симлинки и метаданные файла.
#Обработка текста
awk '{print $1, $9}' access.log | head
awk '$9 >= 500 {print}' access.log | wc -l
awk -F: '{print $1}' /etc/passwd | head
$1, $9 — поля, -F задаёт разделитель. Для логов часто короче, чем cut+grep.
sed -n '100,120p' app.log
sed 's/old/new/g' file.txt # в stdout
sed -i.bak 's/old/new/g' file.txt # на месте, с бэкапом
sed '/^#/d' config.ini
-i.bak — правка на месте с копией. Без суффикса откатиться будет нечем.
sort access.log | uniq -c | sort -rn | head -20
cut -d' ' -f1 access.log | sort -u | wc -l
tr -s ' ' | tr '[:upper:]' '[:lower:]'
Классика подсчёта частот: sort | uniq -c | sort -rn. uniq требует отсортированного входа.
tail -f app.log
tail -f app.log | grep --line-buffered ERROR
tail -n 200 app.log
head -c 2000 app.log
watch -n 2 'ss -tn | wc -l'
--line-buffered обязателен, иначе grep буферизует и вывод появляется рывками по 4 КБ.
wc -l app.log
diff -u old.conf new.conf
comm -13 <(sort a.txt) <(sort b.txt)
comm -13 — строки, которые есть только во втором файле.
#systemd
systemctl status nginx
systemctl start|stop|restart|reload nginx
systemctl enable --now myapp
systemctl disable --now myapp
systemctl is-active nginx
reload перечитывает конфиг без разрыва соединений, restart роняет процесс. Для nginx почти всегда нужен reload.
systemctl list-units --type=service --state=running
systemctl list-unit-files --state=enabled
systemctl cat nginx
systemctl show nginx -p MainPID,MemoryCurrent
cat показывает юнит вместе со всеми override'ами — удобнее, чем искать файлы руками.
systemctl edit myapp # override-фрагмент
systemctl daemon-reload # после правки юнитов
systemctl reset-failed myapp
edit создаёт /etc/systemd/system/myapp.service.d/override.conf — правильный способ менять пакетные юниты.
[Unit]
Description=My worker
After=network-online.target
[Service]
Type=simple
User=app
WorkingDirectory=/opt/myapp
ExecStart=/opt/myapp/bin/worker
Restart=on-failure
RestartSec=5
MemoryMax=512M
[Install]
WantedBy=multi-user.target
Минимальный рабочий юнит. MemoryMax спасает хост от процесса, который течёт.
systemd-analyze blame | head -10
systemd-analyze critical-chain
Что тормозит загрузку.
#journalctl и логи
journalctl -u nginx -n 100 --no-pager
journalctl -u nginx -f
journalctl -u nginx --since "1 hour ago"
journalctl --since "2026-08-25 10:00" --until "2026-08-25 11:00"
--no-pager нужен в скриптах, иначе команда зависнет в ожидании пейджера.
journalctl -p err -b
journalctl -k # ядро
journalctl -b -1 # предыдущая загрузка
journalctl --list-boots
-p err и хуже. -b -1 — первое, что смотреть после неожиданной перезагрузки.
journalctl --disk-usage
journalctl --vacuum-size=200M
journalctl --vacuum-time=14d
Журнал по умолчанию растёт до 10% раздела. Постоянный лимит — SystemMaxUse в /etc/systemd/journald.conf.
logrotate -d /etc/logrotate.d/nginx # dry-run
logrotate -f /etc/logrotate.d/nginx # принудительно
cat /var/lib/logrotate/status
-d ничего не делает, только печатает решение — так проверяется правило перед применением.
/var/log/nginx/*.log {
daily
maxsize 50M
rotate 7
compress
delaycompress
notifempty
create 0640 www-data adm
postrotate
invoke-rc.d nginx rotate >/dev/null 2>&1
endscript
}
daily без maxsize — типовая ошибка: при всплеске трафика файл раздувается за часы, а ротация ждёт суток.
#Разное полезное
free -h
uptime
vmstat 1 5
iostat -x 1 3
sar -u 1 5
load average сравнивают с числом ядер (nproc): 4.0 на 4 ядрах — полная загрузка, не перегрузка.
dpkg -l | grep -i openssl
apt list --installed | wc -l
apt-get -s autoremove
apt-get clean
dpkg -S /usr/bin/curl # какой пакет владеет файлом
-s у apt — симуляция, показывает план без выполнения.
tmux new -s work
tmux attach -t work
tmux ls
# Ctrl-b d — отсоединиться, Ctrl-b c — новое окно, Ctrl-b % — сплит
Обязательно для долгих задач по ssh: обрыв связи не убьёт процесс.
ssh-copy-id -i ~/.ssh/id_ed25519.pub root@host
ssh -i ~/.ssh/key -p 2222 user@host
scp file.txt host:/tmp/
rsync -avz --progress ./dist/ host:/var/www/site/
rsync с завершающим слэшем в источнике копирует содержимое, без слэша — сам каталог. Классический источник сюрпризов.
Host myserver
HostName 203.0.113.10
User root
Port 22
IdentityFile ~/.ssh/id_ed25519
IdentitiesOnly yes
Запись в ~/.ssh/config. Дальше просто ssh myserver.
| Симптом | Что смотреть |
|---|---|
No space left, а место есть | df -i — кончились иноды |
Диск полон, но du не показывает | удалённый файл держит процесс: lsof +L1 |
| Сервис не поднимается после правки юнита | systemctl daemon-reload |
Address already in use | ss -tlnp | grep :ПОРТ |
| Скрипт зависает в CI | journalctl без --no-pager |
| Логи растут скачками | logrotate без maxsize |
grep в пайпе выводит рывками | нужен --line-buffered |