Выполнение сценария оболочки из сценария PHP

Я хочу выполнить скрипт Bash, присутствующий в системе, из скрипта PHP. У меня есть два скрипта в системе. Один из них — это PHP-скрипт с именем client.php, присутствующий в /var/www/html, а другой — скрипт Bash с именем testscript, присутствующий в /home/testuser.

Мой скрипт client.php выглядит так

<?php
  $message=shell_exec("/home/testuser/testscript 2>&1");
  print_r($message);
?>  

Мой тестовый скрипт выглядит так

#!/bin/bash
echo "Testscript run succesful"

Когда я делаю следующее на терминале

php client.php

Я получаю следующий вывод на терминале

Testscript run successful

Но когда я открываю страницу в

http://serverdomain/client.php

Я получаю следующий вывод

sh: /home/testuser/testscript: Permission denied 

Я получаю эту ошибку даже после того, как выполнил chmod +x testscript.
Как мне заставить его работать из браузера? Пожалуйста помоги.


person nmadhok    schedule 17.06.2013    source источник
comment
Как насчет разрешения read? Разрешение Execute бесполезно без разрешения read.   -  person Samveen    schedule 17.06.2013
comment
У Apache не будет доступа к вашему домашнему каталогу. И вы никогда не должны этого хотеть. Помните, что недостаточно предоставить права на сценарий. Вы также должны предоставить доступ к каталогам, в которых он находится. например если я поставлю бесплатную, возьму одну газетную подставку в банковском хранилище, никто не сможет забрать газеты, даже если они бесплатны.   -  person Marc B    schedule 17.06.2013
comment
@MarcB Я забыл о разрешениях пути. И хорошая аналогия.   -  person Samveen    schedule 17.06.2013
comment
я сделал ls -l и получил следующий вывод: -rwxr-xr-x 1 apache apache 236 17 июня 14:05 testscript. Итак, как мне это сделать? Где я должен хранить скрипт, чтобы он мог выполняться скриптом php из браузера, а скрипт bash мог выполняться как root.   -  person nmadhok    schedule 17.06.2013
comment
@ user2132281: проблема не в сценарии. это ваш домашний каталог. apache не может добраться до него. также не давайте apache разрешения на это. переместите скрипт куда-нибудь, где apache МОЖЕТ его получить.   -  person Marc B    schedule 17.06.2013
comment
я хочу, чтобы testscript имел привилегии root. поэтому я не могу переместить его в каталог /var/www/html, верно?   -  person nmadhok    schedule 17.06.2013
comment
Смотрите мой ответ. независимо от того, где он находится. root может делать все и вся, даже если root не является владельцем.   -  person Panama Jack    schedule 17.06.2013
comment
погуглите visudo NOPASSWD   -  person bwoebi    schedule 17.06.2013
comment
Вам нужно будет предоставить большие sudo разрешения для вашего веб-сервера в этом скрипте. Или заверните скрипт в бинарный файл suid. Но в любом случае, будьте ОЧЕНЬ ОЧЕНЬ ОЧЕНЬ ОЧЕНЬ осторожны с этим. Неправильный вызов сценария, неправильная передача некоторых данных, и вы предоставили удаленным пользователям корневую оболочку на своем сервере, и бум ваш сервер.   -  person Marc B    schedule 17.06.2013
comment
Это называется плохой идеей. :) Просто не делайте этого. Реальный риск безопасности.   -  person jm666    schedule 18.06.2013
comment
я хочу, чтобы php выполнял скрипт и запускал его как root. Как еще я могу это сделать?   -  person nmadhok    schedule 18.06.2013
comment
Другой метод — запуск демона с правильными привилегиями, который недоступен снаружи сервера и прослушивает только очень специфические локальные запросы из белого списка. Тем не менее, будьте очень осторожны, но гораздо лучше, чем давать эти привилегии веб-серверу.   -  person Wrikken    schedule 18.06.2013
comment
Вместо #!/bin/bash вы должны использовать Posix #!/usr/bin/env bash. Он должен найти Bash в других местах, например /usr/local/bin, если он присутствует и находится на пути.   -  person jww    schedule 28.11.2018


Ответы (4)


У меня был бы каталог с именем scripts в папке WWW, чтобы он был недоступен из Интернета, но был доступен PHP.

e.g. /var/www/scripts/testscript

Убедитесь, что пользователь/группа для вашего testscript совпадает с вашими веб-файлами. Например, если ваш client.php принадлежит apache:apache, измените сценарий bash на того же пользователя/группу, используя chown. Вы можете узнать, кому принадлежат ваши client.php и веб-файлы, выполнив ls -al.

Затем запустите

<?php
      $message=shell_exec("/var/www/scripts/testscript 2>&1");
      print_r($message);
    ?>  

ИЗМЕНИТЬ:

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

Выполнение корневых команд через PHP

person Panama Jack    schedule 17.06.2013
comment
Поскольку веб-сервер не работает (или не должен) работать с правами root, он не сможет этого сделать. - person Barmar; 17.06.2013
comment
Я обновил свой ответ информацией до решения, которое должно вам подойти. Сэкономьте мне время, чтобы написать это. :) - person Panama Jack; 17.06.2013
comment
я хочу, чтобы мой тестовый скрипт находился только в /home/testuser. И я хочу выполнить это с помощью php. Как я могу это сделать, не меняя тестовый скрипт и не ставя под угрозу безопасность. Я просто хочу это для этого скрипта - person nmadhok; 17.06.2013
comment
У меня не работает, я не получаю вывода из своего скрипта, если запускаю его как www-data, но он работает, если запускаю его с root - person Black; 29.01.2016

