[Seek Help] 我设置的PATH变量不知道在哪里被覆盖了 Resolved
Tofloor
poster avatar
码梦天涯
deepin
2025-02-21 17:33
Author

我需要由systemd启动的进程可以访问一些环境变量,

把这些变量加在了~/.config/environment.d/99-xxx.conf文件中,

检查systemctl --user show-environment

其余变量都可以奏效,唯独PATH似乎在哪里被无情的覆盖了,

始终都是/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games:/sbin:/usr/sbin

我的系统版本是v23

这里有一个类似的issue,但他是2017年的,而且说明这了不是systemd的bug

https://github.com/systemd/systemd/issues/6414

而且

~/.config/environment.d/99-xxx.conf被读取时的PATH是/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin

后面systemctl --user show-environment看到的/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games:/sbin:/usr/sbin不只是有点变化,更像是毫无关系

已决绝

最后在/etc/profile里面加了以下一段

if [ "$(id -u)" -ne 0 ]; then
  cur_user="$(id --user --name)"
  [ -f "/home/${cur_user}/.profile" ] && . "/home/${cur_user}/.profile";
  # echo $PATH > "/home/${cur_user}/Desktop/profile-$(date +%s).log"
  unset cur_user
  export PATH
fi

大概...应该不会影响其他用户吧

缺点

每次修改环境变量,最起码要注销一下登录,不然不会触发这里,systemd拿不到最新的变量(这体验..简直如同windows)

Reply Favorite View the author
All Replies
deepinuser17
deepin
2025-02-22 00:13
#1

如果想设定个人的环境变量, 在~/.bashrc文件的末尾,加入:

export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin

Reply View the author
hotime
deepin
2025-02-22 15:54
#2

那要不就 再给它再盖回去?

~/.bashrc~/.zshrc中,加上:

if [ -f ~/.config/environment.d/90-env.conf ]; then
    . ~/.config/environment.d/90-env.conf
fi
systemctl --user set-environment PATH="$PATH"

然后重启看看?

图片.png

Reply View the author
码梦天涯
deepin
2025-02-23 00:27
#3
hotime

那要不就 再给它再盖回去?

~/.bashrc~/.zshrc中,加上:

if [ -f ~/.config/environment.d/90-env.conf ]; then
    . ~/.config/environment.d/90-env.conf
fi
systemctl --user set-environment PATH="$PATH"

然后重启看看?

图片.png

如果我一次没打开过bash或者zsh,这也不会起效啊😂

Reply View the author
码梦天涯
deepin
2025-02-23 00:28
#4
deepinuser17

如果想设定个人的环境变量, 在~/.bashrc文件的末尾,加入:

export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin

不是这个问题,~/.bashrc只在打开bash后才会生效

Reply View the author
deepinuser17
deepin
2025-02-23 08:36
#5

可以在systemd启动文件里, 用EnviornmentFile=<环境变量文件>来指定加载环境变量的文件路径。

例如:

[Unit]
Description=description-about-the-service
After=network.target

[Service]
Type=simple  
Restart=always
User=username-the-service-should-run-as
EnvironmentFile=/path/to/environment/file1
EnvironmentFile=/path/to/environment/file2
ExecStart=/path/to/the/script/to/start

[Install]
WantedBy=multi-user.target
Reply View the author
neko
deepin
Ecological co-builder
Resources Team Moderator
2025-02-23 21:06
#6

在不同地方的配置文件里都输出一下PATH变量和文件路径

Reply View the author
hotime
deepin
2025-02-23 22:34
#7
码梦天涯

如果我一次没打开过bash或者zsh,这也不会起效啊😂

那就写到脚本里,用户登陆时自动执行:

~/.config/autostart/set_systemd_user_path.desktop

[Desktop Entry]
Exec=~/.local/bin/set_systemd_user_path.sh
Name=set_user_path_for_systemd_app
Name[zh_CN]=设定systemd用户PATH
Type=Application

~/.local/bin/set_systemd_user_path.sh

#!/bin/sh

# 设置用户环境变量(可作用于systemd用户应用)
if [ -f ~/.config/environment.d/90-env.conf ]; then
    . ~/.config/environment.d/90-env.conf  
fi
systemctl --user set-environment PATH="$USER_PATH"

~/.config/environment.d/90-env.conf

JAVA_HOME="~/Dev/JDK/jdk-11.0.22"
USER_PATH="$JAVA_HOME/bin:$PATH"
Reply View the author
码梦天涯
deepin
2025-02-24 09:26
#8
hotime

那就写到脚本里,用户登陆时自动执行:

