Меню Рубрики

Установка php скриптов на веб сервере

HackWare.ru

Этичный хакинг и тестирование на проникновение, информационная безопасность

Как запустить PHP скрипт без веб-сервера

Интерпретатор PHP стал неотъемлемой частью практически каждого веб-сервера. Подавляющее большинство веб-приложений написаны на PHP. Поэтому технология PHP очень стойко у многих ассоциируется именно с веб окружением, со средой веб-сервера. Но на самом деле, запускать скрипты PHP можно без веб-браузера. Речь идёт не о специально созданных как веб приложения программах, таких как WordPress, phpMyAdmin, гостевые книги, форумы и прочее. Такие скрипты специально создавались для работы в условиях веб-сервера и для вывода результатов в веб-браузер. Вряд ли удастся полноценно с ними работать в командной строке. Речь идёт о консольных программах на PHP, которые могут выполнять различные, не обязательно связанные с веб сервисами функциями. По сути, PHP является очень гибким языком с хорошим набором классов и на нём можно написать консольную программу под любые функции. Либо ядро программы (так называемый бэк-энд) к которому будер обращаться графический пользовательский интерфейс.

Ещё запуск PHP скриптов в консоли удобен для изучающих язык. Хотя кто-то может с этим не согласиться. При выводе результатов в консоль, а также при передаче аргументов в скрипт, не нужно уделять внимание HTML. Но если вы изучаете PHP для создания веб-приложений и онлайн сервисов, то вам всё равно потом придётся доучивать особенности передачи аргументов из веб-браузера (в окружении сервера), а также HTML вообще, поскольку весь вывод скриптов нужно будет оформлять для браузеров пользователей.

Как запустить PHP скрипт в командной строке Linux

У вас должен быть установлен PHP, к счастью, в Linux интерпретатор PHP устанавливается очень просто, а в некоторых дистрибутивах присутствует по умолчанию. Если у вас его ещё нет, то установите его одной из следующей команд.

В Debian, Kali Linux, Linux Mint, Ubuntu:

Установка полного веб-сервера в Linux Mint описана здесь, в Ubuntu здесь, в Arch Linux/BlackArch здесь, а в Kali Linux он уже установлен, про то, как его запустить здесь.

В остальном запуск скриптов в консоли, в том числе опции запуска, в Linux и Windows идентичные.

Если вы совсем новичок в Linux, то также смотрите Азы работы в командной строке.

Как запустить PHP скрипт в командной строке Windows

Если вы знакомы с запуском консольных программ в Windows или хотя бы в Linux, то для вас всё совсем просто — везде программы запускаются примерно одинаково. Но начнём по порядку для новичков.

Если вы хотите не только возможность запускать PHP из командной строки, но и полноценный веб-сервер Apache + PHP + MySQL на Windows, то выполните установку по этой статье.

Для запуска PHP в командной строке необязательно устанавливать веб-сервер, достаточно скачать и распаковать архив с PHP интерпретатором. О том, где скачать PHP с официального сайта и как разобраться с версиями, смотрите эту статью.

Если вы часто будете запускать PHP скрипты из командной строки Windows, то настоятельно рекомендуется Добавить путь до PHP в переменную окружения PATH в Windows. Благодаря этому не придётся каждый раз указывать полный путь до файла php.exe.

Теперь, когда PHP установлен и путь до php.exe добавлен в переменную окружения Windows, открываем командную строку, для этого нажмите сочетание клавиш Win+x и выберите Windows PowerShell.

Для проверки, что нормально установилось, посмотрим справку по PHP:

На самом деле, мы запускаем файл php.exe, но расширение можно отбросить. То есть предыдущая запись эквивалентна

Справка и опции запуска PHP скриптов в командной строке

Справка содержит опции для разнообразных вариантов запуска файлов .php в командной строке, поэтому приведу её перевод полностью.

