Удаленный запуск скрипта 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:
В Arch Linux, BlackArch:
Установка полного веб-сервера в 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 в командной строке, поэтому приведу её перевод полностью.
Как можно увидеть, вариантов запуска много. Если вы не совсем поняли, что имелось ввиду, не беспокойтесь. В начале мы ознакомимся со значением опций, изучим, так сказать, матчасть, а затем приступим к конкретным примерам, которые внесут окончательную ясность.
Опцию -f можно отбросить, то есть предыдущая и следующая команды равнозначны:
Я создал тестовый файл, который расположен по пути C:\Users\Alex\Documents\PHP\test.php тогда я могу запустить его в PHP так:
Как передать аргументы PHP скрипту в командной строке
Для передачи скрипту аргументов, перечислите их после имени файла, разделяя пробелом. Если сами аргументы содержат пробелы или другие символы, которые имеют особое значение для оболочки командной строки, то поместите эти аргументы в одинарные или двойные кавычки.
Пример запуска PHP скрипта с тремя аргументами:
Как в PHP скрипте обратиться к аргументам
Переданные аргументы содержаться в массиве $argv. Причём, порядковый номер аргумента соответствует номеру в массиве. То есть первый аргумент будет помещён в $argv[1], второй в $argv[2] и так далее.
Самый первый элемент массива с именем $argv[0] содержит полный путь до запускаемого скрипта.
Содержимое файла test.php:
Запустим его и передадим в скрипт три аргумента:
Как в 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 не сможет записывать файлы даже в папку открытую для всех.
Чтобы избавиться от этой ошибки есть несколько вариантов:
Чтобы запустить PHP скрипт без учёта настроек файла php.ini используйте опцию -n, например:
Кстати, чтобы узнать, какие именно файлы настроек учитываются при работе PHP, выполните следующую команду:
Заключение
Запуск PHP скриптов в командной строке — это альтернатива их запуску через веб-сервер. Работа в консоли может быть удобна при обучении языку программированию PHP или для отладки определённых функций, даже если в дальнейшем эти функции и скрипты будут работать на веб-сервере.
Скрипт на PHP может быть альтернативой скрипту на Bash, особенно если нужно использовать СУБД (MySQL, SQLite) — с которыми через Bash работать тяжело, либо для использования возможностей PHP по работе с текстом в разметке XML, JSON — что в Bash также не очень удобно.
В любом случае, нужно знать о такой возможности, поскольку некоторые программы, особенно такое можно увидеть среди эксплойтов, представляют собой PHP скрипты, предназначенные для запуска в командной строке с аргументами.
Как запускать долгоживущие скрипты на удаленном сервере
Давайте подключимся по ssh к нашему серваку. После подключения сразу создадим новый скрин:
После этого мы оказываемся в новом терминале без какой-либо истории. Давайте выполним теперь в этом терминале какую-нибудь команду. К примеру:
После чего можно попробовать отключиться от терминала. Для этого нужно сначала нажать сочетание клавиш CRTL + A, а затем нажать клавишу D.
В терминале, из которого мы запускали скрин, мы увидим уведомление о том, что мы отключились от скрина:
Теперь давайте снова подключимся к этому скрину. Для этого воспользуемся той же командой:
Вжух! И мы вернулись в тот же терминал, с тем же контекстом, от которого отключались.
Давайте теперь для имитации долгоиграющей команды напишем вот такой простецкий PHP-скрипт:
И запустим его в нашем скрине:
После чего отключимся от скрина сочетанием CTRL+A, затем D.
Затем снова подключимся:
И увидим текущий статус выполнения скрипта.
Можете также отключиться от сервера и снова подключиться к нему по ssh, проверить, что всё работает.
Чтобы завершить скрин, нужно нажать сочетание клавиш CTRL+D. В таком случае мы получим сообщение о завершении, а не об отключении от терминала:
Смотрите, не перепутайте сочетания клавиш =) Теперь если снова запустить
будет снова создан новый терминал.
Если нужно иметь полный лог происходящего, то лучше писать вывод команды в лог-файл. Например, запустив в скрине команду:
Следить за изменениями в логе можно с помощью команды:
Всё, теперь никакие разрывы соединений нам не страшны. Всем успешных миграций 😉
Script-server. WebUI для удалённого запуска ваших скриптов
Всем привет. В данной статье я бы хотел рассказать про свой домашний проект. Если коротко: Script server является веб-сервером для предоставления пользователям доступа к вашим скриптам через web-интерфейс. Сервер и скрипты запускаются локально, а параметризуются и показываются удалённо.
Предыстория
На новом месте работы, первые мои задачи были весьма рутинны и однообразны. Схематично они выглядели так:
Надо сказать, что к определённому моменту подобные задачи уже перестали на меня назначать и у созданных скриптов без необходимой адаптации было очень призрачное будущее.
Поэтому я решил создать инструмент, который позволит удалённо запускать мои скрипты другим людям, без необходимости создавать необходимое окружение и в более удобной форме настраивать их запуск.
На пути создания
Схема работы
Администратор сервера (т.е. я) создаёт файлы конфигурации для каждого скрипта, в которых описывает предназначение скрипта, путь запуска и требуемые параметры. Эти файлы конфигурации используются сервером для предоставления данных о скриптах пользователю, а также для их запуска. Информация на страницу пользователя передаётся Ajax запросами.
Пользователь заполняет параметры и запускает скрипт на сервере, где его выполнение передаётся специальному обработчику. Обработчик в асинхронном режиме принимает input и предоставляет output, а также следит за процессом выполнения скрипта.
Веб сервер служит прослойкой между этим обработчиком и страницей, и через веб-сокеты осуществляет обмен данными.
Выбор инструментов
В то время я учил Python и для разработки решил использовать именно его, как неплохую практику. Для проекта был выбран Python 3, без поддержки 2й версии, поскольку необходимости в этом нет, а тратить лишнее время не хотелось.
В начале разработки для сервера я использовал Flask, но не смог сделать (читай разобраться) с асинхронностью и отслеживанием подключения/отключения клиентов, поэтому довольно быстро перевёл все на Tornado.
Касаемо web разработки: Web-разработчик из меня никакой, поэтому здесь я тоже решил немного попрактиковаться в синтаксисе и основах. В связи с этим не было использовано почти никаких фреймворков и библиотек, за исключением materializecss для более-менее приличного оформления.
Web страница представляет собой «одностраничное приложение» с минимумом HTML и созданием контента в JS по Ajax запросам.
Первая эксплуатация и улучшения
Примерно через месяц у меня получился сервер, который худо-бедно можно было использовать и я поделился им с коллегами-разработчиками, которым тоже приходилось выполнять эти рутинные задачи (которые как назло в этот период почти закончились).
В процессе эксплуатации были обнаружены как баги, так и явно недостающие элементы, над которыми я потихоньку работал и улучшал. В то же время были добавлены мелкие улучшения, такие как типы параметров, логгирование всех запусков и т.п.
Интересный момент: для некоторых мелких задач (связанных с работой в консоли и со скриптами) я также перестал пользоваться консолью, а перешёл на этот UI. Т.е. у меня заведено несколько конфигураций скриптов, которые я использую чаще, чем другие люди.
Эксплуатация реальным пользователем
Спустя некоторое время локального тестирования (мною и другими разработчиками), инструмент был наконец предоставлен руководителю проекта, который начал потихоньку им пользоваться. И надо отметить, что он очень доволен, т.к. это экономит в том числе и его время. Процесс «внедрения» и обучения пользователя занял примерно 5 минут.
Из-за особенностей процессов и ограничений, Script server используется в основном для тестового окружения. Но некоторые его части уже стали использоваться и для Production (в той части, где это безопасно).
Основные камни
Ниже приведён список проблем и моих личных открытий, которые мне больше всего запомнились.
Передача выходных данных из процесса выполнения скрипта на страницу в асинхронном режиме. Тут сказалось отсутствие опыта как во Flask, так и в вебе: как лучше организовать такую передачу. В итоге реализовал на вебсокетах передачу данных в виде событий (тип и данные). Также в событиях можно отправлять и другие команды во время выполнения, но пока это не используется.
Передача ввода пользователя в исполняемый скрипт. Пытался сделать запрос на ввод только при ожидании такового в скрипте, но не нашёл способа. Поэтому пользователи во время выполнения скрипта могут вводить столько информации, сколько хотят (обычный терминал ведет себя так же). Данные отправляются через тот же вебсокет.
Отслеживание отключения пользователей. Именно из-за этой проблемы отказался от Flask: в тот момент я делал не на вебсокетах, а на SSE (ну почти). Однако позже я все же перевёл передачу input/output скрипта на вебсокеты, так что возможно и Flask бы подошёл. В Торнадо же просто можно подписаться на закрытие вебсокета.
Output скриптов в (не)терминальном режиме. Честно говоря для меня это было открытием: output скриптов может отличаться если запускать их в терминале или вне. Например тот же…
… показывает input_prompt только в терминальном режиме. Не очень хорошо чего-либо ждать от пользователей, не показывая им чего именно. Пришлось разбираться с pty, чтобы обманывать запускаемые скрипты. По этой причине у меня сейчас два типа обёрток для запуска скриптов: с поддержкой терминала и без. Первый включается по-умолчанию, второй можно включить с помощью конфигурации (оставил его на всякий случай, если терминальный режим будет сбоить).
Автоскролл выходных данных скрипта. С одной стороны это решается довольно просто, с другой стороны были проблемы с настройкой автоматического отключения этого (если пользователь скроллит вручную или выделяет текст), а также с тенью, вводом пользователя и т.п. Ничего экстраординаорного, но несколько часов потратить пришлось.
Настройка панели с выходными данными скрипта таким образом, чтобы она занимала всё доступное место, но при этом никогда не выходила за границы окна. Таким образом страница всегда умещается в окно и единственный скролл добавляется именно внутри output панели. Для меня это было особенно важно, т.к. я категорично не люблю скроллы в скроллах.
Производительность страницы при очень большом количестве выходных данных скрипта. Тут со мною злую шутку сыграл следующий код:
Дело в том, что получение innerText это сама по себе довольно ресурсоёмкая операция, которая пытается представить входящий html как строку, даже если это просто текст. Если вызывать эту операцию пару сотен раз и для тысячи символов, то эффект не заметен, но в моем случае данных было гораздо больше и браузер просто зависал на несколько минут от такой нагрузки. Решилось изменением кода на следующий:
Висящие процессы, т.е. никто ничего не выполняет, но в процессах висит выполняемый скрипт. Причины были разные, например: пользователь закрыл страницу, а сервер не обрабатывает это. Или не закрытый дескриптор файла. Или незакрытые дочерние процессы. И это не считая других очевидных багов. Но устранялось все гуглёнием, изучение и исправлением.
Безопасность
Её нет, совсем. Данный инструмент рассчитан на локальный запуск и работу в локальной сети с доверенными пользователями. Поскольку зачастую скрипты тоже пишутся для себя, они также не являются особо защищёнными. Соответственно прежде чем запускать такой сервер, нужно быть на 100% уверенным в фаерволле и пользователях.
С точки зрения скрытия данных, в Script server на текущий момент также ничего нет. Включать пароли в качестве параметров или в конфигурацию крайне не рекомендуется, поскольку они будут логироваться и храниться в чистом виде.
Примеры и скриншоты
Для отладки в проекте я завёл тестовые конфигурации, которые можно использовать для тестирования и демонстрации. В данном разделе все предоставленные скриншоты будут основываться на них.
Конфигурация скриптов
Относительно стандартный баш скрипт с параметрами, вводом пользователя во время работы и печатью: Write file.
Простой питон-скрипт, который выводит стену текста, разбивая его на абзацы и запрашивая input пользователя: Destroy world. Эта конфигурация используется для отладки пользовательского интерфейса при отображении параметров. Содержит все возможные типы параметров: Parameterized
Скриншоты
Полный экран
Слева область выбора скриптов, справа информация по текущему открытому скрипту:
Панель параметров
В этом хаосе можно увидеть семейство разных типов параметров: обязательные, списки, числа, булеаны. Скриншот создан на основе конфигурации Parameterized
Панель input/output
Сверху кнопки запуска и остановки. Поскольку скрипт запущен, активна только последняя. Ниже панель выходных данных скрипта, в самом низу поле для ввода входных данных. Панель выходных данных сжата по высоте для демо-цели, в обычном окне она гораздо выше.
Дальнейшие шаги
На данный момент разработка не ведётся, т.к. в текущем виде Script server полностью покрывает возложенные на него задачи. Что-либо оптимизировать в текущем интерфейсе я также не вижу необходимости. Таким образом мы с ним оба находимся в ожидании новых вызовов и проблем.
В частности, я был бы крайне рад, если бы данный инструмент так же пригодился кому-либо из хабрасообщества и у меня бы появилась необходимость в новых улучшениях.
Список используемых библиотек/фрейворков/благодарностей:













