У меня есть простой баш-скрипт, который использует утилиту 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 > "$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 сервиса файлы результатов нулевые и как это можно исправить?
Проблема с тем, что ваш скрипт не создает корректные файлы результатов, когда он запускается как сервис 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
Обратите внимание, что пишу я в файл в своём домашнем каталоге и запускаю от своего пользователя.
И никаких проблем с тем, что это баш скрипт, не было.