«sudo -s » запускает команду в оболочке, но подстановочные знаки или метасимволы не работают

Я бы обратил внимание на протокол TOX и связанных клиентов. Это настоящий протокол P2P, основанный на DHT (то же, что и BitTorrent). Думаю, это лучшее, что вы можете найти на сегодняшний день!

4
28.11.2018, 17:57
1 ответ

TL;DR:При выполнении команды с параметрами «--shell» или «--login» sudoэкранирует большинство символов (с использованием обратной косой черты ), включая все метасимволы. (кроме $), также включая пробелы.

Это нарушает каждый случай использования, когда вы хотите использовать оболочку, что делает sudo -sв основном непригодным для запуска команд оболочки, которые требуют для запуска в качестве команд оболочки.

Вместо sudo -sиспользуйте sudo sh -c '...'илиsudo bash -c '...'(или любое другое ожидаемое значение $SHELL. )Вместо sudo -iиспользуйте sudo bash -l -c '...'вместо (, предполагая, что оболочка root снова является bash.)


Глядя на соответствующую часть исходного кода sudo , есть этот фрагмент:

/* quote potential meta characters */
if (!isalnum((unsigned char)*src) && *src != '_' && *src != '-' && *src != '$')
    *dst++ = '\\';
*dst++ = *src;

Фрагмент перебирает каждый символ каждого аргумента. Если символ не является буквенно-цифровым, подчеркиванием, дефисом или знаком доллара, он будет экранирован обратной косой чертой.

Это означает, что подстановочные знаки *, ?, [...]и т. д. будут преобразованы в \*, \?, \[...\].

Также метасимволы, такие как ~, ;, |и т. д., будут преобразованы в \~, \;, \|.

Строка с пробелами ls /rootбудет преобразована в ls\ /root.

По какой-то причине $является исключением при экранировании, поэтому sudo -s echo '$HOME'работает, так как $не будет экранировано. (Обратите внимание, что это работает только для переменных, и даже не для формы ${HOME}, в этом случае фигурные скобки будут экранированы, что нарушит выражение.)


Последствия этого цитирования заключаются в том, что в большинстве случаев, требующих запуска оболочки от имени пользователя root, формат sudo -s <command>не дает реальных преимуществ :

.
  • Подстановочные знаки не будут расширены, так как они будут экранированы и не будут работать как подстановочные знаки.
  • Конвейеры не будут работать, так как канал |будет экранирован и тоже не будет работать.
  • Такие команды, как forи if, обычно должны использовать ;, которые будут экранированы и также не будут работать. Альтернативой может быть новая строка, но, похоже, нет способа ввести неэкранированную новую строку.

Короче говоря, форма sudo -s <command>работает только в тех случаях, когда не используются символы подстановки, конвейеры, скриптлеты и т. д. Но тогда вам обычно не нужна оболочка для запуска этих команд! В таких случаях обычно достаточно просто запустить sudo <command>без -s.

Неясно, какова мотивация реализации sudo. Возможно, чтобы поддерживать некоторую согласованность между обработкой команд при добавлении или удалении -s. Возможно также потому, что -iпредшествует -s, и в этом случае есть небольшая разница в том, как устанавливаются переменные окружения...


ВРЕМЕННОЕ РЕШЕНИЕ:Временное решение заключается в явном запуске -cоболочки.

Для этого нужно знать, что такое $SHELLдля целевого пользователя (, который может не совпадать с текущим пользователем, поэтому прямое использование $SHELLне всегда правильно.)

Например, вместо sudo -s ls -l '/root/*.cfg'используйте:

$ sudo bash -c 'ls -l /root/*.cfg'

И вместо sudo -i ls -l '~'используйте:

$ sudo bash -l -c 'ls -l ~'

(Аргумент -lbash создает оболочку «login», которая эквивалентна той, что была создана sudo -i.)

8
27.01.2020, 20:53

Теги

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