× К оглавлению На главную Об авторе

   Дата и время публикации:

Суть проблемы и решение

1. Проблема

Который заключается в основном не в поиске путей включения трассировки выполнения команд в BASH,а их возможность журналирования в отдельном файле и получения, например, их полного пути и размера, как показано в листинге 1.1 .

Листинге 1.1

#!/bin/bash -x
... 
ls /bin/bash
df | egrep 'home\|rootfs'
users
echo "The log file contains some command that were ran in SHELL"
echo "done."

Выполнение которого будет выполняться в перемешку с выводом не только название самих команд (с префиксом "+") на устройства вывода ошибок (STDERR), как показано в дампе 1.2, отображающий печать их выполнения на стандартное устройства STDOUT

Листинге 1.2

+ date +%c-%s
+ ls /bin/bash
/bin/bash
+ df
+ egrep 'home\|rootfs'
+ users
user
+ echo 'The log file contains some command that were ran in SHELL'
The log file contains some command that were ran in SHELL
+ echo done.
done.

2. Решение

Для чего, сначала рассмотрим две основных формы одновременного перенаправления со стандартного устройства вывода STDOUT (файловый дескриптор 1) и стандартного вывод ошибок STDERR (файловый дескриптор 2) в файл, который обозначается далее word [3.1].

Вторая форма является семантически эквивалентной и наиболее популярной : >word 2>&1, как показано в листинге 2.1.

Листинге 2.1

#!/bin/bash -x
...
exec > $PWD/bash_log.out 2>&1

Перенаправляя весь поток сообщений с STDOUT и STDERR в файл с начала до конца выполнения скрипта . При этом нужно помнить, что все летящие сообщения будут направлены прямо в файл $PWD/bash_log.out минуя всех и вся [3.3]...

Поэтому, если укажем 2> $HOME/bash_log.stderr вместо exec > $HOME/bash_log.out 2>&1, который закоментировали, как показано в листинге 2.2

Листинге 2.2

#!/bin/dash -x
... 
#exec > $HOME/bash_log.out 2>&1
exec 2> $HOME/bash_log.stderr 
...

На выходе которого получим некоторый файл, прочитав который с некоторой фильтрацией, которая показана в листинге 2.3

Листинге 2.3

...
cat bash_log.stderr  | sed 's/^[+]\{1,2\}[[:space:]]\(.*\)$/\1/' | awk '{ print $1 }' | xargs which | xargs stat --printf="%n\t\t%x\t\t%s\n"
...

Получим на выводе абсолютные пути, полученные which, и размеры, извлеченные по ним stat --printf="%n\t\t%x\t\t%s\n" [3.1], всех используемых команд и зарегистрированных команд в файле $HOME/bash_log.stderr, как показано в дамп 2.4

Листинге 2.4

Пн 29 мар 2021 09:32:11-1616999531
...
/usr/bin/ls		2021-03-29 09:03:33.749229414 +0300		147176
/usr/bin/df		2021-03-29 09:16:58.370080238 +0300		93936
/usr/bin/egrep		2021-03-29 09:16:58.370080238 +0300		28
/usr/bin/users		2021-03-29 09:28:46.773728789 +0300		39744
/usr/bin/echo		2021-03-29 08:56:59.487833562 +0300		39712
/usr/bin/echo		2021-03-29 08:56:59.487833562 +0300		39712

Но, если вывести время, как было показано только что в дампе выше, то увидим, что есть небольшая засада, а именно, что ни одно из значение времени доступа к файлу, выведенное утилитой STAT, не соответствует времени начала регистрации запуска команд, выведенная командой date.

Но, это уже иная история...

3. Библиография

3.1 BASH. Redirecting Standard Output and Standard Error

3.2 HowToGeek. How to use the stat command on linux

3.3 Baeldung. The Uses of the Exec Command in Shell Script