Ответ 1
Я закончил с upstart, который отлично работает.
У меня есть node.js script, который нужно запускать при загрузке и запускаться под пользователем www-data. Во время разработки я всегда начинал script с:
su www-data -c 'node /var/www/php-jobs/manager.js
Я понял, что произошло, теперь менеджер manager.js отлично работает. Поиск Итак, я нашел, что должен был разместить это в моем /etc/rc.local
. Кроме того, я научился указывать вывод в файл журнала и добавлять 2>&1
к "перенаправлять stderr в stdout", и он должен быть демоном, поэтому последний символ - &
.
Наконец, мой /etc/rc.local
выглядит следующим образом:
#!/bin/sh -e
#
# rc.local
#
# This script is executed at the end of each multiuser runlevel.
# Make sure that the script will "exit 0" on success or any other
# value on error.
#
# In order to enable or disable this script just change the execution
# bits.
#
# By default this script does nothing.
su www-data -c 'node /var/www/php-jobs/manager.js >> /var/log/php-jobs.log 2>&1 &'
exit 0
Если я запустил это сам (sudo /etc/rc.local
): да, это работает! Однако, если я выполняю перезагрузку, процесс node
запущен, /var/log/php-jobs.log
не существует и, следовательно, manager.js не работает. Что происходит?
Я закончил с upstart, который отлично работает.
В этом примере rc.local script я использую перенаправление io в самой первой строке выполнения в свой собственный файл журнала:
#!/bin/sh -e
#
# rc.local
#
# This script is executed at the end of each multiuser runlevel.
# Make sure that the script will "exit 0" on success or any other
# value on error.
#
# In order to enable or disable this script just change the execution
# bits.
#
# By default this script does nothing.
exec 2> /tmp/rc.local.log # send stderr from rc.local to a log file
exec 1>&2 # send stdout to the same log file
set -x # tell sh to display commands before execution
/opt/stuff/somefancy.error.script.sh
exit 0
В некоторых Linux (Centos и RH, например), /etc/rc.local
изначально представляет собой символическую ссылку на /etc/rc.d/rc.local
. В этих системах, если символическая ссылка сломана, а /etc/rc.local
- отдельный файл, изменения в /etc/rc.local
не будут отображаться при загрузке - процесс загрузки запустит версию в /etc/rc.d
. (Они будут работать, если вы запускаете /etc/rc.local
вручную, но не запускаетесь при загрузке.)
Похоже на систему dimadima, это отдельные файлы, но /etc/rc.d/rc.local
вызывает /etc/rc.local
Символическая ссылка из /etc/rc.local
в "реальную" в /etc/rc.d
может потеряться, если вы переместите rc.local
в резервный каталог и скопируйте его или создайте с нуля, не понимая оригинала в /etc
был просто символической ссылкой.
В Ubuntu я заметил, что есть 2 файла. Реальный - /etc/init.d/rc.local
; кажется, что другой /etc/rc.local
фиктивный?
Как только я изменил правильный (/etc/init.d/rc.local
), он выполнил так, как ожидалось.
Возможно, вы также запустили его, указав полный путь к node. Кроме того, если вы хотите запустить команду оболочки в качестве демона, вы должны закрыть stdin, добавив 1 < & - перед &.
если вы используете linux в облаке, тогда обычно у вас нет возможности коснуться реального оборудования руками. поэтому вы не видите интерфейс конфигурации при загрузке в первый раз и, конечно, не можете его настроить. В результате служба firstboot
всегда будет на пути rc.local
. Решение состоит в том, чтобы отключить firstboot
, выполнив:
sudo chkconfig firstboot off
если вы не знаете, почему ваш rc.local
не запускается, вы всегда можете проверить файл /etc/rc.d/rc
, потому что этот файл будет всегда запускаться и вызывать другие подсистемы (например, rc.local).
У меня была та же проблема (на CentOS 7), и я исправил ее, предоставив разрешения на выполнение для /etc/local:
chmod +x /etc/rc.local
Я получил свой script для работы, отредактировав /etc/rc.local
, а затем выпустив следующие 3 команды.
sudo mv /filename /etc/init.d/
sudo chmod +x /etc/init.d/filename
sudo update-rc.d filename defaults
Теперь script работает при загрузке.
Я использую CentOS 7.
$ cd /etc/profile.d
$ vim yourstuffs.sh
Введите следующее в файл yourstuffs.sh script.
введите то, что вы хотите здесь выполнить
export LD_LIBRARY_PATH=/usr/local/cuda-7.0/lib64:$LD_LIBRARY_PATH
Сохраните и перезагрузите ОС.
Это, скорее всего, вызвано отсутствующей или неполной переменной среды PATH.
Если вы предоставите полные абсолютные пути к вашим исполняемым файлам (su и node), он будет работать.
Я понимаю, что если вы разместите свой script на определенном уровне RUN, вы должны использовать ln -s, чтобы связать script с уровнем, на котором вы хотите работать.
Я использовал rc.local в прошлом. Но из моего опыта я узнал, что самый надежный способ запустить ваш скрипт во время загрузки системы - это использовать команду @reboot в crontab. Например:
@reboot path_to_the_start_up_script.sh
сначала сделайте скрипт исполняемым с помощью sudo chmod 755/path/of/the/file.sh
теперь добавьте скрипт в rc.local sh/path/of/the/file.sh
перед выходом 0 в rc.local, затем выполните make rc.local к исполняемому файлу с sudo chmod 755/etc/rc.local
рядом с инициализацией использования rc.local sudo/etc/init.d/rc.local start
это будет инициировать rc.local, теперь перезагрузите систему. Готово..
Я обнаружил, что, поскольку я использовал сетевую команду в моем rc.local
, иногда это не rc.local
. Я исправил это, поместив sleep 3
вверху моего скрипта. Я не знаю почему, но кажется, что когда скрипт запускается, сетевые интерфейсы не настроены должным образом или что-то в этом роде, и это просто дает некоторое время для сервера DHCP или чего-то еще. Я не совсем понимаю, но я полагаю, вы могли бы попробовать.
Ну, вы можете это сделать, но можете получить больше исключений.
Итак, если ваш script должен работать как другой пользователь, такой как www U, убедитесь, что PATH и другая среда в порядке.
sudo -u www -i/the/path/of/your/script
Пожалуйста, предпочитайте руководство sudo ~ -i [команда] Параметр -i (имитировать начальный логин) запускает оболочку, указанную в записи базы данных пароля целевого пользователя в виде логина...
rc.local
работает только при запуске. Если вы перезагрузитесь и хотите выполнить script, он должен войти в файл rc.0
, начиная с префикса K99.