Псевдонимы недоступны при использовании sudo


161

Сегодня я играл с псевдонимами и заметил, что псевдонимы, по-видимому, недоступны при использовании sudo:

danny@kaon:~$ alias
alias egrep='egrep --color=auto'
alias fgrep='fgrep --color=auto'
alias grep='grep --color=auto'
alias l='ls -CF'
alias la='ls -A'
alias ll='ls -alF'
alias ls='ls --color=auto'

danny@kaon:~$ ll -d /
drwxr-xr-x 23 root root 4096 2011-01-06 20:29 //

danny@kaon:~$ sudo -i
root@kaon:~# ll -d /
drwxr-xr-x 23 root root 4096 2011-01-06 20:29 //
root@kaon:~# exit
logout

danny@kaon:~$ sudo ll -d /
sudo: ll: command not found

Есть ли причина, по которой вы не можете использовать псевдонимы во время использования sudo?


Вы объявили этот псевдоним в .bashrc в / root /
Лучано Фаччинелли

2
@LucianoFacchinelli: /root/.bashrcне читается при запуске команды через sudo.
Flimm


@Flimm: Как насчет sudo -i?
Evi1M4chine

Ответы:


251

Добавьте следующую строку в ваш ~/.bashrc:

alias sudo='sudo '

Из руководства по bash :

Псевдонимы позволяют заменить строку словом, если оно используется в качестве первого слова простой команды. Оболочка поддерживает список псевдонимов, которые можно устанавливать и удалять с помощью встроенных команд alias и unalias.

Первое слово каждой простой команды, если оно не заключено в кавычки, проверяется на наличие псевдонима . Если это так, это слово заменяется текстом псевдонима. Символы '/', '$', '`', '=' и любые метасимволы оболочки или символы цитирования, перечисленные выше, могут не отображаться в псевдониме. Текст замены может содержать любые допустимые входные данные оболочки, включая метасимволы оболочки. Первое слово замещающего текста проверяется на псевдонимы, но слово, идентичное расширяемому псевдониму, не раскрывается во второй раз. Это означает, что, например, псевдоним ls можно присвоить «ls -F», и Bash не пытается рекурсивно развернуть текст замены. Если последний символ значения псевдонима является пробелом или символом табуляции, то следующее слово команды, следующее за псевдонимом, также проверяется на расширение псевдонима .

(Акцент мой).
Bash проверяет только первое слово команды на наличие псевдонима, любые слова после этого не проверяются. Это означает, что в такой команде sudo llтолько sudobash проверяет псевдоним только первое слово ( ) и llигнорируется. Мы можем сказать bash проверить следующее слово после псевдонима (то есть sudo), добавив пробел в конец значения псевдонима.


18
Довольно хорошее решение.
ulidtko

Таким образом, в основном проблема сводится к тому, что sudo просто запрограммирован таким образом, что он не проверяет псевдоним, поэтому ll не найден?
kemra102

2
Чтение документации, очевидно, приносит большую пользу :-)
biocyberman

4
Это сломается, если я использую флаг sudo, например sudo -H ll?
Марк Э. Хаас

1
@ mehaase Да, я пытался, и это ломается.
user31389

5

Я написал функцию Bash для этого, что тени sudo.

Он проверяет, есть ли у меня псевдоним для данной команды, и в этом случае запускает команду с псевдонимом вместо буквальной sudo.

Вот моя функция в качестве одной строки:

sudo() { if alias "$1" &> /dev/null ; then $(type "$1" | sed -E 's/^.*`(.*).$/\1/') "${@:2}" ; else command sudo $@ ; fi }

Или красиво отформатирован:

sudo() { 
    if alias "$1" &> /dev/null ; then 
        $(type "$1" | sed -E 's/^.*`(.*).$/\1/') "${@:2}"
    else 
        command sudo "$@"
    fi 
}

Вы можете добавить его к своему .bashrcфайлу, не забывайте получать его или перезапустить сеанс терминала, чтобы применить изменения.


Было бы замечательно, если бы это также сработало для sudo -H ll.
Л

3

Псевдонимы зависят от пользователя - их необходимо определить в /root/.bashrc


3
Они уже находятся в /root/.bashrc, так что это не проблема
kemra102

1
Ответ на этот вопрос будет единственно правильным для ситуации , когда вы запускаете оболочку себя как корень, так как с sudo -sили sudo -iтолько если запустить сам по себе , чтобы получить корневую оболочку, а не с sudo -s command...или sudo -i command...формами) или sudo bashили sudo su, или в ситуации , когда вы Я включил root-логины и таким образом получил root-оболочку. Когда пользователь без полномочий root запускается sudo command...из своей собственной оболочки, расширение псевдонима выполняется его собственной оболочкой без полномочий root. sudoсам по себе псевдонимы не расширяет, поэтому применительно к ситуации, описанной в вопросе , этот ответ неверен.
Элия ​​Каган