~/.config/autostart/set_systemd_user_path.desktop

[Desktop Entry]
Exec=~/.local/bin/set_systemd_user_path.sh
Name=set_user_path_for_systemd_app
Name[zh_CN]=设定systemd用户PATH
Type=Application

~/.local/bin/set_systemd_user_path.sh

#!/bin/sh

# 设置用户环境变量(可作用于systemd用户应用)
if [ -f ~/.config/environment.d/90-env.conf ]; then
    . ~/.config/environment.d/90-env.conf  
fi
systemctl --user set-environment PATH="$USER_PATH"

~/.config/environment.d/90-env.conf

JAVA_HOME="~/Dev/JDK/jdk-11.0.22"
USER_PATH="$JAVA_HOME/bin:$PATH"

哈哈哈哈,有够hack,不过也确实没别的好办法了😂

Reply View the author
码梦天涯
deepin
2025-02-24 09:35
#9
neko

在不同地方的配置文件里都输出一下PATH变量和文件路径

是的,.conf被读取期间PATH是/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin

读取完毕的PATH完全是符合我预期的,但是

后面又变成了/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games:/sbin:/usr/sbin

所以这铁定就是直接覆盖的,而不是读取原PATH再拼接回去的

Reply View the author
码梦天涯
deepin
2025-02-24 09:56
#10
hotime

那就写到脚本里,用户登陆时自动执行:

~/.config/autostart/set_systemd_user_path.desktop

[Desktop Entry]
Exec=~/.local/bin/set_systemd_user_path.sh
Name=set_user_path_for_systemd_app
Name[zh_CN]=设定systemd用户PATH
Type=Application

~/.local/bin/set_systemd_user_path.sh

#!/bin/sh

# 设置用户环境变量(可作用于systemd用户应用)
if [ -f ~/.config/environment.d/90-env.conf ]; then
    . ~/.config/environment.d/90-env.conf  
fi
systemctl --user set-environment PATH="$USER_PATH"

~/.config/environment.d/90-env.conf

JAVA_HOME="~/Dev/JDK/jdk-11.0.22"
USER_PATH="$JAVA_HOME/bin:$PATH"

找到问题了,/etc/profile里面覆盖的,开头直接是静态字符串无脑覆盖的,,, 我刚刚试了启动项的办法,shell里面可以正常,但是ide里面还是没有生效, 但是感谢

Reply View the author
hotime
deepin
2025-02-24 13:16
#11
码梦天涯

找到问题了,/etc/profile里面覆盖的,开头直接是静态字符串无脑覆盖的,,, 我刚刚试了启动项的办法,shell里面可以正常,但是ide里面还是没有生效, 但是感谢

纯好奇,可以讲一下你是怎么在IDE中测试这个不生效的吗?

Reply View the author
码梦天涯
deepin
2025-02-24 14:26
#12
hotime

纯好奇,可以讲一下你是怎么在IDE中测试这个不生效的吗?

是这样的,建了一个Shell Script的Run Configuration,选择Script text,取消掉Execute in the terminal
image.png

而且我也都确认加了x的权限,我也很奇怪,为什么会不生效

又试了一遍,是sh没执行....

现在sh执行了,show-environment可以看到PATH的改动了,但是ide里面还是那个覆盖过来的PATH

Reply View the author
码梦天涯
deepin
2025-02-24 15:35
#13
hotime

纯好奇,可以讲一下你是怎么在IDE中测试这个不生效的吗?

而且我log里面加了时间,发现autostart执行的脚本是晚于/etc/profile的,这种情况下还不生效就更奇怪了,完全解释不通

Reply View the author
hotime
deepin
2025-02-24 18:01
#14
码梦天涯

是这样的,建了一个Shell Script的Run Configuration,选择Script text,取消掉Execute in the terminal
image.png

而且我也都确认加了x的权限,我也很奇怪,为什么会不生效

又试了一遍,是sh没执行....

现在sh执行了,show-environment可以看到PATH的改动了,但是ide里面还是那个覆盖过来的PATH

我看了一下软件界面,有些大致的猜测。

在取消勾选“Execute in the terminal”时,可以注意到它的上方有个配置项“Environment variables”。

截图_jetbrains-rustrover_20250224174557.png


截图_jetbrains-rustrover_20250224174700.png

从打开后的界面中可以看出,RustRover在这里是可以自行配置“Shell Script”运行所需环境变量的,默认勾选了“Include System environment variable”,暂时还没有任何由用户自定义的变量。

所以这看起来是一个相对独立的环境变量配置,和systemd的用户环境变量没有关系。

