在systemd服务中使用环境变量

systemd 读取环境变量的机制

根据systemd/User中的说明如下:

Environment variables

The user instance of systemd does not inherit any of the environment variables set in places like .bashrc etc. There are several ways to set environment variables for the systemd user instance:

  • For users with a $HOME directory, create a .conf file in the ~/.config/environment.d/ directory with lines of the form NAME=VAL. Affects only that user’s user unit. See environment.d(5) for more information.
  • Use the DefaultEnvironment option in /etc/systemd/user.conf file. Affects all user units.
  • Add a drop-in configuration file in /etc/systemd/system/user@.service.d/. Affects all user units; see #Service example
  • At any time, use systemctl --user set-environment or systemctl --user import-environment. Affects all user units started after setting the environment variables, but not the units that were already running.
  • Using the dbus-update-activation-environment --systemd --all command provided by dbus. Has the same effect as systemctl --user import-environment, but also affects the D-Bus session. You can add this to the end of your shell initialization file.
  • For “global” environment variables for the user environment you can use the environment.d directories which are parsed by some generators. See environment.d(5) and systemd.generator(7) for more information.
  • You can also write a systemd.environment-generator(7) script which can produce environment variables that vary from user to user, this is probably the best way if you need per-user environments (this is the case for XDG_RUNTIME_DIRDBUS_SESSION_BUS_ADDRESS, etc).

One variable you may want to set is PATH.

After configuration, the command systemctl --user show-environment can be used to verify that the values are correct.

