Почему скрипт не запускается с помощью systemctl?

У меня есть простой баш-скрипт, который использует утилиту mtr для отправки 5 пакетов на адрес 8.8.8.8 и сохраняет результаты в файл. Затем он повторяет этот процесс каждые 20 секунд. 

При ручном запуске скрипт работает корректно, однако, когда я пытаюсь запустить его как сервис systemd, файлы результатов оказываются нулевого размера. 

Вот сам скрипт: <br/> <br/> 
<pre><code class="bash">#!/bin/bash

# Указываем IP-адрес назначения
DESTINATION="8.8.8.8"

# Количество пакетов
PACKETS=5

# Бесконечный цикл
while true; do
    # Генерация уникального имени файла
    OUTPUT_FILE="/home/mtr_results_$(date +%Y-%m-%d_%H:%M:%S).log"

    # Выполняем команду mtr и сохраняем результат в файл
    mtr -r -c $PACKETS $DESTINATION &gt; "$OUTPUT_FILE"

    echo "Отчет сформирован и сохранен в файл $OUTPUT_FILE."

    # Пауза между итерациями
    sleep 20
done</code></pre> <br/> <br/> 
А вот конфигурация моего systemd сервиса: <br/> <br/> 
<pre><code>[Unit]
Description=MTR Monitoring Service
After=network.target

[Service]
ExecStart=/home/mtr.sh

[Install]
WantedBy=multi-user.target</code></pre> <br/> <br/> 
Я выдал права на скрипт с помощью <code>chmod +x /home/mtr.sh</code> и запустил следующие команды: 
<code>systemctl daemon-reload</code> <br/> 
<code>systemctl enable mtr.service</code> <br/> 
<code>systemctl start mtr.service</code> <br/> 
Проверяя статус сервиса, я вижу следующее: 
<pre><code>[root@CENTOS7_TEST_MACHINE home]# systemctl status mtr
● mtr.service - MTR Monitoring Service
   Loaded: loaded (/etc/systemd/system/mtr.service; enabled; vendor preset: disabled)
   Active: active (running) since Wed 2024-12-25 09:46:25 MSK; 12min ago
 Main PID: 1466 (mtr.sh)
   CGroup: /system.slice/mtr.service
           ├─1466 /bin/bash /home/mtr.sh
           └─2145 mtr -r -c 5 8.8.8.8

Dec 25 09:53:24 CENTOS7_TEST_MACHINE mtr.sh[1466]: Отчет сформирован и сохранен в файл /home/mtr_results_2024-12-25_09:53:12.lo</code></pre> 

Почему при запуске скрипта как systemd сервиса файлы результатов нулевые и как это можно исправить?
  • 25 декабря 2024 г. 7:03
Ответы на вопрос 3
Проблема с тем, что ваш скрипт не создает корректные файлы результатов, когда он запускается как сервис systemd, может быть связана с несколькими факторами, такими как права доступа и окружение.

Вот несколько шагов, которые помогут вам решить эту проблему:

1. **Путь к файлу и права доступа**: Убедитесь, что пользователь, от имени которого запускается ваш сервис, имеет права на запись в директорию `/home`. Сервисы systemd часто запускаются не от имени пользовательского аккаунта, а от имени пользователя `root` или другого системного пользователя, который может не иметь прав на запись в указанную папку. Попробуйте изменить путь к файлу на что-то вроде `/var/log/mtr_results.log` и проверьте права на запись в этой директории.

2. **Использование полного пути к утилите mtr**: Убедитесь, что в вашем скрипте вы используете полный путь к утилите `mtr`. Для этого, выполните команду `which mtr`, чтобы найти полный путь (например, `/usr/bin/mtr`) и измените строку в скрипте:
   ```bash
   /usr/bin/mtr -r -c $PACKETS $DESTINATION > "$OUTPUT_FILE"
   ```

3. **Окружение и переменные окружения**: Когда вы запускаете скрипт через systemd, окружение может отличаться от вашего терминала. Часто переменные окружения (такие как путь к `PATH`) могут быть неполными. Чтобы предостеречься от проблем, вы можете добавить в ваш скрипт строки, которые явно записывают нужные переменные окружения.

4. **Логирование ошибок**: Добавьте перенаправление ошибок в ваш скрипт, чтобы записывать ошибки, возникающие при выполнении команды `mtr`. Это поможет вам понять, что может идти не так:
   ```bash
   /usr/bin/mtr -r -c $PACKETS $DESTINATION > "$OUTPUT_FILE" 2>> /home/mtr_errors.log
   ```

5. **Очистка старых файлов**: Иногда старые лог-файлы могут вызывать путаницу. Убедитесь, что вы не переписываете старые файлы или не сталкиваетесь с проблемами доступа к ним.

6. **Dependencies**: Убедитесь, что зависимости, необходимые для выполнения `mtr`, доступны и корректно импортированы, когда вы этот сервис запускаете.

Пример исправленного скрипта может выглядеть следующим образом:

```bash
#!/bin/bash

# Указываем IP-адрес назначения
DESTINATION="8.8.8.8"

# Количество пакетов
PACKETS=5

# Бесконечный цикл
while true; do
    # Генерация уникального имени файла
    OUTPUT_FILE="/var/log/mtr_results_$(date +%Y-%m-%d_%H:%M:%S).log"

    # Выполняем команду mtr и сохраняем результат в файл
    /usr/bin/mtr -r -c $PACKETS $DESTINATION > "$OUTPUT_FILE" 2>> /var/log/mtr_errors.log

    echo "Отчет сформирован и сохранен в файл $OUTPUT_FILE."

    # Пауза между итерациями
    sleep 20
done
```

После внесения изменений, не забудьте перезагрузить демона systemd с помощью `systemctl daemon-reload` и перезапустить сервис `systemctl restart mtr.service`.
системд не использует интерпретатор командной строки, потому запись ExecStart=/home/mtr.sh не правильна в корне. ты пытаешься исполнить баше-скрипт, а системд не подставляет баш в качестве дефолтного исполнителя. 

говоря проще, первым параметром ExecStart должон быть бинарный исполняемый файл.
ExecStart=/bin/bash /home/mtr.sh
Возможно, файл юнита слишком куцый, и с правами на файлы что-то не то? 
Вот такой вариант у меня сработал:
test.sh:
#!/bin/bash

while true; do
    date +%Y-%m-%d_%H:%M:%S >> /home/myuser/test.log
    sleep 20
done

Юнит:
[Unit]
Description=kaBOOM
After=network.target
StartLimitIntervalSec=1

[Service]
Type=simple
Restart=always
RestartSec=5
User=myuser
ExecStart=/home/myuser/test.sh

[Install]
WantedBy=multi-user.target


Обратите внимание, что пишу я в файл в своём домашнем каталоге и запускаю от своего пользователя.
И никаких проблем с тем, что это баш скрипт, не было.
Похожие вопросы