为什么用户不应该使用正常的sudo来启动图形化应用程序?

我已经阅读了“RootSudo”社区文档,对这句话很感兴趣:

你绝对不应该使用普通的sudo来以Root身份启动图形应用程序。

为什么呢?有什么区别吗?请给出一个简单的解释,因为我只是一个普通的桌面用户。

1其实,最近我在将MATLAB安装到/usr/local上遇到了一些困难。这需要root权限才能写入/usr/local,但是使用gksu运行安装程序却使得无法以非root用户身份运行已安装的程序。而使用sudo运行安装程序则一切正常。 - Bib-lost
另一个原因是:任何应用程序(即使没有根权限)都可以嗅探键盘输入,并获取您的sudo密码。图形化的sudo可能会尝试防止这种情况发生。 - Dan Dascalescu
3个回答

在Ubuntu 19.10及更高版本中,该文章(以及本答案)中的警告不再适用。请参阅WinEunuuchs2Unix的答案以及此问题
图形应用程序通常将设置和其他用户特定数据存储在写入用户主文件夹内的配置文件中。应用程序用于确定用户主文件夹的主要机制是HOME环境变量。(您可以使用echo $HOME自行检查它)。
假设你正在以root身份运行gedit(一个图形化文本编辑器)。如果你运行sudo gedit,HOME将继续指向你的主目录,即使程序是以root身份运行的。因此,gedit将会将配置文件作为root写入你的主目录。这有时会导致配置文件被root拥有,从而对你来说无法访问(当你以自己的身份而不是root身份运行程序时)。这主要发生在应用程序需要创建新的配置文件时。默认情况下,新创建的文件归创建它们的用户所有(在这种情况下是root,而不是你)。

这就是为什么你应该使用图形界面的sudo前端来运行图形应用程序,而不是直接使用sudo的主要原因。在Ubuntu和它的大多数衍生版(包括Xubuntu和Lubuntu)中,标准的图形界面前端是{{link1:gksu/gksudo}}。在Kubuntu中是{{link2:kdesudo}}。(这取决于所使用的桌面环境。)

如果你想直接使用sudo来运行像gedit这样的图形应用程序,你可以运行:

sudo -H gedit

-H 标志使得 sudoHOME 设置为指向 root 的主文件夹(即 /root)。

这仍然不能自动处理 .Xauthority 的所有权,也不能将其复制到临时文件夹中(这是图形化 sudo 前端为您处理的另一件事情)。但是,在不经常发生的情况下,如果无法访问 .Xauthority,您将收到一个错误提示,然后可以通过删除它(sudo rm ~/.Xauthority)来解决问题,因为它会自动重新生成。因此,保护 .Xauthority 的所有权和权限比保护配置文件的所有权和权限更不重要。

与以root所有的.Xauthority不同,当配置文件变为root所有时,问题往往不太明显(因为图形程序通常会运行,但效果不佳,并且不会将任何有用的错误输出到控制台)。而且有时候修复起来更麻烦,特别是如果你希望你的家目录中的一个或多个文件归属于其他人(因为这样你不能简单地递归地将所有文件的所有权重新设置为自己来修复它)。
因此,除非你非常熟悉应用程序的内部工作原理并确切知道它绝对不会尝试写入任何配置文件,否则不应该使用sudo(至少不带-H)来运行图形应用程序。

