【问题标题】:how to keep windows $PATH when 'sudo su -' on windows-subsystem-for-linux [closed]windows-subsystem-for-linux上的'sudo su -'时如何保留windows $PATH [关闭]
【发布时间】:2018-10-12 09:05:38
【问题描述】:

我正在使用适用于 Linux 的 Window 子系统在 Windows 10(版本 1803 build 17134.345)之上从 Window Store 运行 Ubuntu(版本 1804.2018.817.0)。

当我第一次打开控制台时,我使用我第一次运行 Ubuntu 时创建的帐户登录。在这种情况下,我可以在 Windows 路径中执行操作,例如 cmd.exe

但是,当我使用 sudo su - 切换到 root 时,$PATH 变量不再包含 Windows 路径信息。所以当我输入cmd.exe 时,它会显示cmd.exe: command not found

我的问题是:

  1. 当我第一次打开 Ubuntu 时,Window $PATH 值来自哪里?
  2. 当我使用sudo su - 时,为什么root 用户无法获得Windows $PATH 值?
  3. 当我使用sudo su - 时,如何配置bash 使$PATH 包含Window 路径值,以便我可以运行cmd.exe 之类的命令?

【问题讨论】:

  • 在 regedit 中打开 HKCU\Software\Microsoft\Windows\CurrentVersion\Lxss > 查找 ``DistributionName"="Ubuntu1804"` > DefaultUidFlags 的值是多少?

标签: bash ubuntu windows-subsystem-for-linux


【解决方案1】:

虽然这个话题属于askubuntu,但我还是回答了。

  1. 当我第一次打开 Ubuntu 时,Window $PATH 的值是从哪里来的?
    来自标准Windows %PATH% environment variable,因为ubuntu.exe 进程是conhost.exe(以及Windows 命令提示符cmd.exe)的子进程。

  2. 当我使用 sudo su - 时,为什么 root 用户无法获得 Windows $PATH 值?
    wsl 提示符下检查 sudo sudo -V | grep PATH。阅读man sudo了解解释:

ENVIRONMENT
     sudo utilizes … environment variables.  The security policy 
     has control over the actual content of the command's environment.
…
     PATH             May be overridden by the security policy.

默认的安全策略是sudoers,通过以下方式配置 文件/etc/sudoers

试试这个说明性示例(将以下三个命令分别粘贴到打开的cmd 命令提示符中):

wsl echo ${#PATH}
wsl sudo su   -c 'echo ${PATH} ^&^& echo ${#PATH}'
wsl sudo su - -c 'echo ${PATH} ^&^& echo ${#PATH} ^&^& cat /etc/sudoers ^| grep Default'

结果(后面的命令也会查看/etc/sudoers):

d:\test> wsl echo ${#PATH}
1557

d:\test> wsl sudo su   -c 'echo ${PATH} ^&^& echo ${#PATH}'
[sudo] password for user:
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games
88

d:\test> wsl sudo su - -c 'echo ${PATH} ^&^& echo ${#PATH} ^&^& cat /etc/sudoers ^| grep Default'
[sudo] password for user:
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/snap/bin
70
Defaults        env_reset
Defaults        mail_badpass
Defaults        secure_path="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/snap/bin"

阅读man sudoers 以进一步了解默认值 选项:

env_reset   If set, sudo will run the command in a minimal environment containing
            the TERM, PATH, HOME, MAIL, SHELL, LOGNAME, USER, USERNAME and SUDO_*
            variables… If the secure_path option is set, its value will be used
            for the PATH environment variable.  This flag is on by default.

secure_path Path used for every command run from sudo.  If you don't trust the people
            running sudo to have a sane PATH environment variable you may want to use
            this.  Another use is if you want to have the “root path” be separate from
            the “user path”.  Users in the group specified by the exempt_group option
            are not affected by secure_path.  This option is not set by default.
  1. 当我使用sudo su - 时,如何配置bash 使$PATH 包含窗口路径值,以便我可以运行cmd.exe 之类的命令

    • 您可以通过sudoedit 使用env_keep 选项(不推荐用于security reasons)来保留用户的环境变量。
    • 为了快速前进,请将以下内容复制并粘贴到root 提示符中。它将当前 Windows %path% 变量中的所有文件夹路径添加到 $PATH。您可以考虑将其设为.sh 脚本并添加一些高级逻辑:
cmd.exe /c echo works!            # merely for documentation
echo "${#PATH}"                   # merely for documentation
cmd_path=`/mnt/c/Windows/System32/cmd.exe /C echo "%path:\\\\=\\\\\\\\%"`
OIFS="$IFS"                       # backup $IFS
IFS=';'
read -a c_p_n <<< "${cmd_path}"
IFS="$OIFS"                       # restore $IFS
OPATH="${PATH}"                   # backup  $PATH
for i in "${!c_p_n[@]}"; do PATH=${PATH%/}:$(sed -e 's#^\(.\):#/mnt/\L\1#' -e 's#\\#/#g' <<< "${c_p_n[$i]}"); done
echo "${#PATH}"                   # merely for documentation
cmd.exe /c echo works!            # merely for documentation

结果

user@COMP:~$ sudo su -
root@COMP:~# cmd.exe /c echo works!            # merely for documentation
cmd.exe: command not found
root@COMP:~# echo "${#PATH}"                   # merely for documentation
70
root@COMP:~# cmd_path=`/mnt/c/Windows/System32/cmd.exe /C echo "%path:\\\\=\\\\\\\\%"`
root@COMP:~# OIFS="$IFS"                       # backup $IFS
root@COMP:~# IFS=';'
root@COMP:~# read -a c_p_n <<< "${cmd_path}"
root@COMP:~# IFS="$OIFS"                       # restore $IFS
root@COMP:~# OPATH="${PATH}"                   # backup  $PATH
root@COMP:~# for i in "${!c_p_n[@]}"; do PATH=${PATH%/}:$(sed -e 's#^\(.\):#/mnt/\L\1#' -e 's#\\#/#g' <<< "${c_p_n[$i]}"); done
root@COMP:~# echo "${#PATH}"                   # merely for documentation
1555
root@COMP:~# cmd.exe /c echo works!            # merely for documentation
works!

【讨论】:

  • 我还建议阅读su 的手册页。它在su - 中调用- 参数:- ... start the shell as a login shell .... initializes the environment variables HOME, SHELL, USER, LOGNAME, and PATH。换句话说,su - 告诉它丢弃当前用户的 PATH 等环境变量。
  • @omajid 比较wsl sudo su - -c 'echo $PATH ^&amp;^&amp; cat /etc/sudoers ^| grep Defaults'(注意- 参数)和wsl sudo su -c 'echo $PATH ^&amp;^&amp; cat /etc/sudoers ^| grep Defaults'。不同的$PATH,不同的secure_path。无论如何,Windows %path% 等价物通过 env_reset 丢失。
猜你喜欢
  • 2019-02-11
  • 2018-03-17
  • 2018-10-21
  • 1970-01-01
  • 2021-11-16
  • 1970-01-01
  • 2020-04-04
  • 2016-12-13
  • 1970-01-01
相关资源
最近更新 更多