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