У меня есть скрипт 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