Тариф успешно добавлен в корзину
В корзину
url image

Часть 1. Bash-скрипты. Основные команды и рекомендации

Перед чтением этой статьи рекомендуем ознакомиться с разделом Создание скрипта статьи Знакомство с bash. В нём объяснены основные термины, которые встречаются в этой статье.

Во второй статье серии о bash-скриптах даем рекомендации по их составлению и подробно рассматриваем основные команды Linux.

Основные команды

Ниже приведены команды Unix, наиболее часто используемые в bash — в основном для работы с файлами и обработки текстов. 

Не все они используются в скриптах непосредственно, но для работы с командной строкой необходимы.

Для каждой команды даны пояснения, синтаксис (правила записи), примеры применения и часто используемые опции.

Несколько опций одной утилиты записывают после дефиса без пробелов: 

ls -lat

Команда

Пояснение

Синтаксис и примеры

man

Показать руководство по работе с командой

man <название команды>

Выход: q

less

Постранично вывести содержимое текстового файла. less открывает большие файлы быстрее, чем редакторы, и нет риска случайного изменения важных файлов.

less <путь к файлу>

less /home/user/notes.txt

Листать страницы: пробел

Выход: q

cat

Показать в терминале полное содержимое одного или нескольких файлов

cat <путь к файлу>

cat file1.txt file2.txt file3.txt

ls

Отобразить список объектов в каталоге

ls <опции> <путь или (в текущем каталоге) название каталога>

-l — отображать расширенный набор параметров: разрешения, владелец, размер, дата последнего изменения

-a — отображать скрытые файлы (названия которых начинаются с точки)

-h (вместе с ключом -l) — отображать размер файла в удобном для чтения формате: в K (килобайтах) и М (мегабайтах), а не в байтах

cd

Перейти в указанный каталог

cd <путь к каталогу>
cd - — переход в предыдущий каталог

cd .. — переход в родительский каталог

cp

Скопировать файл или каталог

cp <путь к файлу> <название файла-копии или путь к каталогу копирования>

-r — скопировать каталоги рекурсивно (включая вложенные каталоги)

-i — предупредить, если в результате копирования будет перезаписан существующий файл

mv

Переместить или переименовать файл или каталог

mv <путь к файлу> <новое название файла или путь к каталогу перемещения>

-i — предупредить о перезаписи существующего файла

-n — не заменять существующий файл

rm

Удалить файл или каталог

rm <путь к файлу или каталогу>

-r — удалить объект рекурсивно (включая содержимое вложенных каталогов)

-i — запрашивать согласие на удаление каждого объекта

-f — принудительно удалить указанный объект

touch

Создать пустой файл или изменить дату открытия или изменения файла

touch <путь к файлу>

-m — изменить время изменения файла

-t — указать конкретное время вместо текущего

mkdir

Создать новый каталог

mkdir <путь к создаваемому каталогу>

-p — создать каталог, включая путь к нему, если пути не существует

sort

Отсортировать строки файла или вывода команды в порядке, определённом опцией.

sort <опции> <путь к файлу>

-r — отсортировать строки в порядке, обратном алфавитному, а для чисел — в порядке убывания

-n — отсортировать строки в порядке возрастания чисел, найденных в строках

-u — удалить повторяющиеся строки

grep

Искать в файле или каталоге указанную последовательность символов, включая подстановочные знаки. По умолчанию учитывается регистр символов

-R — искать последовательность символов рекурсивно (то есть в том числе во вложенных каталогах) во всех файлах, включая симлинки (символические ссылки).

-i — не учитывать регистр символов

grep -r kernel /var/log

Симлинк (символическая ссылка) — специальный файл, содержащий только путь к файлу, на который ссылается (целевому файлу). При обращении к симлинку открывается целевой файл.

find

Искать файлы и каталоги во всех вложенных каталогах, начиная с указанного родительского каталога

find <путь к каталогу> <выражение> <опции>

-type d — искать каталоги

find -name "file" # Искать файл с указанным названием

find -name “*.txt” -size +1k

# Искать файлы с расширением .txt размером более 1 КБ

find <путь> <опции> -exec <команда> {} \;

# Найти по указанному пути объекты и выполнить над ними действие при помощи указанной команды

Пояснения:

{} — заглушка: вместо неё подставляется путь к каждому найденному файлу, с которым будет выполнена <команда>.

