Начиная FOREVER или PM2 как WWW-DATA из скрипта PHP

У меня есть скрипт nodejs именем script.js .

 var util = require('util'); var net = require("net"); process.on("uncaughtException", function(e) { console.log(e); }); var proxyPort = "40000"; var serviceHost = "1.2.3.4"; var servicePort = "50000"; net.createServer(function (proxySocket) { var connected = false; var buffers = new Array(); var serviceSocket = new net.Socket(); serviceSocket.connect(parseInt(servicePort), serviceHost); serviceSocket.pipe(proxySocket).pipe(serviceSocket); proxySocket.on("error", function (e) { serviceSocket.end(); }); serviceSocket.on("error", function (e) { console.log("Could not connect to service at host " + serviceHost + ', port ' + servicePort); proxySocket.end(); }); proxySocket.on("close", function(had_error) { serviceSocket.end(); }); serviceSocket.on("close", function(had_error) { proxySocket.end(); }); }).listen(proxyPort); 

Я запускаю его обычно как nodejs script.js , но теперь я хочу включить forever или pm2 функции. Когда я root все работает смутно:

 chmod -R 777 /home/nodejs/forever/; -- give rights watch -n 0.1 'ps ax | grep forever | grep -v grep' -- watch forwarders (where i see if a forever is opened) /usr/local/bin/forever -d -v --pidFile "/home/nodejs/forever/file.pid" --uid 'file' -p '/home/nodejs/forever/' -l '/home/nodejs/forever/file.log' -o '/home/nodejs/forever/file.log' -e '/home/nodejs/forever/file.log' -a start /etc/dynamic_ip/nodejs/proxy.js 41789 1.2.3.4:44481 414 file -- open with forever forever list -- it is there, i can see it forever stopall -- kill them all 

Проблема в том, когда я хочу запустить скрипт из скрипта PHP с помощью функций system или exec :

 sudo -u www-data /usr/local/bin/forever -d -v --pidFile "/home/nodejs/forever/file.pid" --uid 'file' -p '/home/nodejs/forever/' -l '/home/nodejs/forever/file.log' -o '/home/nodejs/forever/file.log' -e '/home/nodejs/forever/file.log' -a start /etc/dynamic_ip/nodejs/proxy.js 41789 1.2.3.4:44481 414 file -- open as www-data (or i can do this just by accessing `http://1.2.3.4/test.php`, it is the same thing) forever list -- see if it is there, and it is not (i see it in watch) forever stopall -- says no forever is opened kill PID_ID -- the only way is to kill it by pid ... and on another server all of this works very well, can create and kill forevers from a php script when accessing it from web ... not know why -- everything is in /etc/sudoers including /usr/local/bin/forever 

Почему это? Как я могу это решить?

Я также сделал какой-то трюк, создал пользователя 'forever2', я создал script.sh с этим контентом:

 sudo su forever2 user123; /usr/local/bin/forever -d -v --pidFile "/home/nodejs/forever/file.pid" --uid 'file' -p '/home/nodejs/forever/' -l '/home/nodejs/forever/file.log' -o '/home/nodejs/forever/file.log' -e '/home/nodejs/forever/file.log' -a start /etc/dynamic_ip/nodejs/proxy.js 41789 1.2.3.4:44481 414 file; 

где user123 не существует, это всего лишь трюк для выхода из shell после выполнения. Скрипт работает, работает forever , я могу закрыть все форварды с помощью команды forever stopall от root . Когда я пытаюсь сделать то же самое, что и http://1.2.3.4/test.php или как пользователь www-data я не могу закрыть его из root или www-data , поэтому даже это не работает.

Я пробовал из Ubuntu 14.04.3 LTS , Ubuntu 14.04 LTS , Debian GNU/Linux 8 … все то же самое.

Любые идеи?

Благодарю.

Если вы запускаете процесс из Apache или веб-сервера, вы уже являетесь пользователем www-data , поэтому выполнение sudo su в контексте пользователя, которое у вас уже есть, вероятно, не требуется.

Когда вы запускаете эту forever задачу, вам также может потребоваться закрыть терминалы / входы и напрямую отправить их на задний план. Что-то вроде этого:

 // Assemble command $cmd = '/usr/bin/forever'; $cmd.= ' -d -v --pidfile /tmp/my.pid'; // add other options $cmd.= ' start'; $cmd.= ' /etc/dynamic_ip/nodejs/proxy.js'; // "magic" to get details $cmd.= ' 2>&1 1>/tmp/output.log'; // Route STDERR to STDOUT; STDOUT to file $cmd.= ' &'; // Send whole task to background. system($cmd); 

Теперь здесь не будет выхода, но вы должны иметь что-то в /tmp/output.log которое могло бы показать, почему forever не удалось, или сбой сценария.

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

Это часть безопасности PHP, вы говорите, что используете ее из php-скрипта, и не используете его в Apache через php-скрипт.

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

Есть способы предотвратить запуск php с правами root, но запустить задачу с правами root, но это немного взломанно, и я не буду делиться этим кодом, но я объясню, чтобы вы могли изучить его. вот где начать

http://php.net/manual/en/function.proc-open.php

С помощью Proccess вы можете выполнить proc. Как и ваш script.js через nodeJS, используя SUDO, а затем прочитайте stdOut и stdErr, подождите запрос пароля, затем подайте его, написав stdIn для этого процесса.

Не забывайте, что при этом пользовательские www-data должны иметь пароль и быть в списке sudoers