Как запускать несколько команд в Linux одновременно

Введение
Терминал Linux — мощный инструмент для управления системой через текстовые команды. Простые операции: работа с файлами, установка пакетов, управление службами — часто выполняются быстрее через оболочку. Но ввод команд по одной неэффективен при повторяющихся задачах. Чтобы ускорить работу и автоматизировать последовательности, команды объединяют в одну строку или помещают в скрипт.
В этой статье вы найдёте понятные правила выбора между операторами, примеры, шаблоны сценариев и чек‑листы для ролей (разработчик, администратор), рекомендации по безопасности и тестированию. В конце — краткая памятка и decision‑tree в Mermaid для быстрой навигации.
Important: Код в примерах безопасно иллюстрирует поведение операторов; перед запуском команд, затрагивающих данные или систему, выполните бэкап или протестируйте в изолированном окружении.
Основные операторы для запуска нескольких команд
Linux поддерживает несколько способов последовательного и условного выполнения команд в оболочке:
- ; — выполняет все команды подряд независимо от кода возврата предыдущей команды.
- && — выполняет следующую команду только если предыдущая завершилась успешно (код возврата 0).
- || — выполняет следующую команду только если предыдущая завершилась с ошибкой (код возврата не 0).
- Также применимы: | (конвейер), & (фоновый запуск), скобки (subshell) и фигурные скобки для группировки команд.
Ниже — подробное описание каждого оператора с практическими примерами.
Точка с запятой ; — всегда выполнить
Описание: Оператор ; разделяет команды и гарантирует, что каждая будет запущена по порядку, независимо от результата предыдущей.
Синтаксис:
commandA ; commandB ; commandCПример: вывести имя пользователя и имя хоста:
whoami ; hostnameКогда использовать: когда команды не зависят друг от друга или вы хотите выполнить все шаги независимо от ошибок.
Примечание: если любая команда вызывает серьёзные побочные эффекты, используйте проверки возврата, чтобы избежать нежелательных действий.
Альтернатива: если частично зависимые операции, рассмотрите комбинацию && и ||.
Логическое И && — выполнить при успешном завершении
Описание: Оператор && выполняет следующую команду только если предыдущая вернула код 0 (успех).
Синтаксис:
commandA && commandBПример: создать каталог и сразу перейти в него только при успешном создании:
mkdir Documents && cd DocumentsКогда использовать: при построении цепочек, где следующий шаг имеет смысл только при успешном завершении предыдущего (сборка → тест → деплой и т. п.).
Совет: для сценариев автоматической установки полезно сочетать && с проверками состояния и логированием.
Логическое ИЛИ || — выполнить при ошибке предыдущей команды
Описание: Оператор || выполняет правую команду, только если левая завершилась с ошибкой (код возврата ≠ 0).
Синтаксис:
commandA || commandBПример: создать файл, только если его нет:
find . -name Document.txt || touch Document.txtЗдесь find возвращает 0, если файл найден; тогда touch не будет вызван. Если find вернёт ненулевой код, touch создаст файл.
Когда использовать: для резервных планов, обработчиков ошибок или попыток альтернативного пути при неудаче.
Комбинация операторов и порядок выполнения
Операторы можно комбинировать в одной строке. Важно понимать приоритет: && и || имеют одинаковый приоритет и оцениваются слева направо, точка с запятой выполняется как разделитель последовательностей. Без явной группировки комбинации могут дать неожиданный результат.
Пример, который часто вводит в заблуждение:
commandA || commandB && commandCЭто читается как:
- Выполнить commandA. Если commandA неуспешна, выполнить commandB.
- Затем, если commandB успешна (или если commandA была успешна и commandB вовсе не запускалась), выполнить commandC.
Практический пример: создать папку, если её нет, и вывести сообщение:
find . -name Document || echo "Directory not found" && mkdir DocumentОднако поведение может отличаться от ожидаемого, если вы хотите, чтобы mkdir выполнялся только при неудаче find. Для явной семантики используйте скобки или подшелл.
Группировка команд: скобки и фигурные скобки
- Подшелл: ( … ) — команды в круглых скобках выполняются в подшелле; изменения окружения (cd, export) не повлияют на родительский шелл.
(commandA && commandB) || commandC- Группировка без подшелла: { … ; } — команды выполняются в текущем шелле; обязательно ставьте точку с запятой перед закрывающей фигурной скобкой.
{ commandA && commandB ; } || commandCПример: создать каталог и перейти в него в одном контексте (без подшелла):
{ mkdir newdir && cd newdir ; }Если использовать (mkdir newdir && cd newdir), переход в каталог произойдёт только в подшелле и не сохранится в текущем сеансе.
Когда использовать: выбирайте ( ) если хотите изолировать побочные эффекты, и { } когда изменения окружения должны сохранитьcя.
Конвейеры и фоновые процессы
- Пайп | передаёт stdout одной команды в stdin следующей.
cat file.txt | grep pattern | wc -l- Фоновый запуск &: запускает процесс в фоне; оболочка немедленно возвращает управление.
long_running_task &Комбинации с логическими операторами тоже возможны, но учитывайте, что код возврата для фонового процесса не будет ждать завершения задачи.
Сценарии (скрипты) — запуск серия команд как программы
Скрипт — удобный способ сохранять и повторно запускать набор команд. Пример простого скрипта обновления системы (Debian/Ubuntu):
- Создайте файл с расширением .sh, например update_system.sh
- Поместите в него:
#!/bin/bash
set -euo pipefail
sudo apt update && sudo apt upgrade -y- Сделайте исполняемым и запустите:
chmod +x update_system.sh
./update_system.shПояснения:
- set -e завершит скрипт при первой ошибке.
- set -u обнаружит использование необъявленных переменных.
- set -o pipefail гарантирует, что пайп вернёт ненулевой код, если хотя бы одна команда в цепочке неуспешна.
Критерии приёмки: скрипт должен корректно завершаться с кодом 0 при успешном выполнении, логировать критичные шаги и не требовать интерактивного ввода без явного подтверждения.
Безопасность и приватность
Important: Никогда не храните пароли, токены или другие секреты в открытых скриптах. Используйте безопасное хранилище паролей (secret manager), переменные окружения в защищённых CI или prompting при необходимости.
Рекомендации:
- Ограничьте права на скрипты: chmod 700.
- Проверяйте вводимые имена файлов/путей перед выполнением команд с удалением или перезаписью.
- При работе с sudo используйте минимально необходимые привилегии и проверенные команды.
Приватность: если ваш скрипт логирует данные, убедитесь, что логи не содержат персональных данных или чувствительной информации, соответствуйте внутренним правилам конфиденциальности и законодательству.
Отладка и диагностика
Как узнать код возврата? Команда echo $? вернёт код последней команды.
false || echo "предыдущая команда завершилась с ошибкой" ; echo $?Полезные приёмы:
- set -x — включить трассировку выполнения (печать каждой команды перед запуском).
- trap ‘echo “Ошибка на строке $LINENO”; exit 1’ ERR — ловушка при ошибке.
Распространённые ошибки и когда это не сработает
- Ожидание, что && и || имеют приоритет: они выполняются слева направо; без группировки результат может отличаться от ожидаемого.
- Переход в каталог в подшелле ( ) не изменит текущий рабочий каталог родительского процесса.
- Фоновые процессы (&) не блокируют выполнение последующих команд и не гарантируют завершения к моменту проверки их статуса.
Counterexample: команда
false && echo OK || echo FAILВыведет FAIL, потому что false возвращает ошибку, && пропускает правую часть, затем || срабатывает.
Методика выбора оператора (мини‑методология)
- Определите зависимость: нужна ли следующая команда только при успехе предыдущей? Если да — &&.
- Нужно ли выполнить альтернативу при ошибке? Если да — ||.
- Независимые действия — ;.
- Если логика сложная, сгруппируйте выражения с ( ) или { } для явного порядка.
- В скриптах используйте set -euo pipefail и trap для надёжного поведения.
Шаблоны и готовые сниппеты
Шаблон: безопасный сценарий с логированием
#!/bin/bash
set -euo pipefail
trap 'echo "Ошибка на строке $LINENO" >&2' ERR
log() { echo "[$(date -Iseconds)] $*"; }
log "Начало выполнения"
commandA && log "commandA выполнилась" || { log "commandA НЕ выполнилась"; exit 1; }
commandB ; log "commandB запущена независимо"
log "Готово"Шаблон: попытка выполнить резервную команду при ошибке
primary_command || { echo "Primary failed, running fallback"; fallback_command; }Тест‑кейсы для команды с && и ||:
- Сценарий: первая команда успешна → вторая выполняется (для &&).
- Сценарий: первая команда неуспешна → проверка, что || запускает альтернативную команду.
- Сценарий: проверка, что ( ) изолирует изменения окружения.
Чек‑лист по ролям
Разработчик:
- Понимать exit code и использовать && для последовательности сборка→тест.
- Упаковывать часто повторяющиеся цепочки в скрипты.
- Не хранить секреты в скриптах.
Системный администратор:
- Использовать set -e для критичных обновлений.
- Логировать действия и использовать trap для корректной обработки ошибок.
- Тестировать в staging перед production.
Инженер DevOps:
- Интегрировать скрипты в CI/CD с явными проверками успешности.
- Использовать секрет‑менеджеры и роутинг логов.
Decision tree (Mermaid)
flowchart TD
A[Нужно выполнить несколько команд?] --> B{Команды зависимы?}
B -- Да --> C{Требуется выполнение только при успехе?}
C -- Да --> D[Использовать &&]
C -- Нет --> E{Нужен резерв при ошибке?}
E -- Да --> F[Использовать || или сочетание с { }]
E -- Нет --> G[Группировка ' ' или { }]
B -- Нет --> H[Использовать ;]
D --> I[Рассмотреть set -e в скрипте]
F --> I
G --> I
H --> IКритерии приёмки
- Команды выполняются в ожидаемой последовательности при различных кодах возврата.
- Скрипты корректно завершаются при ошибках (при необходимости) и дают понятные логи.
- Никакие секреты не попадают в исходные файлы или логи.
Мини‑фактбокс
- Код возврата 0 означает успех; любой ненулевой код — ошибка.
- set -e останавливает скрипт при первой ошибке (но будьте осторожны с &&/|| и пайпами).
- ( ) создаёт подшелл; { } выполняет в текущем шелле.
Примеры реальных сценариев
- Быстро собрать проект и запустить тесты, остановиться если сборка неудачна:
make build && make test- Попытаться создать резервную копию, если основной метод не сработал:
rsync -avz /data remote:/backup || tar czf /tmp/backup.tar.gz /data- Выполнить команду в фоне и дождаться завершения, затем проверить код возврата:
long_task & pid=$!
wait $pid
echo "exit code: $?"Советы по локализации и совместимости
- Синтаксис команд оболочки POSIX совместим с большинством современных дистрибутивов; bash добавляет расширения.
- Для максимальной переносимости используйте /bin/sh и POSIX‑совместимые конструкции.
- В дистрибутивах на базе Debian используйте apt, в RHEL‑based — dnf/yum (проверяйте пакетный менеджер перед автоматизацией).
Сводка
Используйте:
- ; — когда команды независимы и нужно выполнить все подряд.
- && — когда следующий шаг имеет смысл только при успехе предыдущего.
- || — для резервной логики или обработки ошибок.
Группируйте команды, применяйте set -euo pipefail в скриптах, используйте trap для надёжной обработки ошибок. Тестируйте скрипты в безопасной среде и не храните секреты в открытом виде.
Сводка на одну строку: выбирайте оператор по логике зависимостей между командами, группируйте выражения для явной семантики и автоматизируйте повторяющиеся задачи через скрипты с защитой и логированием.
Краткий глоссарий:
- exit code: краткий числовой статус завершения команды (0 = успех).
- подшелл: отдельный экземпляр оболочки, выполняющий набор команд.
- pipefail: опция, влияющая на код возврата конвейера.
Последнее напоминание: прежде чем запускать команды, которые изменяют файлы или систему, убедитесь в наличии резервных копий и тестовой среды.
Похожие материалы
Как устроить идеальную вечеринку для просмотра ТВ
Как распаковать несколько RAR‑файлов сразу
Приватный просмотр в Linux: как и зачем
Windows 11 не видит iPod — способы исправить
PS5: как настроить игровые пресеты