搜刮网上的一些说法后,总结如下:

  • /etc/profile或者/etc/security/limit.d这些文件中配置的环境变量仅对通过pam登录的用户生效,而systemd是不读这些配置的,所以这就造成登录到终端时查看环境变量和手动启动应用都一切正常,但是systemd无法正常启动应用
  • 如果需要给systemd配置默认参数,全局的配置在/etc/systemd/system.conf/etc/systemd/user.conf中。同时还会加载两个配置文件对应的目录中所有的.conf配置文件/etc/systemd/system.conf.d/*.conf/etc/systemd/user.conf.d/*.conf,一般的服务单元使用system.conf即可。加载优先级system.conf最低,所以system.conf.d目录中的配置会覆盖system.conf的配置
  • 目前已知的是更改system.conf配置,需要重启系统才能生效,还没找到如何重新加载此配置

虚拟机实验

实验目的: 看通过systemd运行的程序可以读取到哪些环境变量。

实验方法: 配置同一个脚本,脚本输出env的内容,比较shell下和systemd下启动该脚本的输出内容的区别。

试验文件准备

创建环境变量文件/etc/profile.d/env.sh,在其中设置环境变量MY_ENV="helloworld"

 

1

2

3

 

# cat /etc/profile.d/env.sh

export MY_ENV="helloworld"

#

创建service使用的脚本/usr/local/bin/systemctl_env_test.sh

 

1

2

3

4

5

 

#!/bin/bash

LOG_FILE="/tmp/systemctl_env_test.log"

echo "========================================================" > $LOG_FILE

env | sort >> $LOG_FILE

echo "========================================================" >> $LOG_FILE

 

1

2

3

4

5

6

7

8

 

#!/bin/bash

LOG_FILE="/tmp/systemctl_env_test.log"

echo "Start...." > $LOG_FILE

echo "======= Before load /etc/profile.d/env.sh" >> $LOG_FILE

env >> $LOG_FILE

source /etc/profile.d/env.sh >> $LOG_FILE

echo "======= After load /etc/profile.d/env.sh" >> $LOG_FILE

env >> $LOG_FILE

添加权限sudo chmod a+x /usr/local/bin/systemctl_env_test.sh

创建system service文件,/usr/lib/systemd/system/systemctl_env_test.service

 

1

2

3

4

5

6

7

8

9

10

11

 

[Unit]

Description=systemctl_env_test service

After=syslog.target network.target

[Service]

Type=forking

ExecStart=/usr/local/bin/systemctl_env_test.sh

PrivateTmp=false

[Install]

WantedBy=multi-user.target

导入service: systemctl daemon-reload

启动service命令: systemctl start systemctl_env_test.service

执行输出

当在shell下直接运行/usr/local/bin/systemctl_env_test.sh时,日志文件systemctl_env_test.log的输出如下:

 

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

 

# bash /usr/local/bin/systemctl_env_test.sh

#

# cat /tmp/systemctl_env_test.log

========================================================

HISTCONTROL=ignoredups

HISTSIZE=1000

HOME=/root

HOSTNAME=jk-server

LANG=zh_CN.UTF-8

LESSOPEN=||/usr/bin/lesspipe.sh %s

LOGNAME=root

LS_COLORS=rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:mi=01;05;37;41:su=37;41:sg=30;43:ca=30;41:tw=30;42:ow=34;42:st=37;44:ex=01;32:*.tar=01;31:*.tgz=01;31:*.arc=01;31:*.arj=01;31:*.taz=01;31:*.lha=01;31:*.lz4=01;31:*.lzh=01;31:*.lzma=01;31:*.tlz=01;31:*.txz=01;31:*.tzo=01;31:*.t7z=01;31:*.zip=01;31:*.z=01;31:*.Z=01;31:*.dz=01;31:*.gz=01;31:*.lrz=01;31:*.lz=01;31:*.lzo=01;31:*.xz=01;31:*.bz2=01;31:*.bz=01;31:*.tbz=01;31:*.tbz2=01;31:*.tz=01;31:*.deb=01;31:*.rpm=01;31:*.jar=01;31:*.war=01;31:*.ear=01;31:*.sar=01;31:*.rar=01;31:*.alz=01;31:*.ace=01;31:*.zoo=01;31:*.cpio=01;31:*.7z=01;31:*.rz=01;31:*.cab=01;31:*.jpg=01;35:*.jpeg=01;35:*.gif=01;35:*.bmp=01;35:*.pbm=01;35:*.pgm=01;35:*.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.tiff=01;35:*.png=01;35:*.svg=01;35:*.svgz=01;35:*.mng=01;35:*.pcx=01;35:*.mov=01;35:*.mpg=01;35:*.mpeg=01;35:*.m2v=01;35:*.mkv=01;35:*.webm=01;35:*.ogm=01;35:*.mp4=01;35:*.m4v=01;35:*.mp4v=01;35:*.vob=01;35:*.qt=01;35:*.nuv=01;35:*.wmv=01;35:*.asf=01;35:*.rm=01;35:*.rmvb=01;35:*.flc=01;35:*.avi=01;35:*.fli=01;35:*.flv=01;35:*.gl=01;35:*.dl=01;35:*.xcf=01;35:*.xwd=01;35:*.yuv=01;35:*.cgm=01;35:*.emf=01;35:*.axv=01;35:*.anx=01;35:*.ogv=01;35:*.ogx=01;35:*.aac=01;36:*.au=01;36:*.flac=01;36:*.mid=01;36:*.midi=01;36:*.mka=01;36:*.mp3=01;36:*.mpc=01;36:*.ogg=01;36:*.ra=01;36:*.wav=01;36:*.axa=01;36:*.oga=01;36:*.spx=01;36:*.xspf=01;36:

MAIL=/var/spool/mail/root

MY_ENV=helloworld

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

PWD=/root

SELINUX_LEVEL_REQUESTED=

SELINUX_ROLE_REQUESTED=

SELINUX_USE_CURRENT_RANGE=

SHELL=/bin/bash

SHLVL=2

SSH_CLIENT=192.168.187.1 54467 22

SSH_CONNECTION=192.168.187.1 54467 192.168.187.81 22

SSH_TTY=/dev/pts/0

TERM=xterm-color

USER=root

_=/usr/bin/env

XDG_RUNTIME_DIR=/run/user/0

XDG_SESSION_ID=77

========================================================

#

可以看到/etc/profile.d/env.sh中设置的MY_ENV=helloworld能够被脚本/usr/local/bin/systemctl_env_test.sh读取到。

使用systemctl运行systemctl_env_test.service来执行脚本/usr/local/bin/systemctl_env_test.sh时,输出如下:

 

1

2

3

4

5

6

7

8

9

10

11

 

# systemctl start systemctl_env_test.service

#

# cat /tmp/systemctl_env_test.log

========================================================

LANG=zh_CN.UTF-8

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

PWD=/

SHLVL=1

_=/usr/bin/env

========================================================

#

可以看到除了/etc/profile.d/env.sh中设置的MY_ENV=helloworld没有被读取外,连基础的HOSTNAME,SHELL等环境变量都没有。

结论
  • 可以看到shell中运行脚本可以读取到全部正常的环境变量

  • systemd中运行脚本,只读取到最最基础的LANG,PATHPWD几个环境变量, /etc/profile下的环境变量并没有读取。

systemd添加使用环境变量的方法

使用Environment设置环境变量

可以在systemdservice中使用Environment来设置环境变量。

修改原文件/usr/lib/systemd/system/systemctl_env_test.service,使用Environment关键字来添加如下环境变量:

 

1

2

3

 

Environment="One=1" "Three=3"

Environment="Two=2"

Environment="Four=4"

此时/usr/lib/systemd/system/systemctl_env_test.service变为:

 

1

2

3

4

5

6

7

8

9

10

11

12

13

14

 

[Unit]

Description=systemctl_env_test service

After=syslog.target network.target

[Service]

Type=forking

Environment="One=1" "Three=3"

Environment="Two=2"

Environment="Four=4"

ExecStart=/usr/local/bin/systemctl_env_test.sh

PrivateTmp=false

[Install]

WantedBy=multi-user.target

执行systemctl start后查看脚本env的输出日志,结果如下:

 

1

2

3

4

5

6

7

8

9

10

11

12

13

 

# systemctl start systemctl_env_test.service && cat /tmp/systemctl_env_test.log

========================================================

Four=4

LANG=zh_CN.UTF-8

One=1

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

PWD=/

SHLVL=1

Three=3

Two=2

_=/usr/bin/env

========================================================

#

可以看出systemdservice文件中设置的环境变量,可以被ExecStart指定的脚本读取到。

使用EnvironmentFile导入环境变量文件

使用Environment导入少数固定的环境变量是可行的,但是如果需要导入大量的,或者时常要变动的环境变量,那么使用EnvironmentFile 关键字通过导入文件的方式会更合适。

试验方法如下:

创建测试用环境变量文件/usr/local/etc/environment_file_test/load.conf, 内容如下:

 

1

2

 

MY_ENV="helloworld"

GLOBAL_ENV="nihaoshijie"

修改原文件/usr/lib/systemd/system/systemctl_env_test.service,使用EnvironmentFile关键字来导入文件/usr/local/etc/environment_file_test/load.conf

 

1

 

EnvironmentFile=/usr/local/etc/environment_file_test/load.conf

此时/usr/lib/systemd/system/systemctl_env_test.service变为:

 

1

2

3

4

5

6

7

8

9

10

11

12

 

[Unit]

Description=systemctl_env_test service

After=syslog.target network.target

[Service]

Type=forking

EnvironmentFile=/usr/local/etc/environment_file_test/load.conf

ExecStart=/usr/local/bin/systemctl_env_test.sh

PrivateTmp=false

[Install]

WantedBy=multi-user.target

执行systemctl start后查看脚本env的输出日志,结果如下:

 

1

2

3

4

5

6

7

8

9

10

11

 

# systemctl start systemctl_env_test.service && cat /tmp/systemctl_env_test.log

========================================================

GLOBAL_ENV=nihaoshijie

LANG=zh_CN.UTF-8

MY_ENV=helloworld

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

PWD=/

SHLVL=1

_=/usr/bin/env

========================================================

#

可以看出systemdservice文件中设置的环境变量,可以被ExecStart指定的脚本读取到。

注意: /usr/local/etc/environment_file_test/load.conf文件是配置文件,就是key=value的格式,和/etc/profile.d/中导入的shell文件是不同的,需要加以区别。所以load.conf配置文件中,不能使用export xx=yy的格式

在执行命令或脚本中设置或者source环境变量文件

除了在systemdservice文件中指定EnvironmentEnvironmentFile外,还有一个方法就是在ExecStartExecStop等执行的脚本中直接指定环境变量或者source环境变量文件。

在上面的几个例子中,也可以不在/usr/lib/systemd/system/systemctl_env_test.service文件中使用EnvironmentEnvironmentFile,而是直接在执行的shell脚本/usr/local/bin/systemctl_env_test.shsource /etc/profile.d/environment_file_test.sh

试验方法如下:

修改ExecStart执行的shell脚本/usr/local/bin/systemctl_env_test.sh, 在里面添加source /etc/profile.d/env.sh , 添加后的文件内容为:

 

1

2

3

4

5

6

 

#!/bin/bash

LOG_FILE="/tmp/systemctl_env_test.log"

echo "========================================================" > $LOG_FILE

source /etc/profile.d/env.sh

env | sort >> $LOG_FILE

echo "========================================================" >> $LOG_FILE

其中/etc/profile.d/env.sh文件的内容如下:

 

1

 

export MY_ENV="helloworld"

还原文件/usr/lib/systemd/system/systemctl_env_test.service去除EnvironmentEnvironmentFile的设置,变为:

 

1

2

3

4

5

6

7

8

9

10

11

 

[Unit]

Description=systemctl_env_test service

After=syslog.target network.target

[Service]

Type=forking

ExecStart=/usr/local/bin/systemctl_env_test.sh

PrivateTmp=false

[Install]

WantedBy=multi-user.target

执行systemctl start后查看脚本env的输出日志,结果如下:

 

1

2

3

4

5

6

7

8

9

10

 

# systemctl start systemctl_env_test.service && cat /tmp/systemctl_env_test.log

========================================================

LANG=zh_CN.UTF-8

MY_ENV=helloworld

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

PWD=/

SHLVL=1

_=/usr/bin/env

========================================================

#

可以看出也能加载出MY_ENV这个环境变量。

注意这边是shell脚本中source /etc/profile.d/env.sh, 所以文件中需要加上export,父shell才能读取对应的内容。

### 回答1: 您可以输入以下命令安装或更新systemctl: sudo apt-get update sudo apt-get install systemd 确保systemd在PATH环境变量,您可以运行以下命令: echo $PATH 如果需要,您可以将systemd的路径添加到PATH环境变量。 ### 回答2: 要安装或更新systemctl命令并确保它在PATH环境变量,可以按照以下步骤进行操作: 1. 首先,确认你的操作系统是基于SystemdLinux发行版,如Ubuntu、Fedora、Debian等。因为systemctl是Systemd的主要命令,只能在Systemd系统上使用。 2. 如果你使用的是Ubuntu或Debian,打开终端并运行以下命令,以安装systemctl: ``` sudo apt-get update sudo apt-get install systemd ``` 3. 如果你使用的是Fedora或CentOS,打开终端并运行以下命令,以安装systemctl: ``` sudo dnf update sudo dnf install systemd ``` 4. 安装完毕后,可以通过运行以下命令来验证systemctl是否已成功安装: ``` systemctl --version ``` 如果显示了systemctl的版本信息,则说明安装成功。 5. 确保systemctl所在的路径已添加到PATH环境变量,以便可以从任何目录直接执行该命令。打开终端并编辑你的bash配置文件(通常是~/.bashrc或~/.bash_profile): ``` nano ~/.bashrc ``` 在文件末尾添加以下内容: ``` export PATH="/usr/bin/systemctl:$PATH" ``` 保存文件并退出。 6. 更新bash配置文件后,需要重新加载它以使更改生效。运行以下命令来重新加载bash配置文件: ``` source ~/.bashrc ``` 现在,你应该能够从任何位置使用systemctl命令,而无需指定完整的路径。 以上就是安装或更新systemctl命令并确保它在PATH环境变量的步骤。请根据你使用Linux发行版进行相应的操作。 ### 回答3: 要安装或更新systemctl命令并确保其在PATH环境变量,可以按照以下步骤操作: 1. 确认系统是基于Systemd的。Systemd是一个用于启动、管理和控制Linux系统的初始化系统。可以运行以下命令检查系统是否支持Systemd: ``` ps -p 1 -o comm= ``` 如果返回的结果是`systemd`,则表示系统已经基于Systemd。否则,需要将系统升级到支持Systemd的版本。 2. 安装Systemd软件包。可以使用以下命令来安装Systemd软件包(考虑到不同的Linux发行版,命令可能会略有不同): ``` sudo apt-get install systemd ``` 或者 ``` sudo yum install systemd ``` 根据系统的不同,可能需要使用适当的包管理器来安装Systemd。 3. 更新PATH环境变量。可以通过编辑`.bashrc`或`.bash_profile`文件来更新PATH环境变量。可以使用以下命令打开文件进行编辑: ``` vi ~/.bashrc ``` 或者 ``` vi ~/.bash_profile ``` 在文件的末尾添加以下行: ``` export PATH=$PATH:/usr/bin/systemctl ``` 保存文件并关闭编辑器。 4. 重新加载配置。执行以下命令来重新加载更新后的配置文件: ``` source ~/.bashrc ``` 或者 ``` source ~/.bash_profile ``` 这将使更新后的PATH环境变量生效。 5. 检查systemctl命令是否成功安装或更新并在PATH环境变量。可以使用以下命令来查看systemctl命令的版本信息: ``` systemctl --version ``` 如果命令成功执行,并显示系统的systemctl版本信息,则表示安装或更新成功,并且systemctl命令已经在PATH环境变量
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值