我正在尝试 sudo 位于自定义路径中的一些二进制文件。运行时该自定义路径被删除sudo
,但sudo -E
应该保留我的路径。为什么它不起作用?
$ env | egrep ^PATH PATH=/home/codemonkey/.nvm/v0.6.1/bin:/usr/local/bin:/usr/bin:/bin:/usr/local/gam es:/usr/游戏 $ sudo env | egrep ^PATH PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/X11R6/bin $ sudo -E env | egrep ^PATH PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/X11R6/bin
我知道如何解决这个问题,我只是想知道为什么sudo -E
不起作用
答案1
您可以设置exempt_group
选项来告诉 sudo 保留PATH
该组中的用户。
例如,假设你的用户在 sys 组中。将以下内容添加到你的 sudoers 文件中
Defaults exempt_group="sys"
现在你的用户将不需要PATH
为 sudo 命令重置(-E
此功能不需要重置)。
请参阅手册页更多细节。
编辑:必须指出这是一个糟糕的答案。它确实有效,但它有一个副作用,我在使用它时没有注意到。它还免除了该组中的用户必须输入密码的麻烦。似乎如果不允许这样做,您就无法获得 PATH 保存。我觉得有点愚蠢...
答案2
除了我已经输入的解决方案之外,还提出另一个解决方案。这仅适用于 bash(但可以修改为其他 shell)。
以下是一个包装器sudo
,它将查找您传递给它的命令。一旦找到命令,它就会将其更改为完全限定路径。
因此实际上sudo echo hello
变成了sudo /bin/echo hello
。
将以下内容放入您的~/.bashrc
function sudo() {
local ARGS
declare -a ARGS=()
while (( $# )); do
if [[ "${1:0:1}" == "-" ]]; then
# the argument is a dash-arg; '-s' for example
ARGS[${#ARGS[@]}]="$1"
if [[ "$1" =~ ^-[pugD]$ ]]; then
# these are the arguments that take a parameter, so skip the next
ARGS[${#ARGS[@]}]="$2"
shift
fi
shift
elif [[ "$1" == *"="* ]]; then
# the argument is a env var to set, not a command
ARGS[${#ARGS[@]}]="$1"
shift
else
# finally, a command
CMD="$(which --skip-alias --skip-functions "$1")"
[[ -z "$CMD" ]] && ARGS[${#ARGS[@]}]="$1" || ARGS[${#ARGS[@]}]="$CMD"
shift
break
fi
done
command sudo "${ARGS[@]}" "$@"
}
请注意,如果您的命令=
名称中带有 ,它将无法正确处理。这种情况极不可能发生,因此我接受了这个警告以使其保持简单。
答案3
从sudoers(5)
:
setenv Allow the user to disable the env_reset option from the
command line via the -E option. Additionally, environment
variables set via the command line are not subject to the
restrictions imposed by env_check, env_delete, or env_keep.
As such, only trusted users should be allowed to set
variables in this manner. This flag is off by default.
答案4
我会查看 sudoers 文件中的选项,因为它们控制某些 sudo 行为。
当然,我会查阅 sudoers 文件的手册页。