eval: почему опасен и когда реально нужен
В Bash почти любую строку можно превратить в команду через eval. Он берёт переданный текст и запускает его как новый Bash-код.
Именно поэтому это один из самых спорных инструментов в shell-скриптах.
▪️Как работает eval
Простой пример:
cmd="ls -la"
eval "$cmd"
Bash сначала получает строку:
ls -la
а затем выполняет её как обычную команду.
▪️Где возникает проблема
Если данные приходят от пользователя:
read input
eval "$input"
Теперь введённый текст становится кодом.
Например, вместо ожидаемого аргумента можно передать дополнительные команды, которые Bash выполнит при обработке строки.
Главная проблема eval - повторный разбор данных как команд.
▪️Почему кавычки не всегда спасают
Например:
file="test.txt"
eval "cat $file"
Пока значение простое - всё работает.
Но если внутри появятся специальные символы:
file="file name.txt"
или другие управляющие конструкции, поведение может отличаться от ожидаемого.
▪️Частая замена eval
Вместо хранения команды строкой:
cmd="ls -la /tmp"
eval "$cmd"
лучше использовать массив:
cmd=(ls -la /tmp)
"${cmd[@]}"
Теперь Bash хранит команду и аргументы отдельно.
▪️Когда eval действительно нужен
Иногда без него сложно обойтись. Например, при работе с динамическими именами переменных:
name="USER"
eval "echo \$$name"
Но даже здесь часто есть более безопасные варианты:
declare -n ref="$name"
echo "$ref"
▪️Проверка перед использованием
Если всё же нужен eval, данные должны быть полностью контролируемыми:
case "$action" in
start|stop|restart)
eval "service_$action"
;;
esac
Здесь значение ограничено заранее известным списком.
▪️Почему это важно
eval не является “плохой” командой сам по себе. Проблема появляется, когда данные превращаются в код.
В большинстве случаев массивы, case, функции или declare решают задачу безопаснее. eval стоит оставлять только для ситуаций, где действительно нужен второй проход парсинга Bash.
BashTex 📱 #eval
В Bash почти любую строку можно превратить в команду через eval. Он берёт переданный текст и запускает его как новый Bash-код.
Именно поэтому это один из самых спорных инструментов в shell-скриптах.
▪️Как работает eval
Простой пример:
cmd="ls -la"
eval "$cmd"
Bash сначала получает строку:
ls -la
а затем выполняет её как обычную команду.
▪️Где возникает проблема
Если данные приходят от пользователя:
read input
eval "$input"
Теперь введённый текст становится кодом.
Например, вместо ожидаемого аргумента можно передать дополнительные команды, которые Bash выполнит при обработке строки.
Главная проблема eval - повторный разбор данных как команд.
▪️Почему кавычки не всегда спасают
Например:
file="test.txt"
eval "cat $file"
Пока значение простое - всё работает.
Но если внутри появятся специальные символы:
file="file name.txt"
или другие управляющие конструкции, поведение может отличаться от ожидаемого.
▪️Частая замена eval
Вместо хранения команды строкой:
cmd="ls -la /tmp"
eval "$cmd"
лучше использовать массив:
cmd=(ls -la /tmp)
"${cmd[@]}"
Теперь Bash хранит команду и аргументы отдельно.
▪️Когда eval действительно нужен
Иногда без него сложно обойтись. Например, при работе с динамическими именами переменных:
name="USER"
eval "echo \$$name"
Но даже здесь часто есть более безопасные варианты:
declare -n ref="$name"
echo "$ref"
▪️Проверка перед использованием
Если всё же нужен eval, данные должны быть полностью контролируемыми:
case "$action" in
start|stop|restart)
eval "service_$action"
;;
esac
Здесь значение ограничено заранее известным списком.
▪️Почему это важно
eval не является “плохой” командой сам по себе. Проблема появляется, когда данные превращаются в код.
В большинстве случаев массивы, case, функции или declare решают задачу безопаснее. eval стоит оставлять только для ситуаций, где действительно нужен второй проход парсинга Bash.
BashTex 📱 #eval