也就是说,我们要想用当前用户的shell中配置的环境变量去执行脚本,就勾选“Execute in the terminal”,如果我们想自定义,就不勾选,然后自己在这里定义用户环境变量PATH或其他。

我是这么理解的...


如果就要限定不勾选“Execute in the terminal”,看起来只能我们把桌面入口文件复制到用户目录,然后在Exec项加上环境变量了(更省事点)

cp /usr/share/applications/com.jetbrains.rustrover.desktop ~/.local/share/applications/

编辑修改 ~/.local/share/applications/com.jetbrains.rustrover.desktop

Exec项由:
Exec=/opt/apps/com.jetbrains.rustrover/files/RustRover/bin/rustrover.sh %u

修改为:

Exec=env PATH=~/.cargo/bin:$PATH /opt/apps/com.jetbrains.rustrover/files/RustRover/bin/rustrover.sh %u

注销重新登陆或重启。

如果桌面有RustRover的桌面入口文件软连接记得删掉,重新发送到桌面;如果任务栏有驻留RustRover,记得取消驻留然后从启动器打开RustRover重新驻留(启动器里显示的RustRover会替换成用户目录的桌面入口文件)

这个办法对于用户没有管理员权限或不便修改/etc目录的系统级配置文件的情形下,会有点帮助吧。


话说楼主那个改/etc/profile的,其实也可以考虑单独写到 /etc/profile/xxx.sh (更正)/etc/profile.d/xxx.sh中,未来重新安装系统进行配置时候有单独的文件也方便些。

Reply View the author
码梦天涯
deepin
2025-02-25 10:47
#15
hotime

我看了一下软件界面,有些大致的猜测。

在取消勾选“Execute in the terminal”时,可以注意到它的上方有个配置项“Environment variables”。

截图_jetbrains-rustrover_20250224174557.png


截图_jetbrains-rustrover_20250224174700.png

从打开后的界面中可以看出,RustRover在这里是可以自行配置“Shell Script”运行所需环境变量的,默认勾选了“Include System environment variable”,暂时还没有任何由用户自定义的变量。

所以这看起来是一个相对独立的环境变量配置,和systemd的用户环境变量没有关系。

也就是说,我们要想用当前用户的shell中配置的环境变量去执行脚本,就勾选“Execute in the terminal”,如果我们想自定义,就不勾选,然后自己在这里定义用户环境变量PATH或其他。

我是这么理解的...


如果就要限定不勾选“Execute in the terminal”,看起来只能我们把桌面入口文件复制到用户目录,然后在Exec项加上环境变量了(更省事点)

cp /usr/share/applications/com.jetbrains.rustrover.desktop ~/.local/share/applications/

编辑修改 ~/.local/share/applications/com.jetbrains.rustrover.desktop

Exec项由:
Exec=/opt/apps/com.jetbrains.rustrover/files/RustRover/bin/rustrover.sh %u

修改为:

Exec=env PATH=~/.cargo/bin:$PATH /opt/apps/com.jetbrains.rustrover/files/RustRover/bin/rustrover.sh %u

注销重新登陆或重启。

如果桌面有RustRover的桌面入口文件软连接记得删掉,重新发送到桌面;如果任务栏有驻留RustRover,记得取消驻留然后从启动器打开RustRover重新驻留(启动器里显示的RustRover会替换成用户目录的桌面入口文件)

这个办法对于用户没有管理员权限或不便修改/etc目录的系统级配置文件的情形下,会有点帮助吧。


话说楼主那个改/etc/profile的,其实也可以考虑单独写到 /etc/profile/xxx.sh (更正)/etc/profile.d/xxx.sh中,未来重新安装系统进行配置时候有单独的文件也方便些。

我在用napi-rs做一个绑定库,napi-rs的cli是通过npm脚本来执行的,之后会在npm启动的nodejs进程里面,打开一个子进程,执行cargo命令,关掉Execute in terminal就是为了模拟这个情况


模拟下来相当于是这样的Shell text

node -e "console.log(require('child_process').execSync('cargo --version', { stdio: 'pipe' }).toString());"

windows上面相同的操作不会有问题,毕竟按照windows的逻辑,以用户X身份打开的程序,应该就是有用户X的用户变量

而且我打开Terminal面板,手敲命令也不会有这个问题,但是感觉不太科学,不符合直觉,所以才觉得应该是有问题在这里面


我最开始想到的是一定在哪里可以配置,但是前面试过的几个配置方式都会被覆盖,找来找去找到/etc/profile

顺便更正一下,我觉得你想说的应该是/etc/profile.d/xxx.sh,我这就挪过去👍

Reply View the author