Как можно увидеть, вариантов запуска много. Если вы не совсем поняли, что имелось ввиду, не беспокойтесь. В начале мы ознакомимся со значением опций, изучим, так сказать, матчасть, а затем приступим к конкретным примерам, которые внесут окончательную ясность.

Как запустить .php скрипт в командной строке Windows и Linux

Для запуска .php файла в консоли Windows используется следующая команда:

Опцию -f можно отбросить, то есть предыдущая и следующая команды равнозначны:

Я создал тестовый файл, который расположен по пути C:\Users\Alex\Documents\PHP\test.php тогда я могу запустить его в PHP так:

Как передать аргументы PHP скрипту в командной строке

Для передачи скрипту аргументов, перечислите их после имени файла, разделяя пробелом. Если сами аргументы содержат пробелы или другие символы, которые имеют особое значение для оболочки командной строки, то поместите эти аргументы и одинарные или двойные кавычки.

Пример запуска PHP скрипта с тремя аргументами:

Как в PHP скрипте обратиться к аргументам

Переданные аргументы содержаться в массиве $argv. Причём, порядковый номер аргумента соответствует номеру в массиве. То есть первый аргумент будет помещён в $argv[1], второй в $argv[2] и так далее.

Самый первый элемент массива $argv[0] содержит полный путь до запускаемого скрипта.

Запустим его и передадим в скрипт три аргумента:

Как в PHP получить данные от пользователя в консоли

Благодаря передаваемым аргументам, скрипт может выполнять действия не только с прописанными в нём данными, но и с другими значениями, указанными при запуске скрипта.

Кстати, при работе в окружении веб-сервера, то есть когда PHP скрипт выполняет задачи для веб-сайта, возможность передать ему аргументы реализована с помощью HTTP методов GET и POST. Эти аргументы передаются перед запуском скрипта и уже после запуска PHP скрипта, новые данные отправить нельзя — нужно ждать завершения работы программы, и при необходимости запустить её ещё раз с новыми данными.

Во время работы скрипта может потребоваться ввод новых данных, в консоли это достигается с помощью строки запроса, в которую пользователь может ввести значение и нажать Enter для передачи его скрипту. В контексте веб-сайта такой возможности — передать данные уже во время выполнения скрипта — нет. То есть консольный запуск PHP скриптов с аргументами не только проще (не нужно возиться с HTML формой), но и даже более гибкий.

Читайте также:  Установка волоконно оптического кабеля

В PHP для запроса пользователю используется функция readline.

Эта функция одинаково работает и на Windows и на Linux. Причём на Linux она имеет интерактивные возможности Bash, например, сохраняет историю ввода, к которой можно вернуться с помощью стрелок. На Windows эта возможность появилась начиная с PHP 7.1.

Если сильно надо, можно настроить автозавершение вводимых данных. Все функции GNU Readline рассмотрены здесь. Я же коснусь только readline, которая считывает введённую пользователем строку. С этой функцией можно указать один опциональный аргумент — строку, которая будет показана пользователю в приглашении.

Пример консольного PHP скрипта, которые запрашивает у пользователя данные в приглашении командной строки:

Проверка синтаксиса скрипта PHP в командной строке

С опцией -l будет проверен синтаксис, то есть не нарушены ли правила кода PHP, но сам файл скрипт не будет выполнен:

Или если в файле есть ошибки:

Выполнение команд PHP в интерактивном режиме

Если вам это нужно, то можно работать с интерпретатором PHP в интерактивном режиме, вводя код построчно. При этом код выполняется после нажатия кнопки Enter, но значения переменных сохраняются в рамках одной сессии. То есть вы можете присвоить значение какой-либо переменной, а затем использовать его в других строках.

Для запуска интерактивного шелла:

Запуск отдельных команд PHP

Для выполнения отдельных команд используйте опцию -r:

Запуск встроенного в PHP веб-сервера

В PHP есть свой собственный веб-сервер! Если вам очень надо, можно вообще обойтись без сторонних серверов для каких-то определённых задач.

