I have a nodejs script named 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);
I am runing it normally like nodejs script.js, but now i want to include forever or pm2 functionalities as well. When i am root everything works smootly:
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
The problem is when i want to run the script from a PHP script with the system or exec functions :
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
Why is that? How can i solve this?
I also made some trick, created a user 'forever2', i created a script.sh with this content :
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;
where user123 is not existent, is just a trick to exit the shell after execution. The script works, runs forever, i can close all forevers with the command forever stopall from root. When i try the same thing running the http://1.2.3.4/test.php or as www-data user i cannot close it from root or www-data, so not even this works.
I tried from Ubuntu 14.04.3 LTS, Ubuntu 14.04 LTS , Debian GNU/Linux 8 ... still the same thing.
Any ideeas?
Thanks.
If you are starting the process from within Apache or the web-server you are already as the www-data user, so doing a sudo su to the user context you already have is likely not necessary.
When you start this forever task you may also be required to shut the terminals/inputs and directly send to background. Something like this:
// 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);
Now, there won't be any output here but you should have something in /tmp/output.log which could show why forever failed, or the script crashed.
If you've been running the script sometimes as root, then trying the same command as www-data you may also be running into a permissions on one or more files/directories created from the execution as root which now conflict when running as www-data.
This is part of PHP security you say you're running it from a php script and your not your running it from Apache via a php script.
PHP web scripts should not have root access as such they run under the same permissions as Apache user www-data.
There are ways to prevent php running as root but run a task as root but it's a little hacky and I'm not going to share the code but I will explain so you can look into it. here is where to start
http://php.net/manual/en/function.proc-open.php
With a Proccess like this you can then execute a proc. Like your script.js via nodeJS using SUDO and then read stdOut and stdErr wait for password request then provide it by writing to stdIn for that process.
Don't forget in doing this the user www-data has to have a password and be in the sudoers list
Per the OPs Comment
Due to the way SUDO works the PATH does not appear to contain the path to the node executables npm, node so your best of building a .sh (bash script) and using sudo to run that.
You still need to monitor this process as it will still ask for a password
#!/bin/bash
sudo -u ec2-user -i
# change this to the path you want to run from
cd ~
/usr/local/bin/pm2 -v
Related
I am trying to get running process on server using Apache.
I have tried on PHP, Perl and Bash script and used this commands :
exec('ps -u username -o pid,uname,cmd,pmem,pcpu,etime --sort=-pcpu > test.txt');
exec('ps -u username -o pid,uname,cmd,pmem,pcpu,etime --sort=-pcpu', $output);
exec('ps -A', $output);
etc...
I only get all / USR / SBIN / HTTPD -k restart processes.
But when I am trying this command on SSH (terminal), I am properly getting all processes.
I think problem is n Apache.
Anybody know how I can solve this problem and get all process using Apache.
Thanks advance
# chcon -t unconfined_exec_t /sbin/httpd
use the command ps x
will list all active process
I have this php code:
echo shell_exec('sh /backups/turnon.sh');
The /backups/turnon.sh code is:
screen -X 'cd /ftb; java -Xms2048m -Xmx2048m -jar mcpc.jar'
However, that outputs to the website:
No screen session found.
However if I open PuTTY and I do screen -x I can load the screen with no issue. What am I doing wrong.
Not sure why one would do this, but as a sample of one way to do it.
www-data
One way to solve this case would be to attach to correct user session. For Apache that is normally www-data which is a user with stripped down privileges. Use ps on apache or,
in PHP you can run this to show you which user PHP (Apache) run as:
<?php echo exec('whoami'); ?>
Output:
www-data
Note that if you run the script using PHP from command-line you will get current user, which you do not want.
Initiate screen session for www-data
www-data is normally not set up with password, as such we cannot log in with that user. To run a screen session for www-data one can do the following:
$ sudo su - www-data
$ script /dev/null
$ screen
Or as a one-liner:
sudo su - www-data -c 'script -c screen /dev/null'
This will start a new shell in www-data's home directory, typically /var/www/. The script command is one way to prevent access error to terminal when running screen due to the use of sudo su.
Execute script from PHP
Now that we have a screen session for www-data we can continue with the Bash script.
/usr/bin/screen -X stuff '/usr/bin/java -cp /some/path/ Test
'
and execute it from PHP.
Capturing output
If you want the buffer from screen in PHP there is various ways:
First create a log-file for www-data's screen session.
touch /tmp/www-data-scr.log
chown www-data:www-data /tmp/www-data-scr.log
Use logfile option in .screenrc and run screen with -L.
Run script -f /tmp/www-data-scr.log inside screen.
Start www-data script screen session with log-file, -f to flush.
sudo su - www-data -c 'script -fc screen /tmp/www-data-scr.log'
Copy buffer to file to get a snapshot.
/usr/bin/screen -X hardcopy /tmp/www-data-scr.log
etc.
You would typically add a
sleep N
in your bash script after issuing the command producing some output and before reading the log file.
To sum up
As privileged user:
touch /tmp/screen.log
sudo chown www-data:www-data /tmp/screen.log
sudo su - www-data -c 'script -c screen /dev/null'
Bash script:
#!/bin/bash
/usr/bin/screen -X stuff 'java -cp /some/class/path/ Test
'
sleep 1
/usr/bin/screen -X hardcopy /tmp/screen.log
sed '/^$/d' /tmp/screen.log
PHP:
<pre>
<?php
echo "-----------------------------------------------------------\n";
echo htmlentities(shell_exec('sh /path/to/script'));
echo "-----------------------------------------------------------\n";
?>
</pre>
The man page for screen specifically states:
-x Attach to a not detached screen session. (Multi display mode).
-X Send the specified command to a running screen session.
The error message you're getting says that there's no existing screen process running to attach to. Something is different between your PuTTY login environment and the environment in which the script is trying to run, possibly that you have a screen session running as your PuTTY login user but none running as the user running the script.
I want to launch the command "unoconv" from a script php.
$command = '/usr/bin/unoconv --server localhost --port 2002 --format=pdf file.rtf >/dev/null 2>/dev/null';
$rc = system( $command );
echo $rc;
The command return no result and the file is not created.
I think is a problem from access with www-data and unoconv.
When I'm launching the command in shell, the file is created.
Any idea?
You can add command unoconv to sudoers.
I do this in this way:
I create wrapper bash script in for example /usr/local/bin where I have command unoconv.
#!/bin/bash
if [ -z "$1" ]; then
echo "Must pass file";
exit 10;
fi
/usr/bin/unoconv -f pdf $1.rtf
after this I adding entry in /etc/sudoers.d:
www-data ALL=NOPASSWD: /usr/local/bin/unoconv.sh
And now you can call script in php:
exec('sudo /usr/local/bin/unoconv.sh '.$fileName);
Try to run
$output = `/usr/bin/unoconv --server localhost --port 2002 --format=pdf file.rtf`;
instead and see error messages.
For me works like this:
$cmd = "/usr/bin/unoconv -f docx files/thefile";
shell_exec($cmd);
of course you have to do this previously (if you lounch your php script from the web):
chown -R www-data:www-data files/
I have found a solution to this problem when running Apache. You have to create the home folder for the www-data user
sudo mkdir /home/www-data
sudo chown www-data /home/www-data
Lastly we will have to edit the home directory and default shell for the www-data user
sudo vim /etc/passwd
For the entry of www-data the last two strings have to be replaced respectively with
/home/www-data
/bin/bash
Simple as this
$output = shell_exec('/opt/libreoffice5.0/program/python unoconv -f rtf test.html');
Edit the path to suite your configuration.
It just works!
You may be running into an issue with LibreOffice, OpenOffice or soffice not being able to write to the current user's $HOME directory.
By running the command below I was able to identify the correct $HOME directory and see the error that was being generated.
$cmd = 'echo $HOME & unoconv -vvvv --format %s --output %s %s 2>/tmp/unoconv.debug.txt';
exec($cmd);
The verbose output of $cmd will be generated written to the file: /tmp/unoconv.debug.txt.
In my case the output was:
Verbosity set to level 5
DEBUG: Connection type: socket,host=127.0.0.1,port=2002,tcpNoDelay=1;urp;StarOffice.ComponentContext
DEBUG: Existing listener not found.
DEBUG: Launching our own listener using /usr/lib64/libreoffice/program/soffice.bin.
Failed to connect to /usr/lib64/libreoffice/program/soffice.bin (pid=32012) in 6 seconds.
Connector : couldn't connect to socket (Success)
Error: Unable to connect or start own listener. Aborting.
The command ran seemed to fine as root, and as sudo -u nobody. On seeing this output I realized there was an issue with the home directory.
Kudos to Dag Wieers for his help - I'm hoping this helps other unoconv devs with their debugging.
I am running Apache on my localhost. From a PHP script run as www-user I would like to control Rhythmbox playback on my machine. So far I have a simple command in my PHP script:
exec('rhythmbox-client --pause');
This works great when I run it from the command-line as me, but if it runs as www-user I guess rhythmbox-client doesn't know/can't access my instance of Rhythmbox.
Is there an easy way for that PHP script to run as my user rather than www-user, or to tell rhythmbox-client which instance to control?
The overall application is that when my phone goes off-hook it calls my PHP script which pauses music, and resumes playback when the phone is on-hook. I love VoIP phones!
Solution:
Thanks to Carpetsmoker and Tarek I used sudo as the answer but there was a couple of problems. To overcome them I did the following:
Created a bash script to call rhythmbox-client. This bash script was executed using sudo in PHP as described in the answer below. Unfortunately rhythmbox-client didn't know what environment to control, so the bash script looks like this:
#! /bin/bash
DBUS_ADDRESS=`grep -z DBUS_SESSION_BUS_ADDRESS /proc/*/environ 2> /dev/null| sed 's/DBUS/\nDBUS/g' | tail -n 1`
if [ "x$DBUS_ADDRESS" != "x" ]; then
export $DBUS_ADDRESS
/usr/bin/rhythmbox-client --pause
fi
Now that bash script can be executed by PHP and wwwuser, and my phone can pause/play my music!
One solution is using sudo(8):
exec('sudo -u myuser ls /');
You will, obviously, need to setup sudo(8) to allow the user running your webserver to invoke it. Editing the sudoers file with visudo(8), you can use something like:
wwwuser ALL=/usr/bin/rhythmbox-client
To prevent Apache from being able to run other commands and only the rythymbox command.
In my case, the solution came this way:
Added this lines to sudoers file:
myuser ALL=(ALL) NOPASSWD: /usr/bin/prlctl
_www ALL=(ALL) NOPASSWD: /usr/bin/prlctl # IMPORTANT!!!
The EXEC() command in PHP was changed to:
exec("sudo -u myuser prlctl list -a", $out, $r);
If a process can be run by any user it can be run by PHP. Example is fortune command
-rwxr-xr-x 1 root root 18816 Oct 1 2009 /usr/games/fortune
Look at the x permission for every user. But this some times doesn't at all work and you may have to let the user, www-data or apache etc, run the program. You can sudo www-data and try to run the command. If it works then Apache/PHP should be able to run it.
I've made a simple bash script for server admininstration and I cannot figure how can I run it in safely inside a php page: I'd like to create a php admininstration page but I obviously don't want to hard-code root password anyware. Let's make an example (this is a foo script, of course)
#!/bin/bash
touch /$1
this simple/stupid script will not work if the user who run it as no writing permission on /.
Actually the script add apache virtualhosts, ftp users and so on...
any ideas?
thanks
Use
sudo /path/to/executable/file
and set up sudo so it can execute the following command for the current user as a root.
http://www.sudo.ws/sudo/sudoers.man.html - here is the sudoers manual, the configuration file, that you have to modify.
zerkms ALL = (ALL) NOPASSWD: /sbin/iptables -L FORWARD -n -v -x
This is example from my /etc/sudoers. Here I allowed to run command /sbin/iptables -L FORWARD -n -v -x as root without asking a password for user zerkms.