Запустить скрипт на локальном (например, на домашнем) компьютере – весьма просто. А вот как это сделать на удаленном компьютере, т.е. на сервере?
Запуск программы, написанной на языке С, на сервере, можно выполнить либо из консоли (по протоколу SSH), либо путем вызова выполнения системной команды (например, из PHP).
Понятно, что в автоматическом режиме его можно запустить, используя автоматический планировщик Cron. А вот как быть, если требуется запустить вручную (например, для окончательной отладки программы)? Об этом пойдет речь в нашей статье. Статья написана, скорее, для новичков. Что такое серверный скрипт, для чего он бывает необходим при работе сайта, объяснять не буду.
В самом деле, любой мало-мальски функциональный сайт нуждается в автоматизированном выполнении тех или иных операций. Подавляющее большинство серверных (т.е. таких, которые выполняются на стороне сервера) скриптов пишут, например, на PHP, на Perl (ну, и плюс та или иная СУБД, если, конечно, в ней есть необходимость).
Как установить программу на сервер? Круглосуточная работа программ на серверах vds/vps.
РНР используется, если скрипты выполняют относительно небольшой объем работы, т.е. их целесообразно использовать там, где производительность (быстродействие) не является критичным. По сути, имея синтаксис и особенности, во многом сходные с языком С (Си), PHP во многом напоминает не что иное, как VBA от Microsoft.
Практически та же самая идеология и, соответственно, примерно аналогичное быстродействие. На наш взгляд, PHP может применяться в основном для создания вспомогательных, не слишком часто запускаемых скриптов, которые, в идеале, запускаются не при первой загрузке страницы сайта. Например, для организации интерфейса, передачи данных с открытой страницы на сервер, ну, или т.п.
Скрипты на Perl обладают более высоким быстродействием, но, в отличие от РНР, Perl заметно сложнее, его код менее читаем. Правда, и возможностей у него побольше, чем у PHP.
Однако, если требуется быстрая загрузка сайта (а кто сомневается в актуальности этого), быстрое выполнение скриптов (например, производящие сложные математические вычисления, применяемые, в том числе, в онлайновых играх), то целесообразнее написать их на более производительном языке, например, на С (или С++), но не спутайте его с С#, который и по идеологии, и по быстродействию недалеко ушел от VBA. Да, на С++ (чистый С еще быстрее), а то и на Ассемблере.
Кому-то может показаться, что написание серверных скриптов на С является анахронизмом. Однако, это не так. На самом деле, язык С дает примерно те же возможности, да и синтаксис, в целом, схож с РНР. Правда, серверные скрипты, написанные на С, являются, конечно, более объемными по сравнению с теми, что выполнены на РНР.
Потом, в С можно столкнуться с довольно серьезной проблемой, связанной с кириллической кодировкой. В PHP она решается, можно сказать, автоматически, а в С – придется все программировать вручную. Но, повторимся, выигрыш в быстродействии – того стоит.
Как запустить на сервере программу, написанную на С (Си)?
- ps — выводить список запущенных процессов
- jobs — альтернативный путь для просмотра процессов запущенных Вами
- ls – просмотр текущего каталога
- bg — ставит выполнение процесса в фоновый режим
- fg — выводит выполнение процесса из фонового режима
- kill — отправляет сигнал на один или несколько процессов (в основном, чтобы «убить» их)
Вот, к примеру, результат, который выводит команда ps :
Удаленный рабочий стол на Windows VDS (VPS сервер). Как запускать программы и решать задачи 24/7
PID TTY TIME CMD
7318 pts/2 00:00:00 bash
20543 pts/2 00:00:00 ps
28314 pts/2 00:00:00 bash
28315 pts/2 00:00:00 logger
Кстати, команда kill имеет опции, выражаемые целым числом. Среди них имеют значение 1, 2, 15, 9. Последняя – вызывает принудительное, наиболее сильное (или грубое) завершение программы, причем игнорировать его она не сможет. Так, если Вы наберете
то должна выгрузиться оболочка bash (правда, скорее всего, она будет тут же автоматически загружена вновь, но уже с другим идентификатором).
Загрузим имеющуюся на сервере программу, написанную нами на С. Например, это будет program. Так как она предназначена для прослушивания определенного логического порта (под номером, к примеру, 5425, с использованием технологии сокетов), то, пока на этот порт не придет сообщение, она ничего выполнять не будет, просто находясь в состоянии ошижидания. Поэтому загрузим ее в фоновом режиме, чтобы она не мешала работать с оболочкой дальше. При этом:
-bash-4.1$ ./program сервер» включает в себя два смысла (значения): во-первых, это программа, которая управляет работой хостинга, позволяет пользователям открывать страницы сайтов, расположенных на нем. Во-вторых, сервер — это компьютер, на котором расположена и работает программа-сервер. Для сервера наша программа ( program ) представляет собой лишь одну из программ, которая может быть запущена пользователем (нами, к примеру), не более того.
Примечание 3 . Программа названа мини-сервером, так как, после ее запуска, она открывает для прослушивания определенный порт и может взаимодействовать с любым соответствующим клиентом, посылающим запрос на хостинг на этот порт.
Так как порт под номером 5425 занят, то, соответственно, команда bind во второй раз сработать не может, вызывая указанную ошибку.
Так вот, кстати, если теперь прекратить сеанс работы, то program останется загруженной в оперативную память сервера. А если еще ее спроектировать так, чтобы она каждый раз генерировала все новые и новые значения портов – то в итоге можно запустить сколько угодно копий указанной программы… и потом получить замечание от хостера. Что нам, конечно, совсем ни к чему.
Поэтому – выгрузим программу из оперативной памяти:
Система даст сообщение:
[1]+ Killed ./program
Проверка при помощи команды ps показывает, что все, процесса с названием программ больше нет:
PID TTY TIME CMD
2382 pts/2 00:00:00 bash
2383 pts/2 00:00:00 logger
5848 pts/2 00:00:00 ps
28478 pts/2 00:00:00 bash
Но, может статься, что порт (под номером 5425) все же не освободится. Вообще, при передаче данных на основе сокетов (используется протокол TCP) система резервирует порт даже в случае, если программа прекратила выполняться. Это делается для того, чтобы при неожиданных обрывах связи (что может создавать — для компьютера, который посылает сообщения нашей программе — видимость прекращения ее выполнения) сохранить на некоторое время работоспособным используемый порт – в расчете, если связь восстановится и/или программа опять заработает. Т.е. таким образом, предусмотрена как бы подстраховка от некорректного завершения работы программы.
Кроме того, порт, скорее всего, не освободится в том случае, если работа программы будет завершена некорректно.
Это означает, что вновь, до момента освобождения порта, программа может не заработать – порт-то занят.
Поэтому после окончания работы с нею желательно проверить, каким сервисом открыты соединения на данному порту, при помощи следующей команды:
netstat -tnlp | grep 5425
Вот что сообщит система:
tcp 0 0 0.0.0.0:5425 0.0.0.0:* LISTEN 21015/./program
Так вот, в данном случае указанный порт действительно занят нашей программой, повторимся, даже несмотря на то, что она, вроде бы, выгружена из памяти.
Для очистки порта (т.е. для удаления его из системы) можно набрать
Произойдет «жесткое» удаление программы из оперативной памяти, в том числе и всех созданных ею объектов, т.е. логических портов.
Вот теперь, как закончили работу, можно закрыть сеанс соединения. Для этого набираем команду
Сеанс должен закрыться:
logout Connection to closed.
Таким образом, как видите, ручной запуск скрипта на удаленном сервере не представляет особого труда.
Источник: www.dissertacii-diplom-ufa.ru
Несколько советов по организации Python-приложения на сервере
В этой статье я хочу поделиться несколькими удобными способами организации вашего проекта на рабочем (даже продакшен) сервере.
Я работаю, в основном, с Python/Django стеком, поэтому все примеры будут, в первую очередь, применительно к этому набору. Также ключевые технологии: Ubuntu (17.10), Python3 (3.6).
Предполагается что вы делаете все грамотно, приложение хранится в репозитории, деплоится в отдельную папку на сервере, используется, например, virtualenv. Для запуска используется отдельно созданный юзер, который имеет достаточно прав, но не слишком много (например не имеет sudo и не разрешен логин по ssh).
Для начала я повторю прописные истины, что все что хранится в репозитории — это только чистый код и статичные данные. Все настройки содержат только дефолты, никаких паролей и ключей, даже в неиспользуемых файлах.
Даже на рабочем компьютере (ноутбуке) где вы пишете код у вас в папке проекта не должно быть ничего что бы вы не могли закачать на продакшен. Имеется в виду порочная практика использования файлика «local_settings.py» в папке settings внутри проекта (как вариант — development_settings.py). Я разберу этот пример ниже.
Логи
Наверняка вы используете логирование. Встроенный модуль logging очень хорош, но не всегда стоит изощряться и использовать его для всего на свете.
Например, ротация логов. В интернете попадаются сложные и изощренные способы начиная от стандартного RotatingFileHandler и заканчивая написанием собственного демона на сокетах для записи логов из нескольких источников. Проблемы начинаются из-за желания делать все на «чистом Python». Это глупо и неэффективно, зато приносит кучу возможных мест возникновения ошибок.
Используйте сервис logrotate. Ниже приводится простой конфиг для логов celery.
Стандартными средствами пишем файлик /var/log/myproject/celery.log, ежедневно он кладется в папку /var/log/myproject/archive/ и к имени добавляется суффикс предыдущего дня.
/var/log/myproject/celery.log < size 1 su myuser myuser copytruncate create rotate 10 missingok postrotate timeext=`date -d ‘1 day ago’ «+%Y-%m-%d»` # daily # timeext=$(date +%Y-%m-%d_%H) # hourly mv /var/log/myproject/celery.log.1 /var/log/myproject/archive/celery_$timeext.log endscript >
Если у вас лог пишется очень быстро и вы хотите его ротировать каждый час, то в конфиге перекомментируйте строчки «daily» и «hourly». Также нужно настроить logrotate чтобы он запускался каждый час (по умолчанию обычно ежедневно). Выполните в bash:
sudo cp /etc/cron.daily/logrotate /etc/cron.hourly/logrotate sudo sed -i -r «s/^[[:digit:]]*( .+cron.hourly)/01/» /etc/crontab
Конфиг (файлик myservice) надо положить в папку logrotate
sudo cp config/logrotate/myservice /etc/logrotate.d/myservice
- конфиг надо именно скопировать, симлинки работать не будут
- в принципе, конфиг почти взят из доки по logrotate, но очень важно поставить copytruncate директиву
- (добавлено из комментария rusnasonov ) logrotate туповат и использует простейшую систему ротирования, без буферов. Ротирование проходит в два шага — сначала копируется старый файл, а потом он обрезается на старом месте. Это может привести к потере логов, которые были записаны в промежутке (отражено в документации)
copytruncate важна по той причине, что при ротировании файл не будет закрыт. Поскольку мы ротируем файл на «живой» системе, файл открыт и сервисы, которые в него пишут, делают это по какому-то файловому дескриптору. Если вы просто переместите файл и создадите новый пустой, то он не будет использоваться. copytruncate говорит что нужно скопировать содержимое, а потом очистить файл, но не закрывать.
Сервисы
Как вы запускаете ваше приложение? Есть куча разных способов. По моим наблюдения основные такие:
- запускаем screen/tmux и внутри запускаем в интерактивном режиме скрипт
- режим демона типа «-D» для gunicorn или celery
- supervisord
- init.d скрипт
- Docker
Все они имеют свои плюсы, но, на мой взгляд, они имеют еще больше минусов.
Я не буду здесь рассматривать Docker. Во-первых, у меня не так много опыта работы с ним. А во-вторых, если вы используете контейнеры, то вам и остальные советы из этой статьи не очень нужны. Там подход уже другой.
Я считаю, что если система предоставляет нам удобный инструмент, то почему бы им не воспользоваться.
В Ubuntu начиная с версии 15.04 по-умолчанию поставляется systemd для управления сервисами (и не только).
systemd очень удобен тем, что самостоятельно делает все правильно:
- запускает приложение под нужным пользователем и устанавливает переменные окружения, если нужно
- при внезапной остановке приложения — перезапускает его заданное количество раз
- очень гибок и позволяет настроить зависимости и порядок запуска
Конечно, если у вас нет systemd, то можно смотреть в сторону supervisord, но у меня довольно большая нелюбовь к этому инструменту и я избегаю его использовать.
Я надеюсь не будет людей, кто будет сомневаться что при наличии systemd использовать supervisord вредно.
Ниже я приведу пример конфига для запуска.
Запуск gunicorn (проксируется через локальный nginx, но это здесь неважно).
[Unit] Description=My Web service Documentation= StartLimitIntervalSec=11 [Service] Type=simple Environment=DJANGO_SETTINGS_MODULE=myservice.settings.production ExecStart=/opt/venv/bin/python3 -W ignore /opt/venv/bin/gunicorn -c /opt/myservice/config/gunicorn/gunicorn.conf.py —chdir /opt/myservice myservice.wsgi:application Restart=always RestartSec=2 StartLimitBurst=5 User=myuser Group=myuser ExecStop=/bin/kill -s TERM $MAINPID WorkingDirectory=/opt/myservice ReadWriteDirectories=/opt/myservice [Install] WantedBy=multi-user.target Alias=my-web.service
Здесь важно не использовать режим демонизации. Мы запускаем gunicorn обычным процессом, а демонизирует его сам systemd, он же и следит за перезапуском при падениях.
Обратите внимание, что мы используем путь к python и gunicorn относительно virtualenv-папки.
Для celery все будет таким же, но строку запуска я рекомендую такой (пути и значения поставьте свои):
ExecStart=/opt/venv/bin/celery worker -A myservice.settings.celery_settings -Ofair —concurrency=3 —queues=celery —logfile=/var/log/myservice/celery.log —max-tasks-per-child 1 —pidfile=/tmp/celery_myservice.pid -n main.%h -l INFO -B
Стоит обратить внимание на параметры для перезапуска:
StartLimitIntervalSec=11 RestartSec=2 StartLimitBurst=5
Вкратце это означает следующее: если сервис упал, то запусти его снова через 2 секунды, но не больше 5 раз за 11 секунд. Важно понимать, что если значение в StartLimitIntervalSec будет, например, 9 секунд, то в случае если сервис остановится 5 раз подряд (сразу после запуска), то после пятого падения systemd сдастся и не будет его больше поднимать (2 * 5). Значение 11 выбрано именно с тем, чтобы исключить такой вариает. Если, например, у вас был сетевой сбой на 15 секунд и приложение падает сразу после старта (без таймаута), то пусть уж лучше оно долбит до победного, чем просто останавливается.
Чтобы установить этот конфиг в систему, можно просто сделать симлинк из рабочей папки:
~~sudo ln -s /opt/myservice/config/systemd/*.service /etc/systemd/system/~~ sudo systemctl daemon-reload
Однако, с симлинками надо быть осторожными — если у вас проект лежит не на системном диске, то есть вероятность что он может монтироваться после старта сервисов (например, сетевой диск или memory-mapped). В этом случае он просто не запустится. Здесь вам придется гуглить как правильно настроить зависимости, да и вообще конфиг тогда лучше скопировать в папку systemd.
Update: после замечания andreymal я думаю что будет правильнее копировать конфиги в папку и ставить им правильные права:
sudo chown root: /opt/myservice/config/systemd/*.service sudo chmod 770 /opt/myservice/config/systemd/*.service sudo cp /opt/myservice/config/systemd/*.service /etc/systemd/system/ sudo systemctl daemon-reload
Еще советую отключить вывод в консоль, иначе все будет попадать в syslog.
Когда у вас все компоненты заведены в systemd, то использование каждого из них сводится к:
sudo systemctl stop my-web.service sudo systemctl stop my-celery.service sudo systemctl start my-web.service sudo systemctl start my-celery.service
Когда компонентов больше одного, то имеет смысл написать скрипт для массового управления всем хозяйством на сервере.
bash manage.sh migrate bash manage.sh start
Для удаленной отладки через консоль (запустит shell_plus из django-extensions):
bash manage.sh debug
Если у вас больше одного сервера, то, конечно, вы используете уже свои скрипты для разворачивания, это просто пример.
Локальные настройки
Это тема для холивара и я хочу заметить, что этот параграф — исключительно моя точка зрения, которая базируется на моем опыте. Делайте как хотите, я просто советую.
Суть проблемы в том, что как ни пиши приложение, ему, скорее всего, придется иметь дело с данными, которые где-то хранятся. Список юзеров, путь к ключам, пароли, путь к базе, и тп… Все эти настройки хранить в репозитории нельзя. Кто-то хранит, но это порочная практика. Небезопасно и негибко.
Какие есть самые частые способы хранения таких настроек и какие проблемы с ними:
- файлик local_settings.py, который хранится в папке проекта рядом с дефолтными setting.py
Проблема: можно случайно закоммитить файл, можно его затереть при копировании/обновлении папки (rsync или из архива) - переменные окружения. Тоже не очень безопасно, не очень удобно (при soft-reload например)
- отдельный файл вне папки проекта
Я рекомендую именно этот способ. Обычно я для проекта создаю yaml-файл в папке «/usr/local/etc/». У меня написан небольшой модуль, который используя магию хаки загружает переменные из файлика в locals() или globals() импортирующего модуля.
Используется очень просто. Где-то в глубинах settings.py для Django (лучше ближе к концу) достаточно вызвать:
import_settings(«/usr/local/etc/myservice.yaml»)
И все содержимое будет замешано в глобальные settings. У меня используется merge для списков и словарей, это может быть не всем удобно. Важно помнить, что Django импортирует только UPPERCASE константы, то есть в файлике настройки первого уровня у вас сразу должны быть в верхнем регистре.
That’s all folks!
Остальное обсудим в комментариях.
Источник: habr.com
Запуск Flask приложения на Linux сервере
Эта статья для тех, кто хочет запустить сайт или API на Flask на своём сервере и сделать его доступным из интернета. Если Вы просто делаете заглушку для теста, или локальный веб сайт эти шаги, возможно, избыточны.
- «Настройка Flask на хостинге»
- Перенос сайта c виртуального хостинга на VPS с помощью LAMP
Введение
Первый деплой проекта на реальном сервере это всегда вызов.
Может появиться огромное количество трудностей, о которых обучающийся программированию даже не догадывался.
Часто нужно навыки очень далёкие от того чему можно было научиться на уроках по синтаксису языка или какому-то фреймворку.
Нужно запастить терпением и быть готовым много читать, искать, спрашивать и проверять.