Intereting Posts
Удаление процесса с USB-последовательного порта Есть ли разница в использовании ресурсов / потребностях между версиями Ubuntu и Debian Linux Mint (под тем же DE)? Как я могу удалить кучу древних пакетов на debian? Отключение монитора, когда он выключен / находится в режиме ожидания в настройке нескольких мониторов Черный экран после спячки Есть ли инструмент для быстрого поиска ключевых слов во многих файлах PDF? Заменить текст с помощью sed и сохранить часть исходного текста Почему я не могу запускать приложения для Android на общем Linux? Linux IO Flow – VFS для блокировки устройства Отклонено разрешение на изменение права собственности Разбор JSON на оболочке Как скомпрометировать скрипт prerm и preinst с сообщением об ошибке в пакете Debian vim cut & paste не работает в Stretch / Debian 9 Перенаправление / переадресация электронной почты с помощью fetchmail в gmail что означает: g означает это действие?

«Команда не найдена», когда функция sudo'ing от ~ / .zshrc

У меня есть функция в ~/.zshrc :

 findPort() { lsof -t -i :$1 } 

Обычным вызовом является findPort 3306 .

Я хочу запустить его с повышенными привилегиями. Но я получаю «команда не найдена».

 ➜ git 🍔 sudo findPort 3306 sudo: findPort: command not found 

Я полагаю, причина в том, что пользователь root либо работает как неинтерактивная оболочка (поэтому не относится к .zshrc), либо относится к другому .zshrc .

Я видел похожие вопросы в отношении alias , но не вопрос о пользовательских функциях. Ответы на эту проблему в отношении alias включают добавление псевдонима в ~/.zshrc :

 alias sudo='nocorrect sudo ' 

Или, возможно:

 alias sudo='sudo ' 

Я пробовал оба этих решения, и проблема все еще существует (да, я перезапустил оболочку).

Я также попытался запустить sudo chsh чтобы гарантировать, что моя корневая оболочка работает под zsh . Ни одно из этих решений не устраняет проблему «команда не найдена».

Есть ли способ запустить мои пользовательские функции в sudo?

sudo запускает команды напрямую, а не через оболочку, и даже если он запускает оболочку для запуска этой команды, это будет новый вызов оболочки, а не тот, который читает ваш ~/.zshrc (даже если он запустил интерактивную оболочку, он вероятно, прочитал бы root ~/.zshrc , а не ваш, если вы не настроили sudo чтобы не сбросить переменную $HOME ).

Здесь вам нужно будет сказать sudo о запуске новой оболочки zsh и сообщить, что zsh читает ваш ~/.zshrc перед запуском этой функции:

 sudo zsh -c '. $0; "$@"' ~/.zshrc findPort 3306 

Или:

 sudo zsh -c '. $0; findPort 3306' ~/.zshrc 

Или поделиться своими текущими функциями zsh с новым zsh вызванным sudo :

 sudo zsh -c "$(functions); findPort 3306" 

Хотя вы можете получить слишком длинную ошибку в списке аргументов, если у вас есть много определенных функций (например, при использовании системы завершения). Поэтому вы можете ограничить его функцией findPort (и любой другой функцией, на которую она опирается, если таковая имеется):

 sudo zsh -c "$(functions findPort); findPort 3306" 

Вы также можете сделать:

 sudo zsh -c "(){$functions[findPort]} 3306" 

findPort функции findPort в анонимную функцию, с которой вы передаете аргумент 3306. Или даже:

 sudo zsh -c "$functions[findPort]" findPort 3306 

(встроенный скрипт, переданный в -c является телом функции).

Вы можете использовать вспомогательную функцию, например:

 zsudo() sudo zsh -c "$functions[$1]" "$@" 

Не используй:

  sdo () {sudo zsh -c "() {$ functions [$ 1]} $ {@: 2}"} 

Поскольку аргументы sdo подверглись еще одному уровню анализа синтаксиса. Для сравнения:

 $ e() echo "$@" $ sdo e 'tname;uname' tname Linux $ zsudo e 'tname;uname' tname;uname 

Я смог сделать многократное сокращение для одного из решений, описанных в ответе Стефана Хазеласа. [Edit: Stéphane повторил исходный ярлык, который я предложил; описанный здесь код является более новой версией его создания]

Поместите это в свой ~/.zshrc :

 sdo() sudo zsh -c "$functions[$1]" "$@" 

Теперь вы можете использовать sdo как « sudo для пользовательских функций».

Чтобы подтвердить, что sdo работает: вы можете попробовать его на пользовательской функции, которая печатает ваше имя пользователя.

 ➜ birch@server ~/ 🍔 test() whoami ➜ birch@server ~/ 🍔 test birch ➜ birch@server ~/ 🍔 sdo test root 

Очень простое решение для меня заключалось в вызове интерактивной оболочки с использованием sudo -s , которая, похоже, работает с моей версией zsh (5.2) для macOS. Это дает мне функции из моего ~/.zshrc .

Из sudo manpage, на самом деле не намекающего на такое поведение:

-s, –shell
Запустите оболочку, указанную переменной окружения SHELL, если она установлена, или оболочкой, указанной в записи базы данных паролей вызывающего пользователя. Если задана команда, она передается оболочке для выполнения через опцию -c оболочки. Если команда не указана, выполняется интерактивная оболочка.

Я не уверен, что ваш вариант использования, но я подозреваю, что вы ищете интерактивное решение.