3

@Alvins ответ самый короткий. Без сомнения! :-)

Однако я думал о командной строке решения для выполнения не сглаженные команд в Судо , где нет необходимости заново sudoс aliasкомандой.

Вот мое предложение для тех, кого это может заинтересовать:

Решение

type -a <YOUR COMMAND HERE> | grep -o -P "(?<=\`).*(?=')" | xargs sudo

пример

В случае llкоманды

type -a ll | grep -o -P "(?<=\`).*(?=')" | xargs sudo

объяснение

если у вас есть псевдоним (например, :), llкоманда type -aвозвращает псевдоним:

$type -a ll
ll is aliased to `ls -l'

в этом случае grepвы выбираете текст между акцентом `и апострофом 'ls -l

И xargsвыполняет выделенный текст в ls -lкачестве параметра sudo.

Да, немного дольше, но полностью чистый ;-) Не нужно переопределять sudoпсевдоним.


3
Может быть проще, если вы использовали aliasвстроенный, так как его вывод чище. alias llвыходы alias ll='ls -ahlF'.
Муру

Вот версия включения предложения @ Мура в: alias ll | sed "s/.*'\(.*\)'.*/\1/g" | xargs sudo.
ACK_stoverflow

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

1

У меня есть еще одно приятное решение, которое добавляет немного доверия:

Используйте завершение bash для автоматической замены слов позади sudoих псевдонимами при нажатии клавиши Tab.

Сохраните это как /etc/bash_completion.d/sudo-alias.bashcomp, и оно должно автоматически загружаться при запуске интерактивной оболочки:

_comp_sudo_alias() { from="$2"; COMPREPLY=()
  if [[ $COMP_CWORD == 1 ]]; then
    COMPREPLY=( "$( alias -p | grep "^ *alias $from=" | sed -r "s/^ *alias [^=]+='(.*)'$/\1/" )" )
    return 0
  fi
  return 1
}
complete -o bashdefault -o default -F _comp_sudo_alias sudo

Затем войдите в новый терминал, и вам будет хорошо идти.


Есть способ получить список псевдонимов, специально предназначенных для заполнения:compgen -a
muru

@ Муру: Спасибо, но в этом случае мне нужны значения, а не ключи. Так что псевдоним, который был введен, будет заменен. Вы вводите псевдоним (как в sudo ll), нажимаете [TAB ↹], и скрипт находит llв списке назначений псевдонимов, вырезает то, что ему назначено, и вставляет его. (Таким образом, вы получите, например sudo ls -lahvF --color=auto --time-style=long-iso.)
Evi1M4chine

0

У меня есть другое решение, в котором вам не нужно добавлять sudoв качестве псевдонима. Я использую Linux Mint 17.3, но он должен быть очень похож на Ubuntu.

Когда вы являетесь пользователем root, он .profileзапускается из своего домашнего каталога. Если вы не знаете, что такое домашний каталог в корневом каталоге, вы можете проверить с помощью:

sudo su
echo $HOME

Как видите, дом rootесть /root/. Проверьте его содержимое:

cd $HOME
ls -al

Там должен быть .profileфайл. Откройте файл и добавьте следующие строки:

if [ "$BASH" ]; then
    if [ -f ~/.bash_aliases];then
        . ~/.bash_aliases 
    fi
fi

По сути, этот bash-скрипт проверяет файл с именем .bash_aliases. Если файлы присутствуют, он выполняет файл.

Сохраните .profileфайл и создайте свои псевдонимы в .bash_aliases. Если у вас уже есть файл псевдонимов, скопируйте его в это место

Перезапустите терминал, и вы готовы!


0

Ответ с лучшим ответом - отличный. Однако, если вы sudo -iнаберете и повысите уровень приглашения sudo ( #), у вас не будет псевдонимов, которые вы хотели бы использовать.

Чтобы использовать ваши псевдонимы (и все остальное) в #командной строке, используйте:

sudo cp "$PWD"/.bashrc /root/.bashrc

Где «$ PWD» автоматически раскрывается в «/ home / YOUR_USER_NAME»


0

@ WinEunuuchs2Unix: $PWDрасширяется до «текущего рабочего каталога». Я думаю, что вы хотите $HOME.

Кроме того, в большинстве случаев, вероятно, лучше иметь отдельный корневой файл .bashrc. Фактически, я бы сделал его настоящим файлом /root, мягкой ссылкой на него в домашнем каталоге пользователя (например, .bashrc_root) и получил его из .bashrcфайла пользователя . Если через некоторое время эта учетная запись привилегированного пользователя больше не будет присутствовать, корневой .bashrcфайл все еще будет доступен для других пользователей.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.