Допустим, в качестве прослушиваемого IP адреса я хочу установить 127.0.0.1, в качестве прослушиваемого порта — 84, корневая папка документов веб-сервера у меня расположена в C:\Users\Alex\Documents\PHP\, тогда команда запуска следующая:

В этой папке у меня файл test_2.php со следующим содержимым:

Можно было бы из спортивного интереса попробовать во встроенном веб-сервере запустить WordPress, но что-то лень…

Получение справки в командной строке

Для получения справки о функциях PHP прямо в командной строке используется опция —rf.

Ну как-то так… а чего вы хотели — это же консоль.

Насколько я понял, в строке Parameters в фигурных скобках пишется количество аргументов функции, строка required означает, что аргумент обязательный, а строка optional — что аргумент опциональный. О функции аргументов иногда можно догадаться по их имени, например, $filename. Информации о том, какое действие выполняет функция, видимо, нет.

Опции для разработчика

Если вы действительно пишите и отлаживаете код, в том числе для веб-сайтов, то вам пригодятся следующие опции:

Вывод информации о PHP

Для показа информации о PHP имеются следующие три опции:

Опция -i — это эквивалент phpinfo, но для консоли.

PHP не может сохранить файл даже если достаточно прав на запись

На самом деле это может случиться не только при запуске PHP скриптов из командной строки, но и при работе скрипта на веб-сервере. Но при запуске в консоли больше условий для получения этой проблемы: PHP скрипт не сохраняет файл в папку, на которую установлены права на запись для кого угодно (777).

Такое поведение может выглядеть необъяснимым, если вы не знаете о директиве open_basedir в главном конфигурационном файле php.ini. Данная директива ограничивает все файловые операции теми папками, которые указаны с ней. Пример:

Данная запись означает, что PHP скрипт может записывать файлы в папку /srv/http/, а также в папки /etc/webapps/, /usr/share/webapps/ и /tmp/.

Причём если директива open_basedir вообще не настроена (строка с ней, например, закомментирована), то PHP может записывать в любую папку, если у текущего пользователя достаточно прав на запись.

При работе в консоли PHP скрипт может пытаться сохранить файлы, например, в текущую папку — если эта папка не указана в open_basedir, но при этом сама директива open_basedir настроена, то возникнет описанная проблема: PHP не сможет записывать файлы даже в папку открытую для всех.

