如何让 sudo 命令使用 /root/.bashrc 中的设置

如何让 sudo 命令使用 /root/.bashrc 中的设置

我定制了.bashrc一些别名,具体来说ll还有export LS_OPTIONS='--color=auto'

不幸的是,这在与 一起使用时不起作用sudo,所以我也修改了/root/.bashrc,但这似乎没有什么区别。

sudo env显示HOME=/rootSHELL=/bin/bash

如何获取sudo使用其中设置的命令/root/.bashrc

我知道只有在bash交互执行时才会发生这种情况,因此我愿意接受有关如何自定义的任何其他建议。

答案1

sudo运行可执行文件,而不是 shell 命令。所以它不知道别名。如果您运行sudo ls,就像sudo /bin/ls,它不会使用ls您可能拥有的任何别名。

您可以sudo ls通过将以下内容放入您的 中来扩展别名.bashrc

alias sudo='sudo '

请注意尾随空格 - 它告诉 shell 继续使用 后面的单词进行别名扩展sudo。请注意,在 sudo 之后扩展别名可能并不总是一个好主意,这取决于您拥有什么类型的别名。

此外,sudo 会从环境中删除大多数变量。这不会影响诸如 之类的别名alias ls='ls $LS_OPTIONS',因为这是 shell 在扩展命令时使用的 shell 变量(从 导出它.bashrc没有任何作用)。但它会影响命令使用的变量,例如LS_COLORS.您可以通过编辑 sudo 的配置来配置 sudo 以保留某些环境变量:运行visudo并添加以下行

Defaults env_keep += "LS_COLORS"

通过这些设置,sudo ll将给出您习惯的颜色。

或者,您可以使用 运行 root shell sudo -s。该 shell 将加载其配置文件(~/.bashrc对于 bash)。根据 sudo 的配置方式,这可能会保留HOME设置为您的主目录,或将其更改为/root.您可以使用 ; 强制将主目录设置为根目录sudo -Hs。相反,要保留原始主目录,请运行sudo env HOME="$HOME" bash.

答案2

感谢那些回答的人,促使我man sudo更仔细地阅读。

sudo -s 如果未指定命令,则执行交互式 shell。

这个交互式 shell 使用/root/.bashrc并因此包含我的自定义。

它确实需要单独输入命令,但这是可以的。

答案3

背景

我一直觉得这个问题是一个XY问题。标题暗示他们想要从中得到任何东西,/root/.bashrc但真正的问题是该文件中的别名 - 人们普遍认为这是不可能的 -为什么我的 Bash 脚本无法识别别名?

基本上按照设计,您的别名不会在sudo其他地方被拾取,因为它们不可移植,这也是我对它们的看法。

用户环境中的任何内容都不应该由脚本和可能在给定机器上运行的任何软件来假定。但我意识到,在某些情况下,给定用户帐户中可能存在一些别名$HOME/.bashrc,其他人可能希望在交互场景中利用这些别名。

为此,您可以简单地告诉 Bash 解释器将其在登录过程中找到的任何别名展开到您使用 时遇到的正常 shell 行为之外sudo

例子

设置

为了进行设置,我已将以下别名、环境变量和函数添加到我的 root 用户/root/.bashrc/root/.bash_profile文件中。

$ grep smurf ~/.bashrc
alias brc_smurf='echo "ran alias from /root/.bashrc"'
export brc_smurf_env='var from /root/.bashrc'
bpf_smurf_func() { echo 'ran func from /root/.bash_profile'; }

$ grep smurf ~/.bash_profile
alias bpf_smurf='echo "ran alias from /root/.bash_profile"'
export bpf_smurf_env='var from /root/.bash_profile'
brc_smurf_func() { echo 'ran func from /root/.bashrc'; }

如果不做任何事情,这些都不起作用(毫不奇怪):

$ sudo brc_smurf
sudo: brc_smurf: command not found

$ sudo bpf_smurf
sudo: bpf_smurf: command not found

我们看到该alias命令在运行时没有显示别名sudo

$ sudo alias
$

此行为暗示您不应期望可以访问别名。但我们继续...

步骤#1 - 别名可见

如果我们运行,bash -ci我们可以引导 Bash 至少读取我们的$HOME/.bashrc

$ sudo bash -ci 'alias' | grep smurf
alias brc_smurf='echo "ran alias from /root/.bashrc"'

很酷,也许我们可以运行它?

$ sudo bash -ci 'alias; brc_smurf'
bash: alias; brc_smurf: No such file or directory

第2步 -shopt -s expand_aliases

没有。同样,这是设计使然,我们正在做一些我们不应该做的事情,因此我们必须禁用许多“安全措施”。另一个“安全”是Bash。

