Вопрос или проблема
У меня есть длинная команда, и я просто хочу использовать alias
, чтобы сократить её. Но команда содержит одинарные кавычки и восклицательные знаки.
Исходная команда: ldapsearch -x -H ... -w 'abc!123'
.
Я пробовал alias search="ldapsearch -x -H ... -w \"abc!123\''
или alias search="ldapsearch -x -H ... -w 'abc!123'"
и так далее. Но ни один из них не работает для меня.
!
является проблемой только для расширения истории. Расширение истории происходит только в интерактивных оболочках (если не отключено пользователем, как я это делаю) и в bash (как в zsh, но в отличие от csh, где обе функции – расширение истории и алиасы – происходят) выполняется до расширения алиасов и не выполняется снова после их расширения, так что нормально оставлять !
без кавычек в значении алиаса:
alias search="ldapsearch -x -H ... -w abc!123"
Такая команда alias
будет нормально работать даже в интерактивной оболочке, потому что в bash (как и в zsh, но в отличие от csh) одинарные кавычки предотвращают срабатывание !
, ^
… в расширении истории.
Чтобы заключить !
в одинарные кавычки в значении алиаса, вам придется делать такие вещи:
alias search="ldapsearch -x -H ... -w "\'abc\!123\'
alias search=$'ldapsearch -x -H ... -w \'abc!123\''
alias search="ldapsearch -x -H ... -w "\''abc!123'\'
alias search="ldapsearch -x -H ... -w 'abc"\!"123'"
alias search=ldapsearch\ -x\ -H\ ...\ -w\ \'abc\!123\'
То есть убедитесь, что !
заключен либо в '...'
, $'...'
, либо \
(вне любых других форм кавычек), а не в двойные кавычки.
Использование "abc!123"
работает в неинтерактивных оболочках, но не в интерактивных. "abc\!123"
работает в интерактивных, но не в неинтерактивных.
Вместо алиаса вы можете использовать функцию (alias
стали популярными, потому что они появились в csh (примерно в 1979 году) до того, как Bourne shell добавил функции (примерно в 1983), но они на самом деле являются изъяном в оболочках в наши дни).
search() { ldapsearch -x -H ... -w 'abc!123' "$@"; }
Или даже возможно лучше, сделайте это:
#! /bin/sh -
exec ldapsearch -x -H ... -w 'abc!123' "$@"
Тогда вы сможете вызывать её откуда угодно, а не только из ваших интерактивных оболочек.
Теперь передача пароля в командной строке является очень плохой практикой, так как аргументы командной строки являются публичной информацией на большинстве систем. Они появляются в выводе ps -f
, они сохраняются в историях оболочки или в журналах аудита.
Вместо этого вы должны использовать что-то такое:
search() {
ldapsearch -x -H ... -y ~/.config/secrets/ldap/host.password "$@"
}
С ~/.config/secrets/ldap/host.password
, доступным только для вас и содержащим пароль, или:
search() {
ldapsearch -x -H ... -y <(
command-that-retrieves-the-password from your password manager
) "$@"
}
Хранение пароля в вашем алиасе может иметь последствия для безопасности. Я бы посоветовал использовать функцию и параметризовать пароль следующим образом. Например
ldap_search() {
локальный password="$1"
ldapsearch -x -H ... -w "$password"
}
Затем вы должны будете загрузить свой файл bashrc
source ~/.bashrc
Затем используйте функцию следующим образом:
ldap_search "<Вставьте здесь ваш пароль>"
Подсказка: Вы также можете использовать read -s -p 'Введите пароль: ' password
, чтобы пароль не отображался в вашем файле истории.
Расширение истории актуально только при использовании bash интерактивно.
Переход на одинарные кавычки не всегда целесообразен. Экранирование восклицательных знаков без использования одинарных кавычек является странным и добавляет отлично к цитированию в цитировании в bash:
Вы можете использовать !”” вместо !, потому что “” внутри двойных кавычек является пустым, а !” не является расширением истории с версии bash 4.3.
$>A=”git commit -m “Разочаровывающее !”” Снаружи темно в $(date +%B)”; make” ; echo $A;
git commit -m “Разочаровывающее ! Снаружи темно в Ноябре”; make
bash -c $A
или char, не следуемый за динамической строкой b:
$>b=’b’ ; echo “abac” | grep -P “.(?!””$b)”
abac (#отрицательный просмотр вперед)
Интерактивная настройка алиаса:
$> alias ldapsearch=”ldapsearch -x -H … -w ‘abc!””123′”
.. с дополнительным пробелом в начале, чтобы по крайней мере предотвратить запись пароля в историю bash. Пожалуйста, смотрите другие ответы относительно паролей.
Ответ или решение
Для сокрытия как одинарных кавычек, так и восклицательных знаков в bash существует несколько подходов, каждый из которых зависит от контекста использования (интерактивные или неинтерактивные оболочки) и ваших конкретных требований. В данном ответе мы рассмотрим несколько методов, включая использование alias
, функции, а также внимание к безопасности при хранении паролей.
Эскейпинг одинарных кавычек и восклицательных знаков в alias
Вы дадите команду ldapsearch
, содержащую восклицательный знак в пароле в одинарных кавычках:
ldapsearch -x -H ... -w 'abc!123'
Для создания alias
вы можете использовать несколько подходов, учитывая, что восклицательные знаки в интерактивной оболочке выполняют расширение истории. Ниже приведены различные варианты, как это сделать:
-
Прямой способ:
Важно помнить, что восклицательный знак не будет вызывать расширение истории, если он находится в одинарных кавычках. Таким образом, следующий вариант будет работать в интерактивных сеансах:
alias search="ldapsearch -x -H ... -w 'abc!123'"
-
Экранирование:
Если вы хотите использовать восклицательный знак с точной экранировкой, вы можете использовать следующее:
alias search="ldapsearch -x -H ... -w 'abc\!123'"
В этом случае восклицательный знак будет интерпретироваться как обычный символ.
-
Использование
$''
:Вы также можете воспользоваться синтаксисом ANSI-C, который позволяет вам использовать специальные символы:
alias search=$'ldapsearch -x -H ... -w \'abc!123\''
-
Совмещение кавычек:
Можно комбинировать кавычки разного типа:
alias search="ldapsearch -x -H ... -w 'abc!123'"
Функции вместо alias
Использование функций вместо alias
более гибкое и безопасное решение. Например, вы можете определить функцию, которая позволяет задавать пароль в качестве параметра:
search() {
ldapsearch -x -H ... -w "$1"
}
При этом вы можете вызвать функцию следующим образом:
search 'abc!123'
Это также поможет избежать проблем с безопасностью, связанных с тем, что пароль может отображаться в истории команд.
Безопасное управление паролями
Передача паролей в командной строке может привести к утечке данных, так как они могут быть видны в истории команд или в выводе процесса ps
. Вместо этого рассмотрите возможность хранения пароля в файле и его чтения в процессе выполнения команды. Например:
search() {
ldapsearch -x -H ... -y ~/.config/secrets/ldap/host.password "$@"
}
Вы можете создать файл ~/.config/secrets/ldap/host.password
, который будет доступен только вам, и хранить в нем пароль.
Заключение
Экранирование одинарных кавычек и восклицательных знаков в bash требует аккуратного подхода, особенно если вам нужно взаимодействовать с инструментами, которые используют эти символы. Сложные комбинации кавычек и функции предлагают более безопасные и управляемые решения. Обязательно учитывайте безопасность ваших данных, избегая передачи паролей в явном виде в командной строке.