Editing a users crontab via bash script called via PHP - php

I am attempting to create a user and add an entry to a users crontab (any user on the system) via a PHP script (running on the same server) which calls a bash script.
I have solved the problem about creating a user, this works OK, but the last line in the bash script to add an entry to that new users crontab does not work when called via the PH script. I have confirmed that it does work when run locally.
I have the following PHP script:
<?php
//system("whoami");
chdir('/var/www/html/sandpit/users/');
$user = "test2";
$user=escapeshellarg($user);
$output = shell_exec("./create_user.sh $user");
echo "<pre>$output</pre>";
//echo "<br>ends";
?>
And the content of create_user.sh is :
#!/bin/bash
export user=$1
sudo /usr/sbin/useradd $user -M
sudo echo "0 1 * * * /root/test.sh" | tee -a /var/spool/cron/crontabs/test2
In the last line I have hardcoded the variable into the actual name 'test2' to deal with one issue at a time, though I know $user to contain 'test2' because it correctly creates the user.
I have added these line to /etc/sudoers:
www-data ALL=(ALL:ALL) ALL
www-data ALL=(ALL) NOPASSWD: ALL
So my question is, why does the last line to edit the users crontab work when run locally (as root) but not run when called via the script? I assume that it is a permissions issue as I know the command line to work correctly as it runs manually.
Any help would be appreciated. Thanks.

You need sudo for tee not for echo. tee is not executed with root privileges.

Related

Execute php file from bash script as www-data using crontab

I am trying to run a php file every night at a certain time using crontab, however the php needs to be running as a www-data because of the directory permissions. To run it as www-data I am using the root crontab and changing the user in there, like so:
* 20 * * * sudo -u www-data /usr/bin/env TERM=xterm /path/to/dailyProc.sh
dailyProc is as follows
today=`date +"%d%m%y"`
year=`date +"%y"`
dm=`date +"%m%d"`
`tar -zxf /path/to/input/$today.tgz -C /path/to/output`
echo "starting data proc"
`/usr/bin/php5 -f /path/to/dataproc.php date=$dm year=$year`
echo "data proc done"
All other commands in dailyProc.sh work but the php doesnt run. The php is using an output buffer and writing it to a file, which works fine calling it from the command line but doesnt work when calling by cron.
I can also definitely run dailyProc.sh from the command line as www-data using
sudo -u www-data dailyProc.sh
and everything works as expected.
Is there any reason I would not be able to run this php file in dailyProc.sh using crontab when everything else in it works?
Cron can be run per user too.
crontab -u www-data -e
This works for me:
* 20 * * * su - www-data -C "/path/to/dailyProc.sh"
You do not need to use su or sudo in a crontab entry, because the 6th column is for the user name anyway. And you don't need to start a terminal, because you won't see it anyway. Hence, the following should do:
* 20 * * * www-data /path/to/dailyProc.sh
The Syntax error: word unexpected… you mentioned in a comment appears to be inside your code. Try running the script from the command line and start debugging from there.
To do this I used curl inside dailyProc.sh
today=`date +"%d%m%y"`
year=`date +"%y"`
dm=`date +"%m%d"`
`tar -zxf /path/to/input/$today.tgz -C /path/to/output`
echo "starting data proc"
`/usr/bin/curl "myserver.com/dataproc.php?date=$dm?year=$year"`
echo "data proc done"

Run bash script from php as another user

I would like to run a bash script without opening a terminal in my Ubuntu system. Some other users will have to daily check and run that process. So I thought I could build a simple php website that could run the script. After some reading here at Stack Overflow and googleing I thought shell_exec could do the trick. But as I don't want to give permissions in some directories to www-data I want to run the scripts as the owner, user meteo.
This is my php:
$autput = shell_exec('date +%d/%m/%Y-%H:%m');
echo "<pre>Hora de inicio: $autput</pre>";
$output = shell_exec('/home/meteo/RAMS/SCRIPTS/RAMS_operatiu.bash');
echo "<pre>".$output."</pre>";
The content of sudoers file, sudo visudo
meteo ALL = NOPASSWD: /home/meteo/RAMS/SCRIPTS/RAMS_operatiu.bash
www-data ALL = NOPASSWD: /home/meteo/RAMS/SCRIPTS/RAMS_operatiu.bash
This way, www-data user runs my script (RAMS_operatiu.bash) but as this script runs an mpich job it has to check mpd.conf then the script crashes as there is not such file for www-data. It actually exists for meteo. So I would like to run as meteo better than www-data. I tried to use
$output = shell_exec('sudo -u meteo /home/meteo/www/RAMS/inicio_RAMS.sh');
but can't find the point to tell the php script to run as meteo, not www-data. Is this possible? Probably I am missing something.
Thank you very much for your help.

php system commands linux