\; — разделитель команд с экранированием при помощи обратного слэша \: выполнять <команду> для каждого найденного объекта

find /home/lite/ -type f -name '*.sh' -exec mv {} scripts \;

# Найти в каталоге /home/lite все файлы с расширением .sh и переместить их в каталог /home/lite/scripts

sudo find /tmp/ -type f -mtime +30 -exec rm {} \; 

# Найти в каталоге /tmp все файлы старше 30 дней и удалить их

locate

Искать файл по имени или фрагменту имени. Результат: все пути, где встречается указанное имя или фрагмент, включая промежуточные каталоги. Как правило, это множество строк (например, для chrome — несколько тысяч), поэтому рекомендуется перенаправлять вывод в less, чтобы его можно было листать

locate <имя или часть имени>

locate chrome | wc -l # Вывести количество строк, в которых найдено слово chrome

ping

Проверить, доступен ли указанный хост по сети для обмена эхо-запросами. Обычно это первый способ диагностики связи между хостами.

Утилита ping проверяет доступность целевого хоста только по протоколу ICMP. Обмен эхо-запросами ping может быть заблокирован на целевом хосте, при этом связь с ним по другим протоколам может сохраняться.

ping <URL или IP-адрес>

ping google.com

ping 216.58.210.174

wget 

Загрузить файл по сети в текущий каталог.

wget <опции> <URL> wget http://example.com/file.zip

-c — продолжить загрузку частично загруженного файла

du

Отобразить объём занятого дискового пространства в указанном каталоге (либо в текущем, если каталог не указан)

du <опции> <путь к каталогу>

-h — отображать размер файлов в удобном для чтения формате: в K (килобайтах) и М (мегабайтах), а не в байтах

-s – показывать только общий размер файлов в каталоге

-a – показывать размер отдельных файлов и каталогов в дополнение к общему размеру

 -x — искать только в текущей файловой системе, но не в прочих примонтированных ФС — например,  расположенных на блочных устройствах или в Docker-контейнерах.

df

Отобразить объём занятого дискового пространства по файловым системам: имя системы, размер, занятое и свободное пространство, доля занятого пространства, точка монтирования.

df <опции>

-h — отображать размер файлов в удобном для чтения формате: в K (килобайтах) и М (мегабайтах), а не в байтах

Команда df

htop

Версия команды top, более удобная для просмотра и использования (кроме неё существуют vtop, ptop и другие с похожим интерфейсом) — можно прокручивать вверх и вниз список процессов и выделять процессы курсором мыши.

В верхней части экрана показаны текущие значения потребления системных ресурсов (% использования ЦА, МБ памяти), в средней — динамически изменяющийся список системных процессов. Чем больше ресурсов использует процесс, тем выше он в списке.

htop — запуск утилиты

Завершить или приостановить процесс: 

  • выбрать процесс, который замедляет работу машины, судя по высокому потреблению памяти и ресурса процессора, 
  • выделить его пробелом или курсором
  • нажать F9 и выбрать вариант сигнала, который будет отправлен процессу: например, SIGTERM (завершение) или SIGTSTP (приостановка).

kill

Завершить зависший процесс

kill <PID>

kill 13771 # Запросить штатное завершение процесса с PID 13771 (mysqld) на скриншоте выше

kill -9 13771 # Принудительно завершить процесс с PID 13757

trap

Включить отладку скрипта целиком

Другие способы использовать команду trap для отладки  рассмотрим в одной из следующих статей.

trap 'echo "# $BASH_COMMAND";read' DEBUG

Команды скрипта по одной отображаются на экране; пользователь нажимает Enter; команда исполняется. Такое выполнение скрипта можно в любой момент прервать нажатием Ctrl+C.

set

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

 

Другие способы использовать команду set для отладки  рассмотрим в одной из следующих статей.

set -x # Включить отладку фрагмента

set +x # Отключить отладку фрагмента

set -e # Прервать выполнение скрипта сразу после ошибки

В этом режиме команды скрипта со знаком ‘+’ впереди по одной отображаются на экране; после каждой команды отображается её вывод.

Можно добавить set +x после строки shebang либо включить и выключить отладку интересующего фрагмента скрипта.

Удобно комбинировать команды set -x и set -e, чтобы выполнение скрипта прерывалось автоматически.

Полезные сочетания клавиш

