我有一个服务作为bash脚本实现。 里面实际上是一个节点应用程序,但是对于这个问题,它可能是任何东西。
基本用例是我们在交互式shell中开发/debugging脚本,然后将其作为服务启用。
如果我ssh到我的设备(login)我的整个环境在那里,我可以在命令行启动我的脚本,没有问题。 我所在的shell已经从.bashrc,.profile等中选取了合适的环境,并且一切正常。
但是,如果我从一个systemd服务启动它,它会像交互式shell一样获得环境。 有条款给环境variables添加环境variables,但是我在这里所做的只是重复了我的交互环境所做的事情,并成为一种简单的方法来忘记一些事情。
对于一个真正的生产服务,我确信有一个正确的方法来做到这一点,但这是一个实验室应用程序,我需要简化,所以没有人在脚本上工作需要知道系统如何工作。
所以问题是:我需要做什么才能让脚本写在交互式bash shell下运行,从systemd运行?
我试图用–login启动bash,但是这不起作用。 也不在外部脚本中明确地执行源.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
这里是我在/etc/systemd/system/job.service中的job.service单元:
[Unit] Description=Job Daemon [Service] User=droid ExecStart=/home/droid/wrapper.sh [Install] WantedBy=multi-user.target
我对systemd有什么不了解,这让我无法正常工作?
通过systemd运行脚本并直接运行脚本的区别在于环境。 你可以像这样testing它。 在您的单元文件中,将其添加到[Service]部分以进行testing:
StandardOutput=console
然后在你的bash脚本中,在顶部添加这一行来转储环境:
env
现在在systemd内部和外部运行脚本并比较转储的环境variables。
systemd的一个特点是严格控制环境。 这既提高了安全性又提供了一致性。
您可以阅读systemd.exec中 systemd如何pipe理环境的更多信息 。
一旦你从systemd运行你想要的东西,通过CLI和系统运行相同的东西很容易。 像这样通过CLI运行它:
systemctl start your-unit-name
然后systemd将运行在完全相同的环境。
你问的是相反的:让systemd使用你的“bash”环境运行服务。 但是,这是一个混乱,变化的环境,可能导致不一致的结果。 相比之下,系统运行时环境则受到严格的控制,产生一致的,可重现的结果。 这就是为什么应该把问题从内部转移出来,并使用systemd使用的相同,一致,受控的执行环境,询问如何在CLI上使用您的服务。