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


9

我已经定制.bashrc了一些别名,特别是llexport LS_OPTIONS='--color=auto'

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

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

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

我知道只有在bash以交互方式执行时才会发生这种情况,因此我对其他有关自定义的建议持开放态度。


@ daniel- gelling-我一直觉得这个Q是XY问题-meta.stackexchange.com/questions/66377/what-is-the-xy-problem。标题暗示他们想要什么,/root/.bashrc但实际上问号后面的内容是该文件的别名-这是不可能的-unix.stackexchange.com/questions/1496/…
slm

@slm我后是增加一个方法的.bashrc -正如我在我个人的.bashrc文件以及为根.bashrc文件为“禁用”的已经做-r了选择crontabcrontab () { [[ $@ =~ -[iel]*r ]] && echo '"r" not allowed' || command crontab "$@" ;}。当以任一用户身份登录时,此方法有效,但是当我执行sudo crontab -r该操作时,它仍然执行。
Daniel Gelling

@DanielGelling-看看我的答案是否对您有用。
slm

Answers:


6

sudo运行可执行文件,而不是shell命令。因此它不了解别名。如果运行sudo ls,则类似于sudo /bin/ls,它不会使用ls您可能拥有的任何别名。

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

alias sudo='sudo '

请注意尾随空格-告诉外壳程序继续使用别名after扩展别名sudo。请注意,在sudo之后扩展别名并非总是一个好主意,这取决于您拥有哪种别名。

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

Defaults env_keep += "LS_COLORS"

使用这些设置,sudo ll将提供您习惯的颜色。

或者,您可以使用运行根shell sudo -s。该外壳程序将加载其配置文件(~/.bashrc用于bash)。根据sudo的配置方式,此HOME设置可能会保留在您的主目录中,或更改为/root。您可以通过以下命令强制将主目录设置为根目录sudo -Hs:相反,要保留原始主目录,请运行sudo env HOME="$HOME" bash


3

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

sudo -s 如果未指定命令,则执行交互式外壳程序。

该交互式外壳使用/root/.bashrc并因此包括我的自定义设置。

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


2

背景

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

基本上是设计使然,您的别名不会被sudo携带,因为它们不便于携带,这也是我对它们的看法。

脚本和任何可能在给定盒子上运行的软件都不应假定用户环境中存在任何内容。但是我意识到,在某些情况下,给定用户帐户中可能会有一些别名,而在$HOME/.bashrc其他情况下,其他人可能希望利用这些别名。

为此,您可以简单地告诉Bash解释器,以扩展它在登录过程中发现的别名,而不是使用时遇到的常规shell行为sudo

设定

为了进行设置,我在根用户/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用户的alias 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

TLDR;

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

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

外卖

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

参考文献


是的,尽管它们之间有一些细微的差别,但我们不在这里详细介绍;-)。无论如何,您能帮我解决在问题注释中提到的情况吗.bashrc?专门-r从中删除选项crontab
Daniel Gelling

好的,但这意味着我必须运行:sudo bash -ci 'alias; shopt -s expand_aliases; echo $brc_smurf_env'而不是简单的sudo echo $brc_smurf_env
Daniel Gelling

您可以删除alias,只是为了显示它们,您需要做sudo bash -ci 'shopt -s expand_aliases; <cmds>'
slm

只是为了编辑我的crontab来输入大量的内容。让我为其创建一个别名:-P
Daniel Gelling,

@DanielGelling-是的,欢迎您到贝壳大肠尽情玩乐。
slm

0

在/ etc / sudoers文件中有很多设置,或者为运行sudo命令设置环境(例如,确保PATH仅具有受信任的位置),但具体取决于您希望从中获得什么如果涉及在shell中运行实际命令以设置环境,则可能无法执行您要执行的操作。特别地,Sudoing不会为您提供root登录shell,因此不会为您设置常规配置文件。


0

假设我们将/root/.bashrc编辑为:

$ sudo su -
Password: ******
# cat ~/.bashrc

echo "root bashrc file was read"
PATH=~/bin:$PATH
echo "$PATH"
export USERVAR=set
echo "$USERVAR"

umask 022
alias ll='ls $LS_OPTIONS -l'
alias l='ls $LS_OPTIONS -lA'

让我们注销并重新登录以使bash读取文件:

# exit
$ sudo su -
root bashrc file was read
/root/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
set
root@here:~# alias l
alias l='ls $LS_OPTIONS -lA'
root@here:~# 

如您所见,已读取文件,更改了PATH并设置了别名。所有功能均可按您的要求进行。

但是,sudo仍然无法如您所愿。

root@here:~# exit
$ sudo env | grep USERVAR              # no output 
$ sudo env | grep PATH
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin

PATH尚未更改。也许有一些方法可以更改sudoers中的路径,但是我强烈建议您避免这样做。而且,无论如何,仅通过更改PATH仍不会应用别名,函数和其他一些更改。需要提供文件。对每个脚本或命令执行此操作将要求计算机执行更多工作,而没有任何实际好处。脚本不使用别名(脚本内部没有实际用途)。

因此,只需登录,.bashrc文件将被自动加载并开始工作。

您可以这样开始bash:

$ sudo bash
root bashrc file was read
/root/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
set
root@mail:/home/isaac/me/temp/clocks-master#

但是,正如您在上面看到的那样,pwd(工作目录)没有更改,并且,如果您进行了更多检查,则其他设置也没有更改。这就是使用正确命令的原因:

$ sudo su -

如果该命令太长而无法键入,请在将使用该命令的用户(不是root)中创建别名或函数,例如:

$ alias mysu='sudo su -'
$ mysu
# 

0

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

sudo -i  命令参数

别名虽然在那里不起作用,但是如果您想使它们可用于则可以轻松地将它们转换为函数sudo -i

继续阅读以进行全面分析和更多详细信息。


这里有一些问题,一些是关于sudo的工作方式,还有一些是bash本身的工作方式...

默认情况下,sudo将仅查找命令并绕过外壳程序,因此sudo ll仅当ll的目录之一中存在可执行文件时,简单运行才有效$PATH。因此,为了使用别名(或函数),您需要确保在过程中调用外壳程序。

一种方法是运行类似sudo sh或的东西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创建登录外壳程序的选项。这是更有前途,因为它读取你的启动文件!但是,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 ...。)

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

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

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

这些是相当长的命令行...而且它们还要求您引用整个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,这是一个额外的好处。

我希望这个答案和解释对您有所帮助!


DV-我觉得这种情况不会比现在已经改善。
slm

1
@slm我认为我的答案是增加一些,因为没有以前的答复中提到的形式sudo -i command arguments,以能够运行功能,/root/.bashrc和具有出口变量可用。但是我看到我的答案可能太长了,而且该信息多少有些隐隐在其中...因此,我添加了一个TL; DR来对其进行总结(同时仍保留调查的技术细节。)请再看一下。
filbranden
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.