最初我在 Ubuntu 上运行了这个脚本,基本上是放入 rc.local 中
#!/bin/bash
IBSYSDIR="/home/matthewh/tmp"
hca_id=1
if [ -d ${IBSYSDIR} ]; then
for hca in ${IBSYSDIR}/*; do
if [ -e ${hca}/node_desc ]; then
echo -n "$(hostname -s) HCA-${hca_id}" >> ${hca}/node_desc
fi
hca_id=$((hca_id+1))
done
fi
现在我的基础设施是 CoreOS,我想恢复此脚本来设置所有节点的 Infiniband 主机名。
理想情况下,为了节省管理开销,我只想将单个服务文件放入 cloud-init 一次并启动它。所以我想出了下面显示的 systemd 服务文件。在想出单个文件奇迹的过程中,我设法将原始文件脚本中的命令缩短为一行。
[ -d ${IBSYSDIR} ] && for hca in ${IBSYSDIR}/*; do [ -e ${hca}/node_desc ] && echo -n "$(hostname -s) HCA-${hca_id}" >> ${hca}/node_desc; done
然而,我似乎无法运行/bin/sh -c "[ -d ${IBSYSDIR} ] && for hca in ${IBSYSDIR}/*; do [ -e ${hca}/node_desc ] && echo -n "$(hostname -s) HCA-${hca_id}" >> ${hca}/node_desc; done"
也许它没有正确地将环境拉入 sh。如何让它仅在单个服务文件(没有其他依赖脚本)内工作?
服务文件和实际错误如下。
[Unit]
Description=Set the infiniband hostname
[Service]
Type=oneshot
Environment="IBSYSDIR=/sys/class/infiniband"
Environment="hca_id=1"
ExecStart=/bin/bash -c "[ -d ${IBSYSDIR} ] && for hca in ${IBSYSDIR}/*; do [ -e ${hca}/node_desc ] && echo -n "$(hostname -s) HCA-${hca_id}" >> ${hca}/node_desc; done"
[Install]
WantedBy=multi-user.target
我看到的实际错误:
Sep 10 00:30:21 service2-2 systemd[1]: Starting Set the infiniband hostname...
Sep 10 00:30:21 service2-2 sh[11134]: -s): -c: line 0: unexpected EOF while looking for matching `)'
Sep 10 00:30:21 service2-2 sh[11134]: -s): -c: line 1: syntax error: unexpected end of file
所以我做了一些进一步的努力,但仍然不起作用。
[Unit]
Description=Set the infiniband hostname
After=docker.service
Requires=docker.service
[Service]
Type=oneshot
ExecStart=/bin/bash -c 'IBSYSDIR=/sys/class/infiniband && hca_id=1 && [ -d ${IBSYSDIR} ] && for hca in ${IBSYSDIR}/*; do [ -e ${hca}/node_desc ] && echo -n "$(hostname -s) HCA-${hca_id}" >> "${hca}/node_desc"; done'
[Install]
WantedBy=multi-user.target
但如果我直接运行
sudo /bin/bash -c 'IBSYSDIR=/sys/class/infiniband && hca_id=1 && [ -d ${IBSYSDIR} ] && for hca in ${IBSYSDIR}/*; do [ -e ${hca}/node_desc ] && echo -n "$(hostname -s) HCA-${hca_id}" >> "${hca}/node_desc"; done'
它确实有效。服务文件有什么特别之处?返回的错误代码是 1。我猜这是权限被拒绝的错误或其他什么。
答案1
$
将所有 改为$$
。
来自 systemd.unit 文档:
要传递文字美元符号,请使用“$$”。在扩展时未知值的变量将被视为空字符串。请注意,第一个参数(即要执行的程序)可能不是变量。
答案2
根据我的经验,systemd 不喜欢在其ExecStart
指令中包含复杂的命令。
尝试将您的脚本放入包装文件中并从中运行该脚本ExecStart
。