$ sudo bash -ci 'shopt -s expand_aliases; alias; brc_smurf'
alias brc_smurf='echo "ran alias from /root/.bashrc"'
alias cp='cp -i'
alias egrep='egrep --color=auto'
alias fgrep='fgrep --color=auto'
alias grep='grep --color=auto'
alias l.='ls -d .* --color=auto'
alias ll='ls -l --color=auto'
alias ls='ls --color=auto'
alias mv='mv -i'
alias rm='rm -i'
alias which='alias | /usr/bin/which --tty-only --read-alias --show-dot --show-tilde'
ran alias from /root/.bashrc

在这里我们可以看到来自的消息/root/.bashrc,我们已经成功执行了 root 用户的别名brc_smurf

步骤#3 - 环境变量怎么样?

如果您使用上面显示的方法,这些现在应该也可以工作。

$ sudo bash -ci 'shopt -s expand_aliases; brc_smurf; echo $brc_smurf_env'
ran alias from /root/.bashrc
var from /root/.bashrc

步骤#4 - 函数怎么样?

这些也按预期工作:

$ sudo bash -ci 'shopt -s expand_aliases; brc_smurf; echo $brc_smurf_env;brc_smurf_func'
ran alias from /root/.bashrc
var from /root/.bashrc
ran func from /root/.bashrc

太长了;

您可以执行此操作来访问环境变量+别名/root/.bashrc

$ sudo bash -ci 'shopt -s expand_aliases; <cmds>'

外卖

此方法启用 的内容/root/.bashrc,但不拾取 的内容/root/.bash_profile

参考

答案4

TL;DR:您可以用来sudo -i运行功能定义/root/.bashrc(但不是别名)并且还可以访问从该文件导出的变量:

须藤-我 命令参数

不过,别名在那里不起作用,但如果您想让它们可用于sudo -i.

请继续阅读以获取完整的分析和更多详细信息。


这里有一些问题,一些是 sudo 如何工作的,一些是 bash 本身如何工作的......

默认情况下,sudo只会查找命令并绕过 shell,因此仅sudo llll.$PATH因此,为了使用别名(或函数),您需要确保 shell 作为进程的一部分被调用。

一种方法是运行类似sudo shor的东西sudo bash,尽管现代sudo(我正在 sudo 1.8.19p1 上测试它)有选项-s-i用于此目的。

所以一次尝试会是这样的sudo -s ll(这相当于sudo bash -c 'll',假设你$SHELL是 Bash,这似乎是基于rcfile你提到的情况。)但这也不起作用,因为它以非交互式方式启动 shell,非登录模式,不读取任何启动文件。它本质上与编写 shell 脚本并用于#!/bin/bash运行它相同。您~/.bashrc将无法从该脚本访问您的别名(和函数) ...

接下来是-i创建登录 shell 的选项。这更有希望,因为它将要读取你的启动文件!然而,sudo -i ll(相当于sudo bash -l -c 'll') 仍然不起作用。那么这怎么可能呢?做过阅读别名的定义ll

好吧,这里的下一个解释是,默认情况下,bash 不会扩展别名,除非 shell 是交互式的……这个由sudo -i(或bash -l) 启动的 shell 是一个登录shell,但仍然无法交互。

所以下一步是获得交互的壳,然后作品

sudo bash -i -c 'll'

(同时拥有登录交互的也很好,当然bash -l -i -c ...会起作用。)

另一种选择是继续使用登录shell(非交互式)但明确要求它扩展别名,所以这也可以工作:

sudo bash -l -O expand_aliases -c 'll'

(bash 的情况交互的不需要登录shell,因为这足以读取初始化文件,但这个需要-l读取它们。)

这些是相当长的命令行...而且它们还要求您引用整个 shell 命令,因此如果您使用参数调用别名,则必须将所有这些都转换为字符串...所以它有点像使用起来很笨拙...

请注意,之前我谈论的是别名和功能……这是故意的,因为这里的功能实际上更方便。您不需要任何特殊的东西(例如具有交互式 shell,或设置特定选项)来在 shell 上执行函数,只要您获取它们的定义即可。

所以如果你定义ll功能您可以直接通过 sudo 的-i快捷方式使用它,而不是别名:

sudo -i ll

如果您有更长的命令行和参数,您也可以直接在此处传递它们:

sudo -i ll -C -R /etc

(相比于sudo bash -i -c 'll -C -R /etc'。)

函数也更加灵活,通常更容易维护...通常很容易将别名转换为函数,唯一的警告是始终在"$@"您期望使用额外参数的地方使用(通常在别名。)

例如,这个别名:

alias ll='ls $LS_OPTIONS -l'

可以改成这个函数:

ll () {
    ls $LS_OPTIONS -l "$@"
}

对于大多数目的来说,它们是等效的。而且,如前所述,该函数应该可以直接从 访问sudo -i,因此这是一个额外的好处。

我希望您发现这个答案和解释有帮助!

相关内容