Назад | Перейти на главную страницу

Почему этот файл модуля systemd не работает?

Первоначально у меня был этот скрипт, работающий на 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.