TGViewer
Bash Days | Linux | DevOps Bash Days | Linux | DevOps @bashdays · 23.6K subscribers
Post #483 10.4K
🔥 Кишочки. Короче познавательное.

В документации для команды eval довольно пространное описание. Давай сегодня с ней поковыряемся.

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

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

Короче дохера всего. Полный список можешь найти в разделах SIMPLE COMMAND EXPANSION и EXPANSION выполнив:

man 1 bash


Ну дак вот, команда eval запускает эту обработку кода. Но прежде чем команда eval будет запущена, код должен быть обработан.

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

Очевидно? Совсем нет. Но вот оно так работает, чо с него взять.

Эта возможность используется по-разному, например для генерации и последующего исполнения кода.

Также если знать некоторые последовательности обработки кода, можно сгладить некоторые особенности самой обработки.

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

Расширение переменной в строке с командой echo происходит гораздо позже, чем расширение фигурных скобок.

Поэтому используем eval. Первая обработка развернет переменную. Вторая, которая запустит eval, развернет конструкцию с фигурными скобками.

str={1..10}   
echo $str
eval echo $str


В результате получим:

{1..10}
1 2 3 4 5 6 7 8 9 10


Другой пример. Здесь из-за использования одинарных кавычек, переменной присваивается указанная строка, а не значение переменной.

И обработка строки делает расширение переменной один раз. Получаем значение переменной s0. Количество обработок строки равно количеству eval плюс один.

(s0=100 ; s1='$s0' ; s2='$s1' ; echo "$s2")
(s0=100 ; s1='$s0' ; s2='$s1' ; eval echo "$s2")
(s0=100 ; s1='$s0' ; s2='$s1' ; eval eval echo "$s2")


На экране ты увидишь:

$s1
$s0
100


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

Это значит, что если ты откроешь файл на чтение и слева укажешь переменную содержащую нужный дескриптор, эта переменная не будет участвовать в перенаправлении.

И раз не указан дескриптор, файл будет ассоциирован со стандартным потоком ввода.

Решение. Делаем так, чтобы при первой обработке перенаправление было распознано как обычная строка и была расширена переменная. Тогда на второй обработке слева от оператора перенаправления будет стоять номер дескриптора из переменной.

(fd=6 ; exec "$fd"</dev/null) 
(fd=6 ; eval exec "$fd</dev/null")
(fd=6 ; eval exec "$fd"\</dev/null)
(fd=6 ; eval exec "$fd"'</dev/null')


В первой строке: /dev/null на stdin и пытается запустить 6.

Круглые скобки использовались, чтобы не засорять текущую оболочку. И чтобы она не завершилась на первом примере. Из-за того что на её стандартный ввод повесили /dev/null. Проверяем какой дескриптор ассоциирован с устройством /dev/null.

bash -c 'shopt -s execfail ; fd=6 ; exec $fd</dev/null ; ls -l /proc/$$/fd'  
bash -c 'shopt -s execfail ; fd=6 ; eval exec $fd\</dev/null ; ls -l /proc/$$/fd'
bash -c 'shopt -s execfail ; fd=6 ; eval exec "$fd</dev/null" ; ls -l /proc/$$/fd'


Этот «хак» с перенаправлением можно использовать для исследований. Когда требуется определённый диапазон дескрипторов.

Почитать: man 1 bash, разделы:

# REDIRECTION  
# SHELL BUILTIN COMMANDS -> eval
# SHELL BUILTIN COMMANDS -> exec
# SHELL BUILTIN COMMANDS -> shopt


А завтра запускаем конкурс с картами. Моя ленивая жопа соизволила добраться до почты.

Хороших выходных!

tags: #bash
—
🔔 @bashdays
More from @bashdays
  1. Sep 29, 2026Самый жаркий холивар в команде — это не systemd, а какие заказать роллы на всю команду. Од…
  2. Sep 24, 2026Post #1565
  3. Sep 23, 2026Здрасти приехали, решил я в кой-то веке воспользоваться услугами Codex, создал аккаунт, по…
  4. Sep 22, 2026Всем привет, с вами TagdTagd. Сегодня опять поднимем тему архивов, но немного с другой сто…
  5. Sep 15, 2026Всем привет, с вами TagdTagd. И это вторая часть. Практическая. С первой частью можешь озн…
  6. Sep 11, 2026🤖 DevOps в эпоху AI трансформации: что работает уже сейчас! 17 сентября Сбер собирает Dev…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →