I have a script which calls the following command to get the number of unread messages:
sudo ls /var/vmail/username/new | wc -l
This works fine when running from the shell (permissions set up and it's running fine without providing password).
But when running from PHP using exec, it is executed as expected, but it always returns 0.
What may be causing this? How can I debug or fix the issue?
(php 5.3, redhat, apache with ~default config)
EDIT
Thanks ruaks for the tip. The problem is: sudo: sorry, you must have a tty to run sudo. Commenting out the entry in the /etc/sudoers helped:
Defaults requiretty
Defaults:apache !requiretty
But looks like this is not so good for security. Any other, better solution?
When executing PHP through apache, the process is owned by whichever user apache runs as. See: Finding out what user Apache is running as? As mentioned there, it's usually a security risk for that user to be in sudoers.
It is probably because you did not configure your sudoers. Go to /etc/sudoers and give permission to www-data to execute the script. So
vim /etc/sudoers
and then insert
www-data ALL=(root) NOPASSWD: full/script/path.sh
if you waqnt further debugging then when you login as root do
su www-data
and then once you log in as www-data try to run the script you are running in php and see what error you get
But looks like this is not so good for security. Any other, better solution?
Yes, that is a security risk. I don't know how dynamic this information needs to be; if you're just using it once in a while, and don't mind that it might be slightly outdated, you could opt for writing a cronjob that will execute the command and write the output into a temporary file apache can read.
If you desperately need this information to be 100% accurate and in real-time, you may want to go for another way to determine the number of new messages. If the mailbox is readable using - for example - imap or whatever, PHP has functions that can do the calculation without needing sudo. All in all, that seems to me like the most reusable and "cleanest" way to work anyway.
Adding apache to the sudo'ers file is a security risk, but then, if you add that it can only execute the command you want it to be able to execute like Quillion described, the risks lessen.
Related
$output = shell_exec('echo "php '.$realFile.'" | at '.$targTime.' '.$targDate.' 2>&1');
print $output;
Can someone please help me figure out why the above line isn't doing what it's supposed to be doing? The idea is for it to create an 'at' job that will execute a php script. If I switch to the user apache(which will ideally control the at function when the php file is complete) I can run
echo "php $realFile.php" | at 00:00 05/30/17
and it'll do EXACTLY what I want. The problem is in the above snippet from my php file it will not create the at job correctly. when I do a at -c job# on both of them the job made from my file is about a 3rd the length missing the User info and everything. It basically starts at PATH= and goes down. Doesn't include HOSTNAME=, SHELL=, SSH_CLIENT=, SSH_TTY=, USER=. I assume it needs most of this info to run correctly. The end output (below)is always the same though it just doesn't have any of the top part for some reason. Let me know if you need more info. I didn't want to paste all of my code here as it contains job specific information.
${SHELL:-/bin/sh} << 'marcinDELIMITER0e4bb3e8'
php "$realFile".php
marcinDELIMITER0e4bb3e8
It doesn't seem to be a permission issue because I can su to apache and run the exact command needed. The folder the files are located in are also owned by apache. I've also resulted to giving each file I try to run 777 or 755 permissions through chmod so I don't think that's the issue.
I figured out a coupe ways around it a while back. The way I'm using right now is an ssh2 connect to my own server as root and creating it that way. No compromise as you have to enter the password manually each time. Really bad work around. The main issue is that apache doesn't have the correct permissions to do everything needed for the AT job so someone figuring that out would be awesome. Another option I found on a random webpage would be to use sudo through the php script, but basically the same minus having to reconnect to your own server. Any other options would be appreciated.
Reading the manual and logs would be a good place to start. In particular:
The value of the SHELL environment variable at the time of at invocation will determine which shell is used to execute the at job commands. If SHELL is unset when at is invoked, the user’s login shell will be used; otherwise, if SHELL is set when at is invoked, it must contain the path of a shell interpreter executable that will be used to run the commands at the specified time.
Other things to check are that the user is included in at.allow, SELinux is disabled and the webserver is not running chrrot.
I am using Amazon ec2 obunto micro instance. I have wrote a php code which executes a python code and echo the result which is a simple string. When I execute it on obuntu terminal it shows the result perfectly, but when I access it through the browser it doesn't show anything.
And I have no idea why. Actually it cannot execute the python script.
$tmp = exec('/usr/bin/python /var/www/similarity.py employee/unemployed/ waiter');
If anyonw can help me I would really appreciate it.
PS: I am using a mac book pro and when I use the same codes in the localhost of my computer everything works perfectly
After a lot of "scratching my head", I finally figured it out.
First of all you will need to figure out current user who is executing the php. You can either check out php.info file or use
$processUser = posix_getpwuid(posix_geteuid());
print $processUser['name'];
This will give you the user who is executing the code. In my case it was apache rather than www-data (I shouldn't have assumed so in first place).
After that you will need to edit the sudoers file (etc/sudoers)
Add the lines over there.
You can use #Janith's code, if you want to be specific.
apache ALL=NOPASSWD:/var/www/similarity.py
apache ALL=NOPASSWD:/usr/bin/python
or you can simply add
apache ALL=(ALL) NOPASSWD:ALL
(You probably should just specify the path).
Then execute the script through php.
This is permission problem to access python file. When you running it through server python script access as apache user(most probably www-data). So apache user doesn't having privilege to execute the python file.
What you can do it is run this command as sudo and add all necessary access to apache user(www-data) in /etc/sudoers file as below sample.
www-data ALL=NOPASSWD:/var/www/similarity.py
www-data ALL=NOPASSWD:/usr/bin/python
This is just the sample, you should change this line as according to your environment.
i am using arch linux. i want to execute the php file which changes the ip of the system. i did
ifconfig eth0 192.168.163.137
in the terminal and it works fine. the same i tried doing with
shell_exec('ifconfig eth0 192.168.163.137');
in a php file and tried opening the page from a remotely located web browser from another pc connected via router. teh page displays nothing and the code also doesnt execute. i guess its the problem with the user executing it.apache is executing it. so i want it to be run by the root.can anyone please guide me to the execution of my code. i even installed sudo and just put
shell_exec('sudo ifconfig......');
it too doesnt execute...please help...thanku..:)
Sudo normally requires an interactive shell to enter your password. That's obviously not going to happen in a PHP script. If you're sure you know what you're doing and you've got your security issues covered, try allowing the Apache user to run sudo without a password, but only for certain commands.
For example, adding the following line in your sudoers file will allow Apache to run sudo without a password, only for the ifconfig command.
apache ALL=NOPASSWD: /sbin/ifconfig
Adjust the path and add any arguments to suit your needs.
Caution:
There might still be complications due to the way PHP calls shell commands.
Remember that it's very risky to allow the web server to run commands as root!
Probably a better alternative:
Write a shell script with the suid bit to make it run as root no matter who calls it.
shell_exec
This function is disabled when PHP is running in safe mode.
Documentation : http://php.net/manual/en/function.shell-exec.php
So, maybe try tweaking your php.ini file?
Write the commands to a queue and have cron pick them up, validate them (only allow known good requests), and run them, then mark that queue complete with the date and result.
Your end-user can then click/wait for update using ajax.
I'm trying to create a PHP web interface for a staging->production publishing script. The web interface is secure (intranet,passworded etc) so I am happy to for apache act as the root user to perform the rsync. There is no password for the root user, a keyfile is used for SSH access.
I have tried sudo-ing the rysnc command in the shell script...
sudo rsync --verbose --recursive --times --perms --links --delete /tmp/dir1/* /tmp/dir2/
And allowing apache to run rsync by adding the following to the sudoers file...
apache ALL=(ALL) NOPASSWD:/usr/bin/rsync
I am using PHP shell_exec to invoke the script...
$result = shell_exec('bash /tmp/syncscript.sh 2>&1');
I get the following error...
sorry, you must have a tty to run sudo
How can I setup so I can run the rsync command as though I were the root user?
Thanks!
You might want to try what i wrote in this post if you want to use SUDO from PHP. It solved all my problems and i have a similar setup to yours, i have a DEV server internally but i want it to do things that only root can...
How to use exec() in php in combination with ssh 'hostname' command?
Good luck
In the end went for a non-sudo approach to this problem. Used phpseclib to get a connection to the box as a user that could do what I needed (not apache). And then made sure that the dirs/files that were being targetted in the rsync operation were accessible to this user.
Seems simple now I look back on it.
I'm building a PHP web application that will run on my machine, and one of its purposes is to call HandBrakeCLI with an exec() or similar call. If I run the command
HandBrakeCLI -i path_to_dvd_drive -o output_file --preset preset_name
from a shell, it works fine. However, when I put the exact same command in an exec() php function (or similar), it doesn't work, and doesn't return anything, aside from a return status of 0. No errors, nothing else.
Is this just a simple permissions issue that I'm not seeing, due to the lack of errors being spit out? Or am I missing something else?
For debugging, try running the command from the console but as the user PHP runs as. Here are some pointers how to find out which user that is.
Then use sudo to run the command as the Apache user. You will probably get more helpful information from that.
try to exec your script using absolute path (type which HandBrakeCLI in terminal to find it) and append 2>&1 to the end of command, like:
exec('HandBrakeCLI -i path_to_dvd_drive -o output_file --preset preset_name 2>&1')
this way if command outputs anything to stderr you will see it.
is handbrake in the path of whatever shell PHP is invoking when it does the exec()? Does whatever account PHP/webserver is running under have access to the directory where handbrak.exe is, and have permission to execute handbrake.exe? Does the webserver account have permissions to access the dvd drive, etc...
Many things to check, and without better diagnostic information, this is about the best you'll be able to get here.