Эта статья была первоначально размещена 2 октября 2018 года по адресу: https://nickjanetakis.com/blog/here-is-why-you-should-quote-your-variables-in-bash
Работая над завершением следующего курса, я заканчивал Ansible Роль для выпуска сертификатов SSL с использованием acme.sh Анкет
Роль поддерживает выдачу сертификатов с одним доменом, многодоменом и подстановочными знаками с использованием API V2 Encrypt. Все это обрабатывается acme.sh , но я сделал судебный звонок, чтобы создать имя файла сертификата на диске, чтобы соответствовать первому сертификату, переданному в Acme.sh.
С точки зрения, это похоже на это:
acme_sh_domain: - domains: ["*.example.com", "example.com"]
Когда все заканчивается, вы получите *.Example.com.Key
и *.Example.com.pem
Сертификаты для использования с NGINX или чем -то еще читают ваши СЕРТ.
Обычно я не сталкиваюсь с файлами, которые начинаются с *
, так что это приведет к веселью . Я неустанно цитирую переменные, поэтому у меня не было слишком много проблем, но когда я играю на терминале, испытывая роль, которую я забыл процитировать MV
командование один раз И вот мы.
Демонстрируя проблему
Если у вас есть Unix-подобная среда, чтобы проверить это на (macos, linux или wsl должны работать), не стесняйтесь следить за этим:
Заказ того, как вы создаете каталоги, имеет значение:
mkdir -p /tmp/demoproblem cd /tmp/demoproblem mkdir test.example.com mkdir *.example.com # mkdir: cannot create directory 'test.example.com': File exists rm -rf * mkdir *.example.com mkdir test.example.com ls -la # drwxr-xr-x 1 nick nick 4096 Sep 29 15:15 *.example.com # drwxr-xr-x 1 nick nick 4096 Sep 29 15:15 test.example.com
На WSL ls
Командные издают окружающие отдельные кавычки вокруг *.Example.com
. На истинной системе Unix вы бы в конечном итоге увидели '*.Example.com'
Но это только разница в презентации с ls
Анкет
Случайно удаление неожиданных каталогов:
rm -rf *.example.com ls -la # drwxr-xr-x 1 nick nick 4096 Sep 29 15:19 . # drwxrwxrwt 1 root root 4096 Sep 29 14:59 ..
Если вы только хотели удалить *.Example.com
(Одна папка) Тогда вы находитесь в мире обиды, потому что она удаляла каждый каталог, который соответствовал шаблону.
Защита от удаления всего, что соответствует звездочке:
mkdir *.example.com test.example.com rm -rf "*.example.com" ls -la drwxr-xr-x 1 nick nick 4096 Sep 29 15:20 . drwxrwxrwt 1 root root 4096 Sep 29 14:59 .. drwxr-xr-x 1 nick nick 4096 Sep 29 15:20 test.example.com
Там мы идем, с цитатами все работает как задумано. Вы могли бы также избежать звездочки с rm -rf \*. example.com
вместо.
Двойная проверка, чтобы убедиться, что он работает с Mkdir:
mkdir "*.example.com" ls -la drwxr-xr-x 1 nick nick 4096 Sep 29 15:23 *.example.com drwxr-xr-x 1 nick nick 4096 Sep 29 15:23 test.example.com
Как мы видим, цитирование также позволяет нам создавать *.Example.com
даже если test.example.com
существуют.
Так почему вы должны цитировать свои переменные?
Представьте себе, если это имя каталога было в переменной, и оно не указано, и вы запустили сценарий, который удалил сертификат. Вы бы удалили этот сертификат вместе с любым другим сертификатом, который у вас был в этом каталоге.
Это могло бы повлиять на несколько проектов, и это могло бы легко подкрасться к производству незамеченным, если бы вы никогда не выпустили сертификат подстановочного знака, потому что 20 раз вы выпустили сертификат, он работал нормально, поэтому вы думали, что находились в ясном виде.
Вот пример сценария, не работающего в соответствии с пропущенными цитатами:
DOMAIN_DIR=*.example.com [ -d $DOMAIN_DIR ] && echo "Directory found" || echo "Directory not found" # bash: [: *.example.com: binary operator expected # Directory not found
Теперь как это для безумия. На этом этапе у нас есть *.Example.com
и test.example.com
В нашем каталоге, но теперь беги mkdir aaa.example.com
к Создайте третий каталог.
DOMAIN_DIR=*.example.com [ -d $DOMAIN_DIR ] && echo "Directory found" || echo "Directory not found" # bash: [: too many arguments # Directory not found
Теперь мы получаем другую ошибку.
А вот и та же настройка, но цитируя Domain_DIR во время назначения:
DOMAIN_DIR="*.example.com" [ -d $DOMAIN_DIR ] && echo "Directory found" || echo "Directory not found" # bash: [: too many arguments # Directory not found
Это все еще не помогает нам.
Вот тот же сценарий, но цитируя только переменную:
DOMAIN_DIR=*.example.com [ -d "$DOMAIN_DIR" ] && echo "Directory found" || echo "Directory not found" # Directory found
Это сработало, но мы все равно должны процитировать задание, чтобы быть в безопасности.
Пока мы находимся в этом, давайте процитируем как назначение, так и переменную и используем долларовые крики:
DOMAIN_DIR="*.example.com" [ -d "${DOMAIN_DIR}" ] && echo "Directory found" || echo "Directory not found" # Directory found
В случае сомнений, процитируйте свои задания и используйте цитаты + долларовые курки вместе при ссылке на переменные. Да, это более многословно, но еще несколько персонажей намного лучше, чем пробуждение к работе Cron, которая удаляла каждый сертификат на вашем сервере в середине ночи, или вызвало некоторые другие странные побочные эффекты в вашем сценарии.
Только не просто используйте долларовые кудри (даже с цитированным заданием):
DOMAIN_DIR="*.example.com" [ -d ${DOMAIN_DIR} ] && echo "Directory found" || echo "Directory not found" # bash: [: too many arguments # Directory not found
Этого не достаточно.
Использование инструментов, которые помогут нам вспомнить наши цитаты
Даже с большим опытом вы можете забыть использовать цитаты время от времени. К счастью для нас, есть инструменты, которые помогут предотвратить появление этой ситуации.
Я настоятельно рекомендую вам установить Shellcheck Анкет Это отличный инструмент для сценария сценария оболочки, который поймает и предупредит вас о куче потенциальных проблем (включая отсутствующие цитаты). Есть даже Расширение VSCODE Для этого тоже.
Вы когда -нибудь были поражены ошибками, связанными с пропущенными цитатами Bash? Дайте мне знать ниже!
Оригинал: «https://dev.to/nickjj/heres-why-you-should-quote-your-variables-in-bash-53o0»