И на старуху бывает проруха
Сегодня решил поделиться отрицательным опытом. Код, приведенный в статье лучше не использовать.
читать первым в телеграм читать первым в макс
У меня возникла необходимость распарсить файл типа:
xxx yy "zz zz zz zz"
Видно, что однословные поля разделены пробелом, а многословные заключены в кавычки. Распарсить такой файл на awk можно, но не быстро. Нужно писать код.
А на bash - вроде просто:
set -- xxx yy "zz zz zz zz"
echo $# $1 $2 $3
# 3 xxx yy zz zz zz zz
Проверил — вроде работает. Классно, пишу цикл, проверяю на файле — не работает. Упрощаю код до минимума.
REC='xxx yy "zz zz zz zz"'
set -- $REC
echo $# $1 $2 $3
# 6 xxx yy "zz
Очевидно, разбились по пробелам. Перепробовал кавычки — не выходит. Не придумал ничего лучшего, как использовать конструкцию:
REC='xxx yy "zz zz zz zz"'
eval "set -- $REC"
echo $# $1 $2 $3
# 3 xxx yy zz zz zz zz
Все работает как надо.
После этого я решил распарсить реальный лог apache.
Все работало прекрасно, но на определенной строчке все зависало на несколько секунд, а потом продолжалось. Начал разбираться, и когда понял, что происходит — чуть не поседел.
Там была инъекция:
$(ping${IFS}-c${IFS}6${IFS}aa.bb.cc.dd)
Переменная IFS использовалась вместо пробела. Короче, команда выглядела так:
ping -c 6 aa.bb.cc.dd
Проблема возникла из-за того, что оператор eval разворачивал не только мою переменную, а все переменные, в том числе и из лога, попутно выполняя команды.
В общем, если я раньше считал оператор eval — бесполезным, то теперь я считаю его вредным.
Вот такой опыт.