Не зная на самом деле сложности настройки, мне нравится маршрут sudo. Во-первых, вы должны настроить sudo, чтобы разрешить вашему веб-серверу выполнять sudo данную команду от имени пользователя root. Затем вам нужно иметь скрипт, который shell_exec веб-сервера (testscript) запускает команду с помощью sudo.

Для коробки Debian с Apache и sudo:

  1. Настройте судо:

    • От имени пользователя root выполните следующее, чтобы отредактировать новый/выделенный файл конфигурации для sudo:

      visudo -f /etc/sudoers.d/Webserver
      

      (или как вы хотите назвать свой файл в /etc/sudoers.d/)

    • Добавьте в файл следующее:

      www-data ALL = (root) NOPASSWD: <executable_file_path>
      

      где <executable_file_path> – это команда, которую необходимо запустить от имени пользователя root с полным путем в имени (скажем, /bin/chown для исполняемого файла chown). Если исполняемый файл будет каждый раз запускаться с одними и теми же аргументами, вы можете добавить его аргументы сразу после имени исполняемого файла, чтобы еще больше ограничить его использование.

      Например, если мы хотим всегда копировать один и тот же файл в каталог /root/, мы напишем следующее:

      www-data ALL = (root) NOPASSWD: /bin/cp /root/test1 /root/test2
      
  2. Измените скрипт (тестовый скрипт):

    Отредактируйте свой сценарий так, чтобы sudo отображалось перед командой, требующей привилегий root (скажем, sudo /bin/chown ... или sudo /bin/cp /root/test1 /root/test2). Убедитесь, что аргументы, указанные в файле конфигурации sudo, точно соответствуют аргументам, используемым с исполняемым файлом в этом файле. Итак, для нашего примера выше у нас будет следующее в скрипте:

    sudo /bin/cp /root/test1 /root/test2
    

Если вы по-прежнему получаете отказ в доступе, файл сценария и разрешения его родительских каталогов могут не позволять веб-серверу выполнять сам сценарий. Таким образом, вам необходимо переместить сценарий в более подходящий каталог и/или изменить разрешения сценария и родительского каталога, чтобы разрешить выполнение с помощью www-data (пользователь или группа), что выходит за рамки этого руководства.

Имейте в виду:

При настройке sudo цель состоит в том, чтобы разрешить команду в ее наиболее ограниченной форме. Например, вместо общего использования команды cp вы разрешаете команду cp только в том случае, если аргументы, скажем, /root/test1 /root /тест2. Это означает, что аргументы cp (и функциональность cp не могут быть изменены).

person Craig Hesling    schedule 18.06.2013
comment
Просто настройте все, как указано выше, и я получаю sudo: нет tty, и нет программы askpass, указанной в apache error.log на Centos 6. - person webcoder.eu; 11.10.2020
comment
Я сталкивался с другими подобными решениями, в которых говорится, что необходимо разделить sudoers, которым разрешено запускать команды или сценарии, пути с запятыми, т.е. NOPASSWD: /bin/cp, /root/test1, /root/test2 ? - person webcoder.eu; 13.10.2020

Я боролся с этой точной проблемой в течение трех дней. Я установил разрешения для сценария на 755. Я вызывал свой сценарий следующим образом.

<?php
   $outcome = shell_exec('/tmp/clearUp.sh');
   echo $outcome;
?>

Мой сценарий был следующим.

#!bin/bash
find . -maxdepth 1 -name "search*.csv" -mmin +0 -exec rm {} \;

Я не получал никакого результата или обратной связи. Изменение, которое я сделал, чтобы запустить скрипт, заключалось в том, чтобы добавить cd в tmp внутри скрипта:

#!bin/bash
cd /tmp;
find . -maxdepth 1 -name "search*.csv" -mmin +0 -exec rm {} \;

Это было больше удачей, чем суждением, но теперь это работает отлично. Надеюсь, это поможет.

person Rob EatsEverything Delaney    schedule 17.07.2014

Это простая проблема. Когда вы работаете с терминала, вы запускаете файл php с терминала как привилегированный пользователь. Когда вы переходите к php из своего веб-браузера, php-скрипт запускается от имени пользователя веб-сервера, у которого нет прав на выполнение файлов в вашем домашнем каталоге. В Ubuntu пользователь www-data является пользователем веб-сервера apache. Если вы используете Ubuntu, вам нужно будет сделать следующее: chown yourusername:www-data /home/testuser/testscript chmod g+x /home/testuser/testscript

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

person priyolahiri    schedule 17.06.2013
comment
я на РХЕЛе. пользователь веб-сервера для меня будет apache. Также будет ли скрипт по-прежнему выполняться пользователем root? Вы сказали, что право собственности на пользователя перейдет ко мне. - person nmadhok; 17.06.2013
comment
Корень охватывает все. Он по-прежнему будет доступен для root. - person priyolahiri; 20.06.2013