![就像我登录一样从 systemd 运行 bash 脚本](https://linux22.com/image/690665/%E5%B0%B1%E5%83%8F%E6%88%91%E7%99%BB%E5%BD%95%E4%B8%80%E6%A0%B7%E4%BB%8E%20systemd%20%E8%BF%90%E8%A1%8C%20bash%20%E8%84%9A%E6%9C%AC.png)
我有一个以 Bash 脚本形式实现的服务。它内部实际上是一个 node.js 应用程序,但就这个问题而言,它可以是任何东西。
基本用例是我们在交互式 shell 中开发/调试脚本,然后将其作为服务启用。
如果我通过 ssh 连接到我的设备(登录),我的整个环境就在那里,我可以在命令行启动我的脚本,没有问题。我所在的 shell 已从 、 等处获取正确的环境,.bashrc
一切.profile
正常。
但是如果我从 systemd 服务启动它,它source
就会像交互式 shell 一样设置环境。有一些规定可以将环境变量添加到单元,但对于我在这里所做的,这只是重复了我的交互式环境所做的工作,并且很容易忘记某些事情。
对于真正的生产服务,我确信有正确的方法来做到这一点,但这是一个实验室应用程序,我需要让它变得简单,以便脚本上的任何人都不需要知道 systemd 是如何工作的。
所以问题是:我需要做什么才能让编写的脚本在交互式 Bash shell 下运行并从 systemd 运行?
我尝试使用 启动 bash --login
,但不起作用。source .bashrc
在外部脚本中明确执行 也不起作用。
下面是我为了强调这个问题而使用的一个例子:
核心脚本(job.sh
):
#!/bin/bash
cd
while [ 1 ]
do
pwd
echo USER is $USER
echo PATH is $PATH
which node
node --version
sleep 1
done
我从另一个脚本调用它(wrapper.sh
):
#!/bin/bash
echo starting wrapper...
bash --login /home/droid/job.sh
这是我的job.service
单位/etc/systemd/system/job.service
:
[Unit]
Description=Job Daemon
[Service]
User=droid
ExecStart=/home/droid/wrapper.sh
[Install]
WantedBy=multi-user.target
我对 systemd 有哪些不理解之处,导致我无法让它正常工作?
答案1
通过运行脚本和直接运行脚本的区别systemd
在于环境。你可以像这样测试它。在你的 Unit 文件中,将其添加到 [Service] 部分,以进行测试:
StandardOutput=console
然后在你的 bash 脚本的顶部添加此行来转储环境:
env
现在在 systemd 内部和外部运行脚本并比较转储的环境变量。
systemd 的一个特性就是可以严格控制环境。这既提高了安全性,又提供了一致性。
您可以在以下位置阅读有关 systemd 如何管理环境的更多信息systemd.exec。
一旦按照 systemd 的意愿运行,通过 CLI 和系统运行相同程序就很容易了。通过 CLI 运行它,如下所示:
systemctl start your-unit-name
然后 systemd 将在完全相同的环境下运行。
您要求的是相反的:让 systemd 使用您的“bash”环境运行服务。但这是一个混乱、不断变化的环境,可能会导致不一致的结果。相比之下,systemd 运行时环境受到严格控制,可产生一致、可重现的结果。这就是为什么应该彻底改变这个问题,并询问如何使用 systemd 使用的相同、一致、受控的执行环境在 CLI 上运行您的服务。
答案2
而.profile
,则被读取任何shell 的登录实例,.bashrc
明确仅供以下人员使用:交互的非登录 shell。事实上,根据你的发行版,默认的.bashrc
顶部可能有这样的内容,以便额外的确保文件仅由交互式 shell 处理:
# If not running interactively, don't do anything
case $- in
*i*) ;;
*) return;;
esac
这可能就是为什么手动采购.bashrc
不起作用的原因。
您可以通过指定并确保在而不是--login
中设置所需的环境变量来使其工作。不过,更好的办法可能是专门为该服务创建一个单独的环境变量文件,并确保该文件既来自 systemd 服务,又来自手动运行它。.profile
.bashrc