可执行文件无需 sudo 即可运行,但使用 sudo 则无法运行

可执行文件无需 sudo 即可运行,但使用 sudo 则无法运行

我在系统中的以下位置安装了 xampp /opt/lampp。之后,我使用以下方法将 php 位置添加到我的路径变量中:

export PATH=$PATH:/opt/lampp/bin

因此,当我php -v使用终端运行时,我得到了预期的输出。

PHP 5.6.8 (cli) (built: Apr 20 2015 18:37:47) 
Copyright (c) 1997-2015 The PHP Group
Zend Engine v2.6.0, Copyright (c) 1998-2015 Zend Technologies

但是当我跑步时sudo php -v我得到了这个:

sudo: php: command not found

我不知道为什么会发生这种情况。我在将其添加到路径变量时做错了什么吗?

编辑:

这个问题不是重复的使用“sudo”运行时的环境变量,因为在那个问题中 zetah 询问如何将任意变量传递给 python 命令。他们可以使用 执行pythonsudo但我无法使用php执行sudo

下列的这个答案sudo,我使用以下命令添加了 PATH :

sudo PATH=$PATH:/opt/lampp/bin php -v

但我得到的输出和以前一样:

sudo: php: command not found

下列的这个答案,我将其添加-Esudo,但得到相同的结果:

$ sudo -E php -v
sudo: php: command not found

答案1

为什么sudo不使用你的 PATH

忽略您的 PATH 变量的原因sudo是它有自己的secure_path,并且相当确定地使用它。

如果你sudo cat /etc/sudoers或只是sudo grep secure /etc/sudoers,你会看到这个路径在你的系统上是什么。我有这一行:

Defaults    secure_path="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/snap/bin"

sudo的目的secure_path是尽量减少具有sudo特权的用户在其路径被修改(可能包括本地目录)后(意外地)以 root 身份运行危险代码的可能性。

可以通过修改注释掉该行来完全避免sudo使用,但这不是一个好主意,因为它会删除安全措施,而且也是不必要的,因为您可以通过各种可取的方式轻松解决它。secure_path/etc/sudoers

使用sudo你的 PATH

要覆盖secure_pathsudo使用当前定义的 PATH,正如 muru 评论的那样, 您可以使用:

sudo env PATH="$PATH" command

请注意,该-E标志或仅仅分配变量不起作用(至少在 Ubuntu 上)。

$ mkdir junk                            # create a test directory to add to PATH
$ echo "echo foo" > junk/useless        # create a harmless program
$ chmod u+x junk/useless                # make it executable
$ PATH="$PATH":~/junk                   # add directory to PATH

添加到 PATH 时,请使用绝对路径(shell 将~在分配变量之前进行扩展)。我不需要export(这样做也没有帮助),因为 PATH 已导出,更改其值也会导致子进程继承更改。

$ useless
foo
$ sudo useless
sudo: useless: command not found
$ sudo -E useless
sudo: useless: command not found

人们常常期望这会起作用...man sudo说:

-E, --preserve-env
            Indicates to the security policy that the user wishes to
            preserve their existing environment variables.

但那不管用。该-E标志对 不起作用secure_path这可能是一个错误

$ sudo PATH="$PATH" useless
sudo: useless: command not found

这不会影响sudo自己的环境,该环境已根据安全策略设置,由/etc/sudoers。这包括env_resetsecure_path作为 Ubuntu 上的默认值,导致加载最小环境并将 PATH 设置为 中的任何内容secure_path

如果sudo能够useless在其自己的路径目录中找到一个命令并运行它,它将进入PATH=$PATH其环境正如这里所示。但它本身不会使用给定的 PATH 值。解决方法是运行:

$ sudo env PATH="$PATH" useless
foo

此解决方法使用env命令设置 PATH。与 不同sudoenv使用给定的变量设置环境,然后查找命令参数并使用修改后的环境运行命令。info (coreutils) env invocation说:

修改PATH在搜索之前生效命令

设置 PATH

当您更改 PATH 变量以包含目录时/opt/lampp/bin,您使用了以下命令:

export PATH=$PATH:/opt/lampp/bin

这将对当前 shell 及其所有子进程(例如从此 shell 调用的 shell)有效。当您退出此 shell 及其所有子进程时,修改后的 PATH 变量已被彻底遗忘,当您打开新 shell 时,您会发现旧的 PATH 变量不包含/opt/lampp/bin。因此,完整命令muru 建议

sudo env PATH="$PATH:/opt/lampp/bin" php -v

/opt/lampp/bin如果你没有继续使用已经添加了 的 shell 的话,那么这将是必要的。

要永久更改路径,您需要编辑一些配置文件,该文件会修改您的用户环境或由 shell 在启动时读取。您可以在 中添加一行来分配环境变量~/.profile,例如:

PATH="$PATH:/opt/lampp/bin"

然后,在注销并重新登录(或运行source ~/.profile以立即查看效果)后,您将始终能够运行

php -v

或者

sudo env PATH="$PATH" php -v

无需先调整你的 PATH。

更简便的替代方案

一个更方便的解决方法是创建指向位于secure_path默认 PATH 中的可执行文件的符号链接,例如:

sudo ln -s /opt/lampp/bin/php /usr/local/bin/php

然后,您在使用 调用命令时不需要执行任何特殊操作sudo,也不需要采取任何步骤来永久或暂时调整您的 PATH。

如果您正在安装的程序的名称与系统进程可能尝试调用的另一个程序的名称相同,那么给符号链接赋予不同的名称,以避免混淆这些进程。您可以使用以下命令检查要使用的名称是否已是其他命令的名称type

$ type php
bash: type: php: not found

因此,目前在这个系统上我可以创建命令php而不用担心出错。如果我php将来安装其他提供命令的程序,我可能必须重新考虑我的配置。

您还可以为命令创建别名并将其添加到您的~/.bashrc,例如:

alias sudo-php='sudo env PATH="$PATH:/opt/lampp/bin/php"'

然后您可以(运行source .bashrc或打开新 shell 后)运行

sudo-php

而不是以sudo phproot 身份运行该程序,并且sudo不会声称不知道它的位置。

此别名仅在交互式 shell 中可用,因此不会混淆其他程序。

当然,可以创建一个别名,以sudo使其始终使用您的 PATH,alias sudo='sudo env PATH="$PATH"'但这是一个坏主意,因为它会降低系统的安全性。

相关内容