如果我的Home目录中的配置文件(或任何文件)已经被root所有,我能否再次成为这些文件的所有者? - Nur
@Nur 假设您的主目录中没有任何文件希望被其他用户拥有或希望具有其他组成员身份(用于共享),您可以运行以下命令:sudo chmod -R $USER:$USER ~ 不幸的是,这些条件并不总是适用。如果您有需要保留组所有者的文件,您可以运行 sudo chmod -R $USER ~。通常情况下,这已经足够了。(如果您的主目录中有需要由其他用户拥有的文件,即使使用这个命令也会有问题。) - Eliah Kagan
如果你没有遇到任何错误或问题,即使你以直接的sudo方式运行图形应用程序作为root用户,也有可能你很幸运地没有任何属于root用户的配置文件。(这种情况可能发生在它从未创建过文件的情况下,因为这是文件变为root所有的主要情况。)如果你没有遇到任何问题,我不会担心。 - Eliah Kagan
1@EliahKagan chmod真的能做到吗?我一直以为是chown来完成这个任务的。chmod从来没有对我起作用过。 - Wyatt Ward
3@Wyatt8740 我在上面的评论中应该明确写成 chown 而不是 chmod。对此我感到非常抱歉,也感谢你指出来! - Eliah Kagan
那么 gksudo 会帮我解决所有者问题吗?还是在使用 gksudo 时我仍然需要考虑这些情况? - Zaibis
@Zaibis 是的,使用gksudo你就不必担心这个问题了。当你使用gksudo或者kdesudo来运行一个图形界面程序时,你的家目录中不会出现意外的以root所有的文件。这就是为什么它们是理想的选择。你还会得到一个图形化的密码提示,所以你可以从运行对话框(Alt+F2)或终端中使用它们。我提到sudo -H的原因是因为只有一些Ubuntu版本预装了gksudokdesudo。你仍然可以安装gksudo。(kdesudo只适用于KDE系统。)但如果你不想安装,sudo -H是一个合理的选择,比裸sudo要好得多。 - Eliah Kagan
有没有不应该使用gksudo的情况?或者是否有其他原因,即使我忘记了,也不应该创建一个别名来使用gksudo代替sudo? - Superole
@Superole 这是一个很好的问题;为了更深入地讨论,我建议您发帖。但是,通常情况下不应使用gksudo,我也不建议将sudo设置为其别名。对于非图形界面命令,有时您可能想保留$HOMEgksudo需要一个可用的显示器(尝试使用DISPLAY= gksudo ls与使用sudo进行比较);sudogksudo具有不同的选项,一些“相同”的选项如-k是无关的;而且即使您刚刚成功运行了它,gksudo也会提示您输入密码。此外,您仍然需要小心,因为别名并不总是被扩展 - Eliah Kagan
gksu在Debian 9和Ubuntu 18.04中不再可用 - 更多信息请参阅https://tracker.debian.org/pkg/gksu和https://bugs.launchpad.net/ubuntu/+source/umit/+bug/1740618。这里有一个关于替代方案的问题:https://askubuntu.com/questions/1042344/ - rpr
运行sudo -H echo $HOME仍然返回我的普通用户的主目录,而不是/root或/home/root目录(在Linux Mint 19.1上使用sudo版本1.8.21p2)。 - The Quark
2@TheQuark 在 sudo -H echo $HOME 中,你的 shell(以你的身份而不是 root 身份运行)对 $HOME 进行 参数扩展,获取 的主目录路径,然后将其传递给 sudo,而 sudo 又将已经扩展的值传递给 echo,最后打印出来。sudo -H printenv HOMEsudo -H bash -c 'echo $HOME'sudo -H sh -c 'echo $HOME' 都会打印 /root。这在概念上类似于 x=a echo "$x" 不会打印 a(除非 x 已经有了值 a),尽管机制不同。 - Eliah Kagan
为了让家里的一切保持安全,我只是使用sudo -i而已。 - mchid


现在的 Ubuntu 和 Debian 安装中已不再包含 gksudo 。详细信息请参阅 https://itsfoss.com/gksu-replacement-ubuntu/ 。https://askubuntu.com/a/1047413/197910 现在是更好的解决方案。 - K7AAY

Ubuntu 19.10 更新

Ubuntu 19.10 开始,输入 sudo some_command 的效果与输入 sudo -H some_command 相同。这意味着任何被操作的配置文件所在的目录将位于 /root 目录而不是 /home/regular_userID 目录(也就是 $HOME)。

对于 Ubuntu 19.10 及更高版本的用户来说,这使得整个问题和答案在很大程度上变得无关紧要。

要查看你的发行版是否像 sudo -H 一样工作,请尝试以下简短测试:

$ sudo printenv | grep HOME
HOME=/home/rick

$ sudo -H printenv | grep HOME
HOME=/root

如你所见,上面的sudo并不像sudo -H那样工作,因此使用普通的sudo可能会损坏你的用户配置文件。
使用 nautilus-admin 插件可替代 gksu nautilusgksu geditsudo -H gedit。它允许您在Nautilus中浏览文件和目录,然后以 root (管理员) 身份打开它们。
安装非常简单:
sudo apt install nautilus-admin

现在当你在Nautilus中时,你将有一个额外的选项可以作为管理员进行编辑。

nautilus admin.gif


gedit 作为 root 用户不能使用首选项

当您以 root 用户身份运行 gedit 时,无法使用您作为普通用户设置的制表位、将制表符转换为空格、字体名称、字体大小、自动换行等首选项。

为解决此问题,我编写了脚本 sgedit,用于继承用户首选项并将其应用于 root:如何将我的 root gedit 与用户 gedit 的首选项同步?

  • 使用sgedit 文件名1 文件名2 ...进行调用
  • 获取用户的gedit设置,包括制表符、字体、换行等。
  • 提升为sudo -H以保留文件所有权并获取root权限。
  • 如果上一个sudo已超时,则请求密码。
  • 获取sudo的gedit设置。
  • 比较用户和sudo的gedit设置之间的差异。
  • 仅对差异部分运行gsettings set命令(将174个set命令减少到十几个或更少。下次运行时可能只有一两个变化,但通常没有变化)。
  • 以后台任务方式调用gedit,使终端提示立即重新出现。

1最好根本不要以root身份运行gedit,而是使用admin:///。这实际上就是nautilus-admin扩展所做的。通过一个非常简单的包装脚本,你也可以轻松地从命令行中实现这一点,参见我对https://askubuntu.com/questions/1191075/how-to-open-a-text-file-in-current-working-directory-with-gedit-admin/1191093#1191093的回答。 - vanadium
只是为了澄清一下:上述编辑是否意味着在19.10+版本中,现在可以安全地运行sudo {GUI命令},就像我们在gksudo被移除之前使用gksudo {GUI命令}一样? - TrailRider
@TrailRider 是的,正如这里得票最高的答案详细解释的那样。 - WinEunuuchs2Unix