Эти комбинации используются в пустой командной строке, то есть до ввода команд:

  • ↑ (кнопка Вверх) — просмотр предыдущей команды. ↑ и ↓ — просмотр истории введённых команд. 
  • Ctrl+R — поиск в истории введённых команд. Нажмите это сочетание и начните набирать команду, которую хотите найти. Продолжайте нажимать Ctrl+R, чтобы просматривать похожие команды в истории. 
  • Ctrl+Shift+R (в режиме поиска по истории) — перемещение вперёд по истории ввода, то есть просмотр более поздних команд.

Во время ввода команды:

  • Tab — автодополнение команд или аргумента. 

Например, чтобы просмотреть, какие утилиты есть у пакетного менеджера apt, напечатайте apt и дважды нажмите Tab. Отобразится список утилит:

Список утилит пакетного менеджера apt

Продолжайте печатать название нужной команды, например, apt-cl, и нажмите Tab. На этот раз отобразится единственное название — apt-clone, так как с символов apt-cl начинается только это название.

До или во время ввода команды:

  • Ctrl+L — очистка экрана от предыдущих команд и выведенных результатов. Вводимая команда остаётся на экране. Можно просмотреть скрытые команды и вывод прокручиванием колёсика мыши.
  • Ctrl+D — выход из сессии текущего пользователя (аналогично команде exit): 
    • из сессии суперпользователя — в сессию непривилегированного (обычного) пользователя, под чьей учётной записью пользователь работал до этого;
    • из сессии обычного пользователя — закрытие окна терминала.

Во время выполнения программы (эти сочетания срабатывают не во всех случаях):

  • Ctrl+Z — приостановка работы приложения: процессы программы получают сигнал приостановки SIGTSTP (terminal stop), ожидают сигнала возобновления SIGCONT (continuation) и переходят в фоновый режим. В фоновом режиме процесс не может читать стандартный ввод — данные, вводимые пользователем в терминал с клавиатуры. 

    Более подробно о потоках данных — стандартном вводе, стандартном выводе и стандартной ошибке — рассказываем в статье Bash-скрипты. Перенаправление ввода и вывода, об управлении заданиями — в статье Bash-скрипты. Управление заданиями, here-документы, конвейер

  • Все процессы, выполняемые в фоновом режиме, можно вывести из него командой fg
  • Ctrl+C — завершение работы программы: процессы программы получают сигнал SIGINT, как и при выполнении команды kill

Общие рекомендации по созданию скриптов

  1. Указывайте в строке c shebang (#!/bin/bash) корректный путь к нужному интерпретатору. 

Shebang — последовательность #!, с которой рекомендуется начинать скрипт. Она описана более подробно в предыдущей статье Знакомство с bash, в разделе  Создание и запуск скрипта.

2. Старайтесь избегать команд и опций, применимых только в конкретной операционной системе. Если это невозможно, создавайте разные варианты скрипта для систем разных семейств, особенно если планируете разместить скрипт в публичном репозитории.

Например, для установки pip (системы управления пакетами Python) в наиболее популярных семействах Linux — Debian, CentOS/RHEL, Fedora и Arch — традиционно используются разные системы управления пакетами (пакетные  менеджеры). 

Простой способ адаптировать скрипт для разных ОС — включить в него блоки команд установки для всех ОС с комментариями:

# Установка pip для Debian, Ubuntu и Mint
sudo apt update
sudo apt install python3-pip -y

# Установка pip для CentOS, Fedora и RHEL
sudo yum install epel-release
sudo yum -y update
sudo yum -y install python3-pip

# Установка pip для Arch и Manjaro
sudo pacman -Syu python3-pip

# Установка pip для SUSE и OpenSUSE
sudo zypper in python3-pip

Другой способ работы с разными ОС в скрипте — по названию операционной системы определить используемый пакетный менеджер:

install=""
if [[ -f /etc/os-release ]]; then
    distro=$(grep -E '^ID=' /etc/os-release | cut -d'=' -f2 | tr -d '"')
    case "$distro" in
      ubuntu|debian|linuxmint)
        sudo apt update    
        install="sudo apt install -y"
        ;;
      centos|fedora|rhel)
        sudo yum install epel-release
        sudo yum -y update
        install="sudo yum install -y"
        ;;
      arch|manjaro)
        install="sudo pacman -Syu"
        ;;
     opensuse|suse)
        install="sudo zypper in"
        ;;
     *)
        install="unknown"
        ;;
