loc="locationA"
usr="user1"
fw_loc=$(</home/user/Desktop/FW_RULES.txt)
ssh -A -tt [email protected] <<ABC
fw_orig="$fw_loc"
fw_cmpr=\$(ssh root@$loc -o LogLevel=ERROR uci show firewall)
wc --lines <<<"\$fw_orig"
wc --lines <<<"\$fw_cmpr"
diff -s <(echo "\$fw_orig") <(echo "\$fw_cmpr")
exit
ABC
У меня есть скрипт, в котором я загружаю локальный текстовый файл в переменную в документе HERE. Текстовый файл содержит около 370 строк. Затем я беру правила брандмауэра с другого сервера и пытаюсь сравнить, совпадают ли правила FW. Однако после строкиfw_orig="$fw_loc"Оболочка автоматически расширяет переменную (хотя на самом деле это не нужно), а терминал издает звуковой сигнал и делает прерывания в тексте, например:
[user2@jump ~]$ fw_orig="firewall.defaults=defaults
>firewall.poplanhttp3=rule
l
> firewall.poplanhttp3.name='poplanhttp3'
> firewall.lanpopchhttp2.name='lanpopahttp5'
> firewal
> firewall.lanpopchhttp2.dest='POPA'
.
firewall.poplanssh2.dest_port='27'
i
> firewall.poplanssh2.target='ACCEPT'
/
Текст прерывается на разных строках каждый раз, когда я его запускаю. Почему происходят эти прерывания со звуком и как этого избежать? Интересно, что позже в моем скрипте я сравниваю обе переменные, и количество строк совпадает, но команда diff находит различия между переменными во всех прерываниях "$fw_orig".
РЕДАКТИРОВАТЬ когда я попытался записать переменную в файл, а затем сравнить ее:
echo "\$fw_orig">/home/user2/file
..
..
diff -s <(echo "\$fw_orig") /home/user2/file
Команда dif вернула:
Files /dev/fd/63 and /home/user2/file are identical
возможно, это поможет понять, что происходит... однако сравнение файл <> переменная работает, сравнение переменная <> переменная не работает...
решение1
Давайте упростим пример, сосредоточившись только на неисправной линии и некоторых ее предпосылках, и исключим ненужные шаги (например, ssh).
Переменная fw_loc
содержит содержимое файла. В ней наверняка много новых строк и пробелов; предположительно, есть и другие специальные символы.
В то время как я не вижу содержимое этого файла, я пытаюсь быть злым. Итак, вот урезанная версия того, что вы делаете, с некоторым воображаемым злым содержимым из этого файла:
fw_loc='foo"; rm -rf "/ouch'
cat <<ABC
fw_orig="$fw_loc"
ABC
Если вы выполните это, вы увидите, что это выводит
fw_orig="foo"; rm -rf "/ouch"
В вашем конкретном случае он не cat
редактируется, а отправляется на удаленный хост для выполнения.
Уровень экранирования явно недостаточен. Я считаю, что это причина странного поведения, которое вы испытываете, хотя я не уверен, на каких специальных символах он не срабатывает в вашем случае.
Одним из возможных подходов является экранирование значения, чтобы последующее присваивание в bash (на удаленной стороне) работало правильно, используя printf %q
:
fw_loc='foo"; rm -rf "/ouch'
cat <<ABC
fw_orig=$(printf %q "$fw_loc")
ABC
Обязательно используйте двойные кавычки непосредственно вокруг ссылки на переменную $fw_loc
(иначе printf
она не будет выполнять свою функцию должным образом), но не вокруг $(...)
подстановки команды (поскольку printf %q
она полагается на ее вывод, не заключенный в кавычки)!
Это печатает
fw_orig=foo\"\;\ rm\ -rf\ \"/ouch
что эквивалентно fw_loc
определению, данному выше.
Возможно, вам придется применить этот прием еще несколько раз в вашем сценарии, я не рассматривал этот момент более подробно.
Альтернативным решением может быть разделение этой сложной логики на более мелкие шаги, например, передача файла с помощью scp
, возможно, даже на локальный хост и выполнение сравнения локально.