Как выводить на экран команды оболочки по мере их выполнения в скрипте оболочки
В скрипте оболочки, как мне выводить на экран все вызываемые команды оболочки и разворачивать имена переменных? Например, для строки ls $DIRNAME я хотел бы, чтобы скрипт выполнил команду и вывел ls /full/path/to/some/dir. Цель - сохранить журнал всех вызываемых команд оболочки и их аргументов. Существует ли лучший способ генерации такого журнала?
Самый эффективный способ вывода выполняемых команд оболочки с расширением переменных - использование режима отладки set -x в вашем скрипте оболочки. Эта встроенная опция оболочки отображает каждую команду и ее расширенные аргументы перед выполнением, что делает ее идеальной для ведения журналов и отладки.
Содержание
- Использование set -x для отладки команд
- Расширение переменных в режиме отладки
- Ведение журнала команд в файлы
- Альтернативные подходы
- Практические примеры и лучшие практики
Использование set -x для отладки команд
Команда set -x - это встроенная опция оболочки, которая включает режим отладки, отображающий каждую команду и ее расширенные аргументы по мере выполнения скрипта. Это наиболее прямой метод для вывода команд оболочки с их фактическими аргументами.
#!/bin/bash
# Включаем режим отладки для вывода всех команд
set -x
# Примеры команд
echo "Запуск скрипта"
ls -l /tmp
cp file1.txt file2.txt
rm file1.txt
При выполнении этого скрипта вы увидите каждую строку команды с расширенными переменными перед ее выполнением:
+ echo 'Запуск скрипта'
Запуск скрипта
+ ls -l /tmp
всего 8
drwxrwxrwt 1 root root 4096 Янв 1 12:00 .
drwxr-xr-x 1 root root 4096 Янв 1 12:00 ..
+ cp file1.txt file2.txt
+ rm file1.txt
Чтобы временно отключить режим отладки внутри скрипта, используйте set +x:
#!/bin/bash
set -x # Включаем режим отладки
echo "Режим отладки ВКЛЮЧЕН"
set +x # Отключаем режим отладки
echo "Режим отладки ОТКЛЮЧЕН"
set -x # Снова включаем режим отладки
echo "Режим отладки снова ВКЛЮЧЕН"
Расширение переменных в режиме отладки
Одним из ключевых преимуществ set -x является автоматический показ переменных в их расширенной форме, что именно и было запрошено. Переменные заменяются их фактическими значениями перед отображением команды.
#!/bin/bash
set -x
DIRNAME="/usr/local/bin"
FILENAME="config.txt"
DEST_DIR="/backup"
ls -l "$DIRNAME"
cp "$FILENAME" "$DEST_DIR"
В выводе будут показаны расширенные переменные:
+ ls -l /usr/local/bin
всего 2048
-rwxr-xr-x 1 root root 12345 Янв 1 12:00 bash
-rwxr-xr-x 1 root root 67890 Янв 1 12:00 python
+ cp config.txt /backup
Для более детального отслеживания переменных вы также можете добавить явные команды echo:
#!/bin/bash
set -x
# Определяем переменные
SOURCE_DIR="/var/log"
BACKUP_DIR="/backups/logs"
DATE=$(date +%Y%m%d)
# Показываем значения переменных
echo "Переменные: SOURCE_DIR=$SOURCE_DIR, BACKUP_DIR=$BACKUP_DIR, DATE=$DATE"
# Команды с расширенными переменными
tar -czf "$BACKUP_DIR/logs_$DATE.tar.gz" -C "$SOURCE_DIR" .
Ведение журнала команд в файлы
Чтобы сохранить вывод отладки в файл вместо отображения в терминале, можно использовать перенаправление оболочки:
#!/bin/bash
# Включаем режим отладки и перенаправляем вывод в файл журнала
set -x 2> execution.log
echo "Запуск процесса резервного копирования"
rsync -avz /source/ /destination/
echo "Резервное копирование завершено"
# Или перенаправляем и stdout, и stderr
set -x &> execution.log
Для более сложного ведения журнала с отметками времени:
#!/bin/bash
# Функция для ведения журнала
log_command() {
local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
echo "[$timestamp] $*" | tee -a script.log
}
# Записываем каждую команду перед выполнением
log_command "Запуск скрипта"
log_command "Обработка файлов"
log_command "ls -l /tmp"
log_command "cp file1.txt file2.txt"
# Альтернатива с использованием trap для автоматического ведения журнала команд
trap 'echo "[ОТЛАДКА] $BASH_COMMAND"' DEBUG
Альтернативные подходы
Хотя set -x является наиболее распространенным методом, существует несколько альтернатив для ведения журнала команд оболочки:
Использование bash -x для выполнения скрипта
Выполните весь скрипт с включенным режимом отладки:
bash -x myscript.sh
Или выполните его и сохраните в файл:
bash -x myscript.sh > debug.log 2>&1
Использование переменной PS4 для пользовательского вывода отладки
Переменная PS4 определяет префикс, отображаемый для следов отладки. Вы можете настроить его, чтобы включать отметки времени или другую информацию:
#!/bin/bash
PS4='+${BASH_SOURCE}:${LINENO}: '
set -x
echo "Запуск процесса"
ls /tmp
Использование strace для трассировки системных вызовов
Для более детального ведения журнала выполнения можно использовать strace (хотя это показывает системные вызовы, а не команды оболочки):
strace -f -o strace.log bash myscript.sh
Использование команды script для записи сеанса
script -a session.log
# Запустите ваши команды
exit
Практические примеры и лучшие практики
Пример полного скрипта для ведения журнала
Вот комплексный пример, сочетающий несколько подходов:
#!/bin/bash
# Включаем режим отладки с пользовательским PS4 для лучшего ведения журнала
PS4='[${BASH_SOURCE}:${LINENO}] '
set -x
# Создаем файл журнала с отметкой времени
LOG_FILE="script_$(date +%Y%m%d_%H%M%S).log"
exec > >(tee -a "$LOG_FILE") 2>&1
echo "=== Начало выполнения скрипта ==="
echo "Файл журнала: $LOG_FILE"
# Примеры команд с переменными
SOURCE_DIR="/var/www"
BACKUP_DIR="/backups/websites"
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
echo "Создание резервной копии сайта..."
tar -czf "$BACKUP_DIR/website_$TIMESTAMP.tar.gz" -C "$SOURCE_DIR" .
echo "Резервное копирование успешно завершено"
echo "=== Завершение выполнения скрипта ==="
Лучшие практики для ведения журнала команд
- Используйте
set -xна уровне скрипта для комплексного ведения журнала - Комбинируйте с пользовательским PS4 для лучшей отслеживаемости
- Перенаправляйте вывод в файлы для постоянного ведения журнала
- Добавляйте отметки времени в записи журнала для лучшего отслеживания
- Используйте
trapдля автоматического ведения журнала определенных событий - Учитывайте влияние на производительность - ведение журнала отладки может замедлить выполнение скрипта
- Фильтруйте конфиденциальную информацию из журналов (пароли, API-ключи)
Вопросы производительности
Ведение журнала отладки может повлиять на производительность скрипта, особенно для циклов и частых операций. Используйте его стратегически:
#!/bin/bash
set -x
# Отключаем режим отладки для критичных по производительности участков
set +x
for i in {1..1000}; do
# Операции, критичные по производительности
echo "Обработка элемента $i"
done
set -x # Снова включаем режим отладки
# Продолжаем с отладкой
echo "Критичный по производительности участок завершен"
Для скриптов в производственной среде рассмотрите возможность условного включения режима отладки:
#!/bin/bash
# Включаем режим отладки, если переменная окружения DEBUG установлена
if [[ "${DEBUG:-}" == "1" ]]; then
set -x
echo "Режим отладки включен"
fi
# Остальная часть вашего скрипта
Источники
- Вопросы для собеседований по скриптингу оболочки для DevOps в 2025 - StarAgile
- Position Is Everything - Как выполнить исполняемый файл в Linux
Заключение
- Используйте
set -xкак основной метод для вывода команд оболочки с расширенными переменными в ваших скриптах - Комбинируйте с перенаправлением (
> filenameили>> filename) для сохранения журналов постоянно - Настраивайте
PS4для лучшего форматирования следов отладки с номерами строк и отметками времени - Учитывайте влияние на производительность и используйте условное ведение журнала отладки для скриптов в производственной среде
- Альтернативные методы включают
bash -x,straceи командуscriptдля разных потребностей в ведении журнала
Подход с использованием set -x предоставляет наиболее прямое решение для вашей задачи вывода команд с расширенными переменными, делая его идеальным для отладки и ведения журналов в скриптах оболочки.