bash - 如何在 windows-subsystem-for-linux 上保持 windows $PATH when 'sudo su -'

标签 bash ubuntu windows-subsystem-for-linux

<分区>


这个问题似乎不是关于 a specific programming problem, a software algorithm, or software tools primarily used by programmers 的.如果您认为这个问题是关于 another Stack Exchange site 的主题,您可以发表评论以说明问题可能在哪里得到解答。

关闭 1 年前

社区在 去年 审查了是否重新打开这个问题并让它关闭:

原始关闭原因未解决

我在 Windows 10(版本 1803 内部版本 17134.345)上运行 Ubuntu(版本 1804.2018.817.0),使用适用于 Linux 的窗口子系统。

当我第一次打开控制台时,我使用我在第一次运行 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. 如何配置 bash,使 $PATH 在我使用 sudo su - 时包含窗口路径值,以便我可以运行 cmd.exe 之类的命令?<

最佳答案

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

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

  2. 当我使用 sudo su - 时,为什么 root 用户无法获取 Windows $PATH 值?
    检查 sudo sudo -V | grep PATH 来自 wsl 提示符。阅读 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.

The default security policy is sudoers, which is configured via the file /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. 如何配置 bash,以便在我使用 sudo su - 时 $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!

关于bash - 如何在 windows-subsystem-for-linux 上保持 windows $PATH when 'sudo su -',我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52776019/

上一篇:php - codeigniter url 中的访问被拒绝错误具有 index.php

下一篇:bash - 如何比较cpu串口是否正确

相关文章:

ubuntu - qemu virtio-9p-pci 不是有效的设备型号名称

linux - ubuntu:共享一个文件夹供组中所有用户使用

apache - 如何让 apache 跟随符号链接(symbolic link)到 WSL 上的 Windows 驱动器

mysql - 错误 2002 (HY000) : Can't connect to local MySQL server after my. cnf 更新

visual-studio - 通过 Visual Studio 在 WSL 1 上使用 vcpkg

bash - 无法使用 Windows bash wsl 查看本地 ip 上的端口

ruby - 如何在 crontab 中测试东西

linux - awk 和数据流通过管道不起作用

bash - 通过连接的第一列连接 3 个文件(是 awk)?

linux - 从 bash 脚本停用 pythonbrew