esac
else
install="unknown"
fi
if [[ "$install" == "unknown" ]]; then
echo "Известных пакетных менеджеров не найдено. Установите ПО вручную."
else
echo "Пакетный менеджер: $install"
fi
${install} python3-pip

а) Инициализируется переменная install.

б) Условный оператор if (расскажем о нём в одной из следующих статей) проверяет: если существует файл /etc/os-release, то переменной distro присваивается значение строки с названием дистрибутива ОС:

  • grep -E '^ID=' /etc/os-release вырезает из /etc/os-release строку ID=
  • cut -d'=' -f2 вырезает название дистрибутива — слово после знака =
  • tr -d '"' удаляет кавычки, если они есть

В итоге переменная install получает значение названия ОС без кавычек — например, centos.

в) Условный оператор case (о нём также расскажем в статье про условные операторы) проверяет:

  • если значение переменной distro — ubuntu, debian или linuxmint:
    • обновляется список пакетов apt, стандартного пакетного менеджера для этого семейства дистрибутивов;
    • переменной install присваивается значение "установить при помощи apt";
  • либо, если значение distro — centos, fedora или rhel:
    • обновляется список пакетов yum;
    • устанавливается дополнительный репозиторий EPEL, в котором находится пакет pip;
    • переменная install получает значение "установить при помощи yum";
  • либо, если значение distro — arch или manjaro, переменная install получает значение "установить при помощи pacman";
  • либо, если значение distro — suse или opensuse, переменная install получает значение "установить при помощи zypper";
  • если значение distro не найдено среди вышеуказанных, переменной install присваивается значение unknown.

Если файл /etc/os-release не существует, то  переменной install также присваивается значение unknown.

г) Условный оператор if проверяет: если переменная install получила значение unknown, отображается сообщение:

Известных пакетных менеджеров не найдено. Установите ПО вручную.

В остальных случаях отображается сообщение:

Пакетный менеджер: <название пакетного менеджера>

д) Пакет python3-pip устанавливается при помощи найденного пакетного менеджера.

3. Рекомендуется записывать скрипты из нескольких команд в несколько строк, чтобы код было проще читать и поддерживать.

4. Используйте единообразные (в рамках одного скрипта) отступы, чтобы улучшить его читаемость. Можно устанавливать их как при помощи пробела, так и клавишей Tab, в зависимости от ваших предпочтений, корпоративных стандартов или стандартов вашего сообщества разработчиков.

5. Добавляйте краткие и понятные комментарии к смысловым блокам скрипта: это поможет и читателю, и самому автору позднее быстро разобраться в содержании и структуре кода.

6. По возможности используйте в скриптах переменные вместо фиксированных значений (чисел, путей и т. д.): так скрипты проще изменять при необходимости. Выносите параметры конфигурации и константы в переменные или файлы конфигурации.

7. Разделяйте скрипт на модули: выделяйте внутри скрипта отдельные функции или создавайте дополнительные скрипты, на которые можно ссылаться внутри основного. Это позволяет при необходимости изменять не весь скрипт целиком, а только его компоненты.

8. Для каждого шага продумайте случаи, в которых он может быть не выполнен: например, если по указанному пути нет файла с указанным именем.

9. Предусмотрите вывод однозначно трактуемых сообщений об ошибках, чтобы пользователю было ясно, как исправить ситуацию.

10. Проанализируйте, какие граничные значения (например, 0, отрицательные числа, очень длинные строки) действуют для скрипта и какие краевые случаи (например, отсутствие ввода, ввод недопустимых символов) могут возникнуть в ходе его работы. Проверьте корректность выводимых результатов для всех вариантов выполнения.

Граничные значения (в тестировании ПО) — границы диапазонов входных данных. Цель тестирования на граничные значения — проверить работу программы с максимальными и минимальными значениями ввода, а также значениями, которые часто вызывают ошибки при выполнении программы.

Краевые случаи (в тестировании ПО) — нетипичные ситуации, которые могут произойти во время работы программы и вызвать ошибки при её выполнении. Краевые случаи не всегда связаны с границами диапазонов входных значений.

Заключение

В статье даны рекомендации по созданию скриптов на bash и рассмотрены основные команды Linux с примерами применения.

Этот материал был полезен?

Скидка 25% новым клиентам!
Закажи сервер сегодня и получи скидку на первый месяц аренды!