linux — Не получается создать файл на сервере через php + bash

если я попытаюсь исполнить скрипт из консоли все работает, а через веб-страницу нет

Первая причина — права на файлы.

ls -ld /etc/apache2/sites-available

выведет что-то похожее:

drwxr-xr-x 2 root root 4096 Oct  8 14:16 /etc/apache2/sites-available

Получается, что права на запись только у владельца (root). Введите в консоли whoami — скорее всего вы и есть root.

А через вебсервер php-скрипт запускается от имени другого пользователя и группы, это устанавливается в настройках /etc/apache2/apache2.conf. Поищем эти настройки:

grep -P "User|Group" /etc/apache2/apache2.conf

Выведет:

User ${APACHE_RUN_USER}
Group ${APACHE_RUN_GROUP}

Поищем эти переменные:

grep -rP "APACHE_RUN_USER|APACHE_RUN_GROUP" /etc/apache2/

Выведет:

/etc/apache2/envvars:export APACHE_RUN_USER=www-data
/etc/apache2/envvars:export APACHE_RUN_GROUP=www-data

Получается, что апач работает от имени www-data и группы www-data.

Чтобы разрешить доступ, нужно сменить владельца:

sudo chown www-data /etc/apache2/sites-available

либо где-то в конце /etc/apache2/apache2.conf поменять

IncludeOptional sites-enabled/*.conf

на другой каталог, доступный для записи www-data. Что делает a2ensite? По сути, она делает симлинки из sites-available в sites-enabled, поэтому a2ensite после такой перенастройки (смена IncludeOptional) не обязательно выполнять.

Опция open_basedir дополнительно ограничивает PHP какими-то каталогами. Поискать можно так:

grep -r open_basedir /etc/apache2

У меня вывело:

/etc/apache2/sites-available/included.site.ru.conf:  php_admin_value open_basedir "/home/pusher/www/site.ru:/home/pusher/www/mod-tmp:/tmp"

Получается, что когда Apache запускает скрипт сайта site.ru, этот скрипт ограничен тремя перечисленными через : каталогами.

Удалите open_basedir или добавьте каталог /etc/apache2/sites-available в эту настройку.

sudo a2ensite «$1».queryberry.ru.conf

sudo systemctl restart apache2

Пользователь www-data, от имени которого запускается скрипт, скорее всего не имеет прав на запуск административных команд с помощью sudo.

Как настроить запуск sudo ... без ввода пароля я подробно описал тут

Вам нужно запускать две команды: a2ensite и systemctl. Выполните:

sudo visudo

Затем необходимо вставить в конце следующее:

www-data    ALL=(ALL)       NOPASSWD: /usr/sbin/a2ensite
www-data    ALL=(ALL)       NOPASSWD: /bin/systemctl

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

Делайте все поэтапно, смотря результат. Чтобы не запускать каждый раз php-скрипт и ломать голову, зайдите от имени апача и выполняйте аналогичные команды. Давайте зайдем под www-data:

sudo su
su www-data -s /bin/bash

вот так можно понять, что первый пункт работает:

cd /etc/apache2/sites-available
touch site.ru
# выведет это:
touch: cannot touch ‘site.ru’: Permission denied

Ага. Не настроено.

sudo systemctl restart apache2
# выведет это:
We trust you have received the usual lecture from the local System
Administrator. It usually boils down to these three things:
    #1) Respect the privacy of others.
    #2) Think before you type.
    #3) With great power comes great responsibility.
[sudo] password for www-data:

Ага. Требует пароль. Не настроено.

Ограничение open_basedir можно проверить только через браузер.

PS. По сути, вы делаете свою реализацию давно решенной задачи по добавлению виртуальных хостов через веб-панель. Насколько безопасно вы это сделаете — зависит от вас. Если что, есть уже готовые решения: cPanel, ISPmanager и другие.

Что такое файл index.php? | Уроки PHP/MySQL программирования на сайте FructCode