Терминал: навигация и базовые команды
Терминал: навигация и базовые команды
Терминал - это не «хакерское окошко». Это основной инструмент работы с сервером. GUI на продакшен-сервере обычно нет.
Навигация по файловой системе
pwd # где я сейчас (print working directory)
ls # что здесь лежит
ls -la # подробно, включая скрытые файлы
cd /var/log # перейти в каталог
cd .. # на уровень вверх
cd ~ # домой
cd - # назад, где был
Структура файловой системы Linux
/
├── bin/ # базовые утилиты (ls, cat, grep)
├── etc/ # конфиги (nginx.conf, .env)
├── home/ # домашние каталоги пользователей
├── var/
│ ├── log/ # логи сервисов
│ └── www/ # веб-контент (иногда)
├── tmp/ # временные файлы
├── opt/ # стороннее ПО
└── usr/ # пользовательские программы
Запомни: конфиги в /etc, логи в /var/log, твой код обычно в /opt или /home.
Просмотр файлов
cat file.txt # весь файл (осторожно с большими)
head -20 file.txt # первые 20 строк
tail -50 file.txt # последние 50 строк
tail -f /var/log/app.log # следить за логами в реальном времени
less file.txt # постраничный просмотр (q - выход)
Поиск
grep "error" app.log # строки с "error"
grep -i "error" app.log # без учёта регистра
grep -r "TODO" ./src/ # рекурсивно по каталогу
grep -n "panic" main.go # с номерами строк
Создание и удаление
mkdir -p projects/backend # создать вложенные каталоги
touch README.md # создать пустой файл
cp file.txt backup.txt # копировать
mv old.txt new.txt # переименовать / переместить
rm file.txt # удалить файл
rm -r directory/ # удалить каталог
Пайпы и перенаправление
Пайп | - это конвейер: выход одной команды становится входом другой.
cat app.log | grep "error" | wc -l # сколько ошибок в логе
ps aux | grep nginx # найти процесс nginx
ls -la | sort -k5 -n # файлы по размеру
Перенаправление:
echo "hello" > file.txt # записать (перезапишет!)
echo "world" >> file.txt # дописать в конец
command 2>&1 # stderr в stdout
command > /dev/null 2>&1 # подавить весь вывод
Горячие клавиши терминала
| Клавиша | Действие |
|---|---|
| Ctrl+C | Прервать команду |
| Ctrl+D | Выход из shell |
| Ctrl+R | Поиск по истории команд |
| Ctrl+L | Очистить экран |
| Ctrl+A / Ctrl+E | В начало / конец строки |
| Ctrl+W | Удалить слово слева |
| Ctrl+U / Ctrl+K | Удалить до начала / конца строки |
| Ctrl+Z | Приостановить процесс (см. ниже) |
Job control: процессы переднего и заднего плана
Запустил долгую команду и понял, что хочешь освободить терминал? Тебе нужен job control.
sleep 300 # запустил на переднем плане - терминал занят
# Ctrl+Z # → пауза процесса
jobs # [1]+ Stopped sleep 300
bg # → продолжить в фоне (& суффикс эквивалент при запуске)
jobs # [1]+ Running sleep 300 &
fg # → вернуть на передний план
# Сразу запустить в фоне
long-script.sh &
[1] 12345 # bash сообщил job-id [1] и PID 12345
# Список фоновых задач
jobs -l
[1]+ 12345 Running long-script.sh &
# Убить процесс
kill %1 # по job-id
kill 12345 # по PID
kill -9 12345 # SIGKILL - только если не реагирует на обычный kill
nohup и disown: процесс переживёт закрытие терминала
# По умолчанию: закроешь ssh - фоновые процессы умрут (SIGHUP)
./deploy.sh &
# nohup - игнорировать SIGHUP, перенаправить вывод в nohup.out
nohup ./deploy.sh &
nohup ./deploy.sh > deploy.log 2>&1 & # перенаправление логов своё
# disown - отвязать УЖЕ запущенный фоновый процесс от shell
./deploy.sh &
disown -h %1 # процесс продолжит работать после exit
История команд: !!, !$, Ctrl+R
# Ctrl+R: интерактивный поиск по истории
# (reverse-i-search)`docker`: docker compose up -d
# жмёшь Ctrl+R ещё раз - следующий матч; Enter - выполнить; Esc - отредактировать
# History expansion
!! # последняя команда
sudo !! # та же команда с sudo (классика)
!$ # последний аргумент предыдущей команды
!* # все аргументы
!ssh # последняя команда, начинающаяся на "ssh"
^foo^bar # повторить последнюю, заменив foo на bar
history # вся история (~/.bash_history)
history | grep docker # найти что искал
!42 # выполнить команду номер 42 из истории
# Пример из жизни
$ wget https://example.com/big-file.tar.gz
$ sha256sum !$
sha256sum https://example.com/big-file.tar.gz # подставится URL, не файл
# Правильный сценарий:
$ wget https://example.com/big-file.tar.gz
$ ls -la !*:t # :t = «basename»
Tab completion: bash-completion
# Базовое: имена файлов и команд
$ ls /var/lo<Tab> # → /var/log/
$ git che<Tab> # → git checkout (если установлен bash-completion)
# Двойной Tab показывает варианты
$ git <Tab><Tab>
add branch checkout clone commit ...
# Установка programmable completion (если ещё нет)
sudo apt install bash-completion # Debian/Ubuntu
brew install bash-completion@2 # macOS
# В .bashrc:
[ -f /etc/bash_completion ] && . /etc/bash_completion
Многие инструменты идут с собственными completion-скриптами:
docker completion bash > /etc/bash_completion.d/docker
kubectl completion bash > /etc/bash_completion.d/kubectl
gh completion -s bash > /etc/bash_completion.d/gh
Теперь kubectl get po<Tab> дополнит «pods», а docker exec <Tab> покажет список запущенных контейнеров.
Aliases vs functions vs scripts
Три способа сохранить «свою» команду - у каждого своя ниша:
# 1. alias - простая подмена строки
alias ll='ls -la'
alias gst='git status'
alias dcd='docker compose down'
# В ~/.bashrc или ~/.aliases (последний source-ить из bashrc)
# 2. function - нужны аргументы или логика
mkcd() { # mkdir + cd одной командой
mkdir -p "$1" && cd "$1"
}
gco() { # git checkout с подсказкой
if [ -z "$1" ]; then
git branch
else
git checkout "$1"
fi
}
# 3. shell script - пере-используется, расшарен с командой
# ~/bin/deploy-staging
#!/usr/bin/env bash
set -euo pipefail
ssh staging "cd /app && git pull && docker compose up -d --build"
chmod +x ~/bin/deploy-staging
echo 'export PATH="$HOME/bin:$PATH"' >> ~/.bashrc
Когда выбирать Сигнал
────────────── ──────────────────────────────────────────
alias подмена строки 1:1; без логики, без аргументов
function нужны позиционные аргументы или условия;
живёт в shell-сессии; легко переопределить
script длинная логика, шарится между людьми, версионируется
в Git; запускается из любого shell (не зависит от bash)
Shebang: #!/usr/bin/env bash vs #!/bin/bash
#!/bin/bash # жёстко привязан к /bin/bash
На macOS системный /bin/bash - древний 3.2 (из-за GPLv3); на NixOS или Alpine его вообще нет (там /bin/sh ≠ bash). Скрипт упадёт «No such file or directory».
#!/usr/bin/env bash # ищет bash в PATH - работает везде
env сам находит интерпретатор по $PATH. Бонус: можно поставить новую версию bash через brew/apt - она подхватится автоматически.
#!/bin/sh # POSIX shell - НЕ bash; нет массивов, нет [[ ]],
# нет process substitution <(...) - только то,
# что есть в /bin/dash (на Debian sh = dash)
Не путай #!/bin/sh и #!/usr/bin/env bash. Если используешь bash-фичи ([[, массивы, ${var,,}) - указывай bash явно.
Мини-задание
- Перейди в
/var/logи найди файлsyslogилиmessages - Посмотри последние 20 строк этого файла через
tail -20 - Найди все строки с «error» через
grep -i "error" - Посчитай их:
grep -ic "error" syslog
Итог
pwd,ls,cd- навигация.cat,head,tail,less- просмотр.grep- поиск.- Пайпы (
|) - суперсила терминала. Комбинируй простые команды для сложных задач. Tabдля автодополнения,Ctrl+Rдля поиска по истории - привыкай сразу.
Типичная ошибка
Копировать команды из Stack Overflow, не читая. rm -rf с неправильным путём, chmod 777 на всё подряд, curl | bash без проверки скрипта - всё это реальные инциденты. Читай, что запускаешь.
Мини-практика
Создай каталог ~/linux-practice. Внутри создай 5 файлов: app.log, error.log, config.yml, main.go, README.md. Запиши в app.log несколько строк с помощью echo "..." >>. Потом найди в нём все строки с определённым словом через grep и посчитай их количество через wc -l.