Чтобы избавиться от этой ошибки есть несколько вариантов:

  • добавить папку, в которую вы хотите сохранить файл, в перечень open_basedir
  • выбрать для сохранения папку уже указанную в open_basedir
  • запустить интерпретатор PHP без чтения настроек из конфигурационных файлов (в этом случае не будет учтена директива open_basedir, а также вообще все другие конфигурации

Чтобы запустить PHP скрипт без учёта настроек файла php.ini используйте опцию -n, например:

Кстати, чтобы узнать, какие именно файлы настроек учитываются при работе PHP, выполните следующую команду:

Заключение

Запуск PHP скриптов в командной строке — это альтернатива их запуску через веб-сервер. Работа в консоли может быть удобна при обучении языку программированию PHP или для отладки определённых функций, даже если в дальнейшем эти функции и скрипты будут работать на веб-сервере.

Скрипт на PHP может быть альтернативой скрипту на Bash, особенно если нужно использовать СУБД (MySQL, SQLite) — с которыми через Bash работать тяжело, либо для использования возможностей PHP по работе с текстом в разметке XML, JSON — что в Bash также не очень удобно.

В любом случае, нужно знать о такой возможности, поскольку некоторые программы, особенно такое можно увидеть среди эксплойтов, представляют собой PHP скрипты, предназначенные для запуска в командной строке с аргументами.

источник

Запускаем PHP-скриптики через php-fpm без web-сервера. Или свой FastCGI-клиент (под капотом)

Приветствую всех читателей «Хабра».

Дисклеймер

Статья получилась довольно длинная и тем кто не хочет читать предысторию, а хочет перейти сразу к сути прошу прямиком к главе «Решение».

Вступление

В данной статье хотелось бы рассказать о решении довольно нестандартной задачи, с которой пришлось столкнуться во время рабочего процесса. А именно, нам понадобилось запускать в цикле кучу php скриптов. О причинах и о спорности подобного архитектурного решения в данной статье распространяться не буду, т.к. собственно она и не про это вовсе, просто была задача, ее нужно было решить и решение показалось мне достаточно интересным чтобы им поделиться с Вами, тем более манов по данному вопросу в интернете я не нашел совсем (ну разумеется кроме официальных спецификаций). Спеки конечно это хорошо и в них конечно все есть, но думаю вы согласитесь, что если вы не особо знакомы с темой, да и еще и ограничены по времени то разбираться в них то еще удовольствие.

Читайте также:  Установка времени для реле стеклоочистителя

Для кого эта статья

Для всех кто работает с web-ом и о протоколе FastCgi знает лишь что это протокол в соответствии с котороым web-сервер запускает php скриптики, но хочет более детально его изучить и заглянуть под капот.

Обоснование (зачем эта статья)

В общем как я уже писал выше когда мы столкнулись с необходимостью запускать много php скриптов без участия web-сервера (грубо говоря из другого php скрипта), то первое что пришло на ум это .

Но при запуске каждого скрипта, будет создаваться окружение, запускаться отдельный процесс, в общем как то затратно по ресурсам нам показалось. Данную реализацию отвергли. Второе что пришло на ум это конечно же php-fpm, он ведь такой крутой, всего один раз запускает окружение, следит за памятью, все там логирует, корректно запускает и останавливает скрипты, в общем все делает круто, и нам конечно же этот путь понравился больше.

Но вот незадача, в теории то мы знали как это работает, в общих чертах (как оказалось в очень общих), но вот реализовать этот протокол на практике без участия web-сервера оказалось довольно трудно. Чтение спецификаций и пару часов безуспешных попыток показали что для реализации потребуется время, которого у нас на тот момент не было. Манов по реализации данной затеи, в которых было бы просто и понятно описано данное взаимодействие не нашлось, спеки наскоком взять тоже не удалось, из готовых решений нашли питоновский скрипт и пыховскую либу на гитхабе, которую в итоге не захотели тащить к себе в проект (может это и не правлиьно но не особо мы любим всякие сторонние библиотеки да еще и не очень то и популярные, а значит и не проверенные). В общем по итогу от этой идеи мы отказались и реализовали все это через старых добрый rabbitmq.

Хоть задачу в итоге и решили, но разобраться в FastCgi детально я все таки решил, и в добавок решил написать об этом статью, в которой будет просто и подробно описано как заставить php-fpm запустить php скрипт без web-сервера, а точнее в качестве web-сервера будет другой скрипт, далее его буду называть Fcgi клиент. В общем надеюсь что данная статья поможет тем кто столкнулся с такой же задачей как и мы и прочитав ее сможет быстро все написать как ему надо.

Творческий поиск (ложный путь)

Итак проблема обозначена, надо приступать к решению. Естественно как любой «нормальный» программист для решения задачи, про которую ни где не написано что делать и что вводить в консоль, я не стал читать и переводить спецификацию, а сразу же придумал свое «гениальное» решение. Суть его в следующем, я знаю что nginx (мы используем nginx и чтобы не писать далее дурацкое — web-сервер, буду писать nginx, так как то посимпатичнее) что то передает в php-fpm, это что то php-fpm обрабатывает и на основе него запускает скрипт, что ж вроде все просто, возьму да залогирую то что передает nginx и передам то же самое.

Тут поможет великолепный netcat (UNIX-утилита для работы с сетевым трафиком, которая по моему может практически все). Итак ставим netcat на прослушивание локального порта, а nginx настраиваем на работу с php файлами через сокет (естественно сокет на том же порту который слушает netcat)

Проверить что все ок, можно обратившись через браузер на адрес 127.0.0.1:9000 должна быть следующая картина

настраиваем nginx чтобы он php скрипты обрабатывал через сокет на 9000 порту (в настройках ‘/etc/nginx/sites-available/default’, конечно могут отличаться)

После этих манипуляций проверим что же получилось, обратившись к php скрипту через браузер

Видно что nginx отправил переменные окружения, а также непечатаемые символы, то есть данные были переданы в двоичной кодировке, а это значит что так просто их нельзя скопировать и послать в сокет php-fpm. Если сохранить их в файл например то они сохраняться в 16-ричной кодировке, выглядеть это будет примено так

Но это тоже мало что нам дает, наверное чисто теоретически их можно перевести в двоичную кодировку, каким то образом (даже не представляю каким) их отправить в сокет fpm, и даже есть вероятность что весь этот велосипед как то сработает, и даже запустит какой то скрипт, но уж как то все это страшненько и кривенько.

Стало ясно что данный путь совершенно неверный, сами видите насколько все это убого выглядит, и тем более все эти действия не позволят нам управлять соединением, и ни как не приблизят к пониманию взаимодействия между php-fpm и nginx.

Все пропало, изучения спецификации не миновать!

Решение (тут собственно начинается вся соль данной статьи)

Теоретическая подготовка

Давайте теперь рассмотрим как же все таки происходит соединение и обмен данными между nginx и php-fpm. Немного теории, все общение происходит как уже понятно через сокеты, далее будем рассматривать конкретно соединение через TCP сокет.

Единицей информации в протоколе FastCgi является cgi запись. Такие записи сервер отправляет приложению и точно такие же записи получает в ответ.

Немного теории (структуры)

Далее рассмотрим структуру записи. Для понимания из чего состоит запись нужно понимать что из себя представляют Си подобные структуры и понимать их обозначения. Для тех кто не знает далее это будет кратко (но достаточно для понимания) описано. Описать постараюсь как можно проще, в детали углубляться тут нет смысла, да и боюсь что в деталях запутаюсь, главное чтобы было общее понимание.

Читайте также:  Установка вмт змз 402

Структуры представляют собой просто напросто набор байтов, и нотацию к ним позволяющую их интерпретировать. То есть у вас есть просто последовательность нулей и единиц, и в этой последовательности зашифрованы какие то данные, но пока у вас к этой последовательности нет аннотации то эти данные для вас не представляют никакой ценности, т.к. интерпретировать их вы не можете.

Что тут видно, у нас есть некоторые биты, что это за биты мы понятия не имеем. Ну давайте попробуем например их разделить на байты и представить в десятичной системе

Отлично мы интерпретировали их и получили какие то результаты, допустим что эти данные отвечают за то сколько определенная квартира должна за электроэнергию. Получается что в доме 222 квартира номер 2 должна заплатить 88 рублей. А что еще за две цифры, что с ними делать просто отбросить? Конечно нет! дело в том что мы не имели нотации (формата) которая подсказала бы нам как интерпретировать данные, и интерпретировали их по своему, в связи с этим получили не только бесполезный, но и вредный результат. В итоге квартира 2 заплатила совершенно не то что должна была. (примеры конечно надуманные и служат лишь для того чтобы более понятно объяснить ситуацию)

Теперь посмотрим как же мы должны были интерпретировать правильно эти данные, имея нотацию (формат). Далее буду называть вещи своими именами, а именно нотация = формат (вот тут форматы).

Теперь все сходиться в доме №222 квартира 600 за электричество должна 1000 рублей Думаю теперь ясна важность формата, и теперь понятно как примерно выглядит условно Си подобная структура. (прошу обратить внимания, тут цель не детально объяснить что такое эти структуры, а дать общее понимание что это такое и как это работает)

Условное обозначение данной структуры будет такое

Еще немного теории (FastCgi записи)

Как я уже сказал выше единицей информации в протоколе FastCgi являются записи. Записи сервер отправляет приложению и такие же записи получает в ответ. Запись состоит из заголовка и тела с данными.

  1. версия протокола (всегда 1) обозначается 1 байтом (‘C’)
  2. тип записи. Для открытия, закрытия соединения и др. все не буду рассматривать, далее рассмотрю только то что понадобится для конкретной задачи, если нужны другие — добро пожаловать сюда спецификация. Обозначается 1 байтом (‘C’).
  3. ID запроса, произвольное число, обозначается 2 байтами (‘n’)
  4. длинна тела записи (данных), обозначается 2 байтами (‘n’)
  5. длинна выравнивающих данных и зарезервированные данные, по одному байту (тут не нужно особо обращать внимания, дабы не отвлекаться от главного в нашем случае всегда будет 0)

Далее идет само тело записи:

  1. сами данные (тут то именно и передаются переменные), могут иметь довольно большой размер (до 65535 байт)

Вот пример самой простой FastCgi записи в двоичном виде с форматом

Практика

Скрипт клиент и передающий сокет

Для передачи данных будем использовать стандартное php расширение socket. И первое что нужно будет сделать — это настроить php-fpm на прослушивание порта на локальном хосте, например 9000. Это делается в большинстве случаем в файле ‘/etc/php/7.3/fpm/pool.d/www.conf’, путь конечно зависит от настроек вашей системы. Там нужно прописать примерно следующее (всю портянку привожу чтобы можно было сориентироваться, главная секция здесь listen)

После настройки fpm, следующим этапом будет подключение к сокету

Начало запроса FCGI_BEGIN_REQUEST

Для открытия соединения мы должны отправить запись с типом FCGI_BEGIN_REQUEST = 1 Заголовок записи будет такой (для приведения числовых значений к бинарной строке с заданным форматом будет использована php функция pack())

Тело записи для открытия соединения должно содержать роль записи и флаг управляющий соединением

Итак запись для открытия соединения успешно отправлена, php-fpm ее примет и далее будет ожидать от нас дальнейшей записи в которой нужно передать данные для разворачивания окружения и запуска скрипта.

Передача параметров окружения FCGI_PARAMS

В данной записи мы будем передавать все параметры которые нужны для разворачивания окружения, а так же имя скрипта который нам надо будет запустить.

Минимальные необходимые параметры окружения

Первое что нам тут нужно сделать — это подготовить необходимые переменные, то есть пары имя => значение, которые мы передадим приложению.

Структура пар имя значение будет такая

Идет сначала 1 байт — длинна имени, потом 1 байт значение

В нашем случае и имя и значения короткие и подходят под первый вариант, по этому его и будем рассматривать.

Закодируем наши переменные в соответствии форматом

Тут значения меньше 128 бит кодируются функцией chr($keyLen), больше pack(‘N’, $valLen), где ‘N’ обозначает 4 байта. И затем все это слепляется в одну строку в соответствии с форматом структуры. Тело записи готово.

В заголовке записи передаем все то же самое как и в предыдущей записи, кроме типа (он будет FCGI_PARAMS = 4) и длинны данных (она будет равна длине пар имя => значение, или длине строки $keyValueFcgiString которую ранее мы сформировали).

Получение ответа FCGI_PARAMS

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

Получаем заголовок, он всегда равен 8 байт (получать данные будем по байту)

Теперь в соответствии с полученной длинной тела ответа сделаем еще одно чтение из сокета

Ура все сработало! Наконец то!
Что мы имеем в ответе, если например в этом файле

то в ответе получим в итоге

Итоги

Много тут не буду писать итак статья длинная получилась. Надеюсь она кому то поможет. И приведу сам итоговый скрипт, он получился совсем небольшой. Конечно он в таком виде довольно мало может, и в нем нет обработки ошибок и всего этого, но ему это и не надо, он нужен как пример, чтобы показать основы.

источник

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *