在我的组织中,我们有许多用于不同服务(例如 ECS 和 Docker)的简单易用的基础 AMI。由于我们的许多项目都涉及 CloudFormation,因此我们正在使用cfn-bootstrap
,它由几个脚本和一个在启动时运行的服务组成,用于安装某些包并为我们执行某些配置管理任务。
在系统启动时,必须执行以下脚本的等效项:
#!/bin/bash
# capture stderr only
output="$(cfn-init -s $STACK_NAME -r $RESOURCE_NAME --region $REGION >/dev/null)"
# if it failed, signal to CloudFormation that it failed and include a reason
returncode=$?
if [[ $returncode == 0]]; then
cfn-signal -e $returncode -r "$output"
exit $returncode
fi
# otherwise, signal success
cfn-signal -s
我正在考虑将其作为运行和运行的 systemdoneshot
服务运行。After=network.target
WantedBy=multi-user.target
唯一的问题是我希望我的 AMI 灵活,并且仅在存在某个文件时才执行此操作。除了将上述脚本嵌入到 EC2 用户数据中,我还可以让用户数据只定义一个环境文件,该文件定义了我需要的变量,并且仅在该环境文件存在时才运行我的一次性服务:
#cloud-init
write_files:
- path: /etc/sysconfig/cloudformation
# ...
content: |
CFN_STACK_NAME="stack-name"
CFN_RESOURCE="resource-name"
CFN_REGION="region"
有没有办法让 systemd 仅在满足给定条件时才运行服务?
systemd 提供了多种可以测试的条件。例如,您可以使用它
ConditionPathExists=
来测试文件是否存在。我偶然发现了这个问题,寻找使用条件启动 systemd 服务的方法。有很多方法:
ConditionArchitecture=, ConditionVirtualization=, ConditionHost=, ConditionKernelCommandLine=, ConditionSecurity=, ConditionCapability=, ConditionACPower=, ConditionNeedsUpdate=, ConditionFirstBoot=, ConditionPathExists=, ConditionPathExistsGlob=, ConditionPathIsDirectory=, ConditionPathIsSymbolicLink=, ConditionPathIsMountPoint=, ConditionPathIsReadWrite=, ConditionDirectoryNotEmpty=, ConditionFileNotEmpty=, ConditionFileIsExecutable=
我想根据特定的主机名启动服务。
ConditionHost
= 可用于匹配主机的主机名或机器 ID。这要么接受一个主机名字符串(可选地使用 shell 样式 glob),它针对由 gethostname(2) 返回的本地设置的主机名进行测试,要么接受一个格式化为字符串的机器 ID(参见 machine-id(5))。可以通过在前面加上感叹号来否定测试。更多关于这里。