I have set of linux system commands that requires to be logged into shell first.
How can i do that in php ?
For example:
$output2 = shell_exec('ls -lrt /opt/test 2>&1');
Since /opt/test can be accessed by user/owner XXX only, I need to login with that username.
runuser command could be helpful but i need directions.
Actually I need to run an application via system command but before that user must be logged in to have access to that application.
One way to do it would be to create a shell script containing all of the commands that you need to run as the privileged logged in user, and then run that shell script using sudo.
You will need to change your sudoers file so that the execution of the script can be run by the user that the script is running as.
eg:
Cmnd_Alias HTTP_COMMANDS = /usr/local/my_ls_script
XXXX ALL=(ALL) NOPASSWD: HTTP_COMMANDS
Be careful when doing this though! Make sure that the sudoers line can only run the commands that you specify.
Also, make sure that you switch to the user at least once, and run sudo, otherwise, the webserver will not be able to run sudo for the user.
Additionally, you might need to disable NO_TTY in the sudoers file.
You would change your command to:
$output2 = shell_exec('sudo -u XXXX /usr/local/my_ls_script 2>&1');

Running command-line application from PHP as specific user

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.

sudo in php exec()

I don't know what the deal is here…
So I want to run an applescript: sudo osascript myscript.scpt
This works fine in the terminal, but not when I execute it via PHP's exec(); nothing happens. The console says
no tty present and no askpass program specified ; TTY=unknown ; …
I did my research, and it seems I'm missing the password for the sudo command. I tried a couple different ways to get around this, including:
writing %admin ALL=(ALL) ALL in /etc/sudoers
and proc_open() instead of exec()
none of which seem to be working, consequently driving me CrAzY!
So basically, is there a clear-cut way to get PHP to execute a simple terminal command?
EDIT: to clarify, myscript.scpt is a simple appleScript that changes the onscreen UI (for a larger project). In theory, simply osascript myscript.scpt should be enough, however the sudo is for some reason necessary to invoke some response from the system. If the sudo could be somehow eliminated, I don't think I would be having this permissions problem.
It sounds like you need to set up passwordless sudo. Try:
%admin ALL=(ALL) NOPASSWD: osascript myscript.scpt
Also comment out the following line (in /etc/sudoers via visudo), if it is there:
Defaults requiretty
I think you can bring specific access to user and command with visudo something like this:
nobody ALL = NOPASSWD: /path/to/osascript myscript.scpt
and with php:
#exec("sudo /path/to/osascript myscript.scpt ");
supposing nobody user is running apache.
php: the bash console is created, and it executes 1st script, which call sudo to the second one, see below:
$dev = $_GET['device'];
$cmd = '/bin/bash /home/www/start.bash '.$dev;
echo $cmd;
shell_exec($cmd);
/home/www/start.bash
#!/bin/bash
/usr/bin/sudo /home/www/myMount.bash $1
myMount.bash:
#!/bin/bash
function error_exit
{
echo "Wrong parameter" 1>&2
exit 1
}
..........
oc, you want to run script from root level without root privileges, to do that create and modify the /etc/sudoers.d/mount file:
www-data ALL=(ALL:ALL) NOPASSWD:/home/www/myMount.bash
dont forget to chmod:
sudo chmod 0440 /etc/sudoers.d/mount
I recently published a project that allows PHP to obtain and interact with a real Bash shell. Get it here: https://github.com/merlinthemagic/MTS
The shell has a pty (pseudo terminal device, same as you would have in i.e. a ssh session), and you can get the shell as root if desired. Not sure you need root to execute your script, but given you mention sudo it is likely.
After downloading you would simply use the following code:
$shell = \MTS\Factories::getDevices()->getLocalHost()->getShell('bash', true);
$return1 = $shell->exeCmd('/path/to/osascript myscript.scpt');
Run sudo visudo command then set -%sudo ALL=(ALL:ALL) to %sudo ALL=(ALL:ALL) NOPASSWD: ALL it will work.
I had a similar situation trying to exec() a backend command and also getting no tty present and no askpass program specified in the web server error log. Original (bad) code:
$output = array();
$return_var = 0;
exec('sudo my_command', $output, $return_var);
A bash wrapper solved this issue, such as:
$output = array();
$return_var = 0;
exec('sudo bash -c "my_command"', $output, $return_var);
Not sure if this will work in every case. Also, be sure to apply the appropriate quoting/escaping rules on my_command portion.
The best secure method is to use the crontab. ie Save all your commands in a database say, mysql table and create a cronjob to read these mysql entreis and execute via exec() or shell_exec(). Please read this link for more detailed information.
killProcess.php
I think directly calling a sudo command might be difficult because you are setting up the whole server to work without a password.
Perhaps as an alternative you could setup a CRONjob as root and monitor a flag file. Once the flag file exists it will run the osascript myscript.scpt and then delete the flag file.
This way you will keep SUDO secure from a config point of view and the server safer. To run the script you just need to touch the flag file from PHP.
It would of course introduce a delay of however many minutes you running the CRON job. It would also mean that you would have to redirect the output to a file and have a async monitor of the output, but it will depend on your application if this is a problem or not.
But it is an alternative that might protect the server.

Categories