Опция NOPASSWD, не относящаяся к второй команде

Это несколько раз уже подошло на этом сайте — посмотрите Понимание IFS и связанные вопросы. В этом ответе я собираюсь суммировать то, что может пойти не так, как надо и как избежать его; посмотрите связанные потоки для деталей.

read line выполняет следующие действия:

  1. Читайте из стандартного входа до первого байта, который является или новой строкой или пустым указателем, и помещает данные в названную переменную line.
  2. Снимите изоляцию с любой обратной косой черты, которая не является в конце строки. Двойная обратная косая черта \\ становится единственной обратной косой чертой. Другими словами, обратная косая черта заключает следующий символ в кавычки, пока это не новая строка.
  3. Если read остановленный в новой строке и символе в конце строки a \, разделите последовательность новой строки обратной косой черты и продолжите читать, добавив к переменной line. Повторитесь до первого из: новая строка, которой не предшествует обратная косая черта; пустой байт; конец входа.
  4. Разделите самый длинный суффикс line это сделано из символов в $IFS. По умолчанию, IFS содержит вкладку, пространство и новую строку, таким образом, это разделяет пробел ASCII от конца значения line.
  5. Разделите самый длинный префикс line это сделано из пробельных символов в $IFS.

Например, если вход

 : hello\
world: :
wibble

затем read line результаты в line содержа : helloworld: : (никакое начальное пространство) со значением по умолчанию IFS. Если IFS был изменен на : (просто двоеточие) затем read line результаты в  : helloworld: (с пространством вначале и в конце). Если IFS содержит обоих : и пространство затем результат : helloworld (никакой начальный или конечный пробел).

Избегать влияния IFS, установите его на пустое значение (обратите внимание, что это отличается от сбрасывания его). Можно установить его только для read команда путем записи IFS= read (см., Почему, 'в то время как IFS = читала' используемый так часто вместо 'IFS =; в то время как считано..'?).

Для предотвращения обработки обратной косой черты передайте -r опция к read.

Если оболочка не является zsh, если существует пустой байт во входе, то последующие символы потеряны. Оболочки не разработаны для чтения двоичных данных.

Таким образом идиома для чтения одной строки за один раз:

while IFS= read -r line; do
  … # process "$line"
end

Когда Вы используете переменную line, удостоверьтесь, что всегда поместили двойные кавычки вокруг подстановок переменных: "$line". Без двойных кавычек оболочка сначала разворачивает значение переменной, затем это повреждает то значение в отдельные слова везде, откуда это содержит символы IFS, и каждое слово интерпретируется как подстановочный шаблон и замены списком соответствия файлам (при отсутствии файлов соответствия, шаблон оставляют, как). Так echo 'a* b*' | IFS= read -r line; echo $line расширяется до списка файлов в начале текущего каталога a или b; для получения неизменного входа использовать echo 'a* b*' | IFS= read -r line; echo "$line".

Обратите внимание также что echo команда иногда изменяет строку, которую она печатает. Точный путь зависит от оболочки. Некоторые оболочки обрабатывают Escape обратной косой черты, и некоторые оболочки распознают опции. Используя echo производить строку дословно только, несомненно, будет работать, Вы знаете, что строка не содержит обратной косой черты и не запускается с тире (-). Надежный и портативный способ распечатать строку, как,

printf '%s\n' "$line"

Это печатает новую строку после строки, как echo. Можно опустить новую строку путем исключения \n в команде выше.

1
16.02.2014, 18:21
2 ответа

Ну, да, это уверенный было что-то очевидное относительно того, почему это не работало. Когда я исправил ошибку, что я должен был добавить/bin/bash-c для разрешения использования-i, я не изменил полный путь для команды, /usr/bin/reprepro, к тому, что я был на самом деле передающим в, reprepro. Изменение его для использования полного пути как ниже, или аналогично изменение правила только включать команду, хорошо работает.

lambda@host:~$ sudo -K
lambda@host:~$ sudo -u repomgr -i /usr/bin/reprepro -b /var/packages/devel pull

Это все еще оставляет загадку почему NOPASSWD не обнаруживается в sudo -l запрос, но я решил фактическую проблему.

0
27.01.2020, 23:53

У меня есть Sudo-версия 1.8.7, и проблема не появляется здесь:

sudo -l
User hl may run the following commands on this host:
    (ALL) ALL
    (nobody) NOPASSWD: /bin/bash -c /home/repomgr/preset-passphrase.sh
    (nobody) NOPASSWD: /bin/bash -c /usr/bin/reprepro -b /var/packages/devel pull

Настолько, возможно, который просто ошибка, которая была уже исправлена. Возможно, можно работать вокруг этого двумя отдельными операторами:

%qa     ALL = (repomgr) NOPASSWD: REPO_LOAD_PASSPHRASE
%qa     ALL = (repomgr) NOPASSWD: REPO_PULL
1
27.01.2020, 23:53

Теги

Похожие вопросы