Первоначально у меня был этот скрипт, работающий на 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. Я предполагаю, что это ошибка отказа в разрешении или что-то в этом роде.
Измените все $
к $$
.
Из документации systemd.unit:
Чтобы передать буквальный знак доллара, используйте «$$». Переменные, значение которых неизвестно во время раскрытия, обрабатываются как пустые строки. Обратите внимание, что первый аргумент (т.е. программа, которую нужно выполнить) не может быть переменной.
По моему опыту, systemd не любит иметь сложные команды в своем ExecStart
директивы.
Попробуйте поместить свой скрипт в файл-оболочку и запустить его из ExecStart
.