I have been trying to execute a script using shell_exec() function in php:
I've written the following lines of code:
$command = "bash /path/to/my/script/ funciton_name() 2>&1";
echo shell_exec($command);
Inside the shell script I'm doing:
sudo rsync -avvc /source/path /destination/path
On executing this on the browser, I get the following error message:
sudo: no tty present and no askpass program specified
When I execute the same shell script on my server, it executes fine.
When I went through similar questions posted on this forum, I realised that I had to add the NOPASSWD line on my server which I found out has already been added in the following format:
User_Alias NOBODY=nobody,apache
NOBODY ALL=(ALL) NOPASSWD : /path/to/my/script
Also when I do:
echo shell_exec("whois");
I get the output as:
apache
Any assistance in overcoming this problem would be of great help.
sudo will require a TTY, even if you have set up it up to be passwordless, unless you explicitly do not require it. But as #Cfreak pointed out, it would be much better (simpler and safer) to avoid sudo by setting correct access rights (read it before continuing) in the first place.
rsync itself will not require root permissions on a sanely configured *nix install. To verify this, you can check that type -a rsync doesn't print anything weird like rsync is aliased to `sudo rsync' and that ls -l $(which rsync) prints sensible permissions (at least rx for everyone).
Related
Hoping someone can help me out here. Trying to run any command using exec() returns 126 and displays the same error message. I've narrowed it down to this pretty minimal test case.
root#test:~ $ sudo -u asterisk php -r 'exec("ls /", $out, $result); var_dump($result);'
sh: /bin/ls: Permission denied
int(126)
root#test:~ $ sudo -u asterisk ls /
bin boot dev etc home lib lib64 lost+found media mnt opt proc root sbin selinux srv sys tmp usr var
root#test:~ $ su -lc 'php -r '\''exec("ls /", $out, $result); var_dump($result);'\' asterisk
This account is currently not available.
SELinux and PHP safe mode are not enabled
permissions are fine on /, /bin/, and /bin/ls
asterisk is a system user created with this command: adduser -d /var/lib/asterisk -M -r -s /sbin/nologin asterisk
it works fine via Apache, which runs as this user
Every attempt to run any command returns permission denied and 126 as $?. The PHP config is pretty much as it shipped (Scientific Linux 6.7, PHP 5.4 via Remi package.)
Would appreciate some assistance (preferably the kind that would require some arcane knowledge, not the kind that means I missed something blindingly obvious!)
Edit: I can get it to work using su if I give the user a login shell:
root#test:~ $ usermod -s /bin/bash asterisk
root#test:~ $ su -c 'php -r '\''exec("ls /", $out, $result); var_dump($result);'\' asterisk
int(0)
However, this isn't my code so changing all the use of sudo to su is not likely to happen. Also, there shouldn't be anything stopping PHP from running this without a login shell.
You probably have enabled sudo option NOEXEC.
When this option is active, you can run command with high privilege, but cannot spawn other commands. This is (AFAIK) required to avoid an exploiter to gain a shell. Since you are using the asterisk user, this also makes much sense.
In your case, PHP command is granted the execution as asterisk user, but when it tries to spawn with exec, the command cannot be executed and it returns 126.
EDIT (as in comment below)
Adding this line to sudoers will solve this issue:
root ALL = (ALL) EXEC: ALL
Your account doesn't have permission to run bash commands.
As you know int(126) return the status of the executed command. From the bash man page:
If a command is found but is not executable, the return status is 126.
Try running ls directly from your asterisk user to see if it works.
If it doesn't work then check the permissions on your asterisk user and see if you have the necessary permissions. If you don't have the permissions, just use chmod to give your asterisk user permission. You should also try and create a new user and see if this command works with that user.
Edit: Since your asterisk account does not have a shell, you cannot execute shell commands from it.
Coming back to provide another answer to my own question a couple of years later. As the accepted answer supposed, I had set this in my file:
Defaults noexec
And I fixed this by overriding it for the root user.
But a better solution would be to apply the defaults only to the targeted user:
Defaults:admin noexec
This way the setting would not have affected the asterisk user I was having problems with in my question!
I'm trying to run a script as root user. here is my code
echo shell_exec("sudo bash.sh 2>&1");
It's giving error
sudo: no tty present and no askpass program specified
www-data is not in the sudoers file. This incident will be reported.
I've followed these methods as well but end up with no permission error
There are a couple of issues you might encounter:
The user that is running the php process must have sudo rights (check with visudoers command)
There is no environment set, so the $PATH variable does not include the path to the sudo command
sudo might require a password. Either change the sudoers file, adding NOPASSWORD, which would be hugely unsafe. Or you have to use pipes (proc_open), and pass the password through the stdin pipe
I've managed to find a way to do so, but after some help from people on this site:
load .profile with proc_open()
proc_open interaction
I'm trying to get a sudo command to execute from within PHP. For simplicity sake, I'm using passthru wrapped in pre tags. Long story short, I want to get some exim stats.
I'm on a CentOS box.
After logging in via shell, I added the following line via visudo.
myuser ALL = NOPASSWD: /usr/sbin/exiwhat
I can successfully execute the exiwhat command using either of the following commands when shelled in.
sudo -u myuser -H /usr/sbin/exiwhat
sudo -u myuser -H exiwhat
I've even tried becoming the the user via su and am still successful.
su myuser
sudo /usr/sbin/exiwhat
-or-
sudo exiwhat
My php script looks a little something like this.
<?php
echo '<pre>';
passthru('whoami');
echo "\n1)";
passthru('sudo exiwhat');
echo "\n2)";
passthru('sudo /usr/sbin/exiwhat');
echo "\n3)";
passthru('exiwhat');
echo "\n4)";
passthru('/usr/sbin/exiwhat');
echo "\n";
echo '</pre>';
All I get back is:
myuser
1)
2)
3)
4)No exim process data
I've tried the same with
exec('exiwhat',$output);
but output returns as an empty array.
I can get simple things like "ps aux" or "dir" to work just fine. Please help.
Possible Duplicate: How to call shell script from php that requires SUDO?
Note: I can run exiwhat via command line and get a good chunk of output. We have several hundred emails in the queue at any point in time.
UPDATE:
Per another thread, I added " 2>&1" to each command and got the following
myuser
1)sudo: sorry, you must have a tty to run sudo
2)sudo: sorry, you must have a tty to run sudo
3)sh: exiwhat: command not found
4)/bin/rm: cannot remove `/var/spool/exim/exim-process.info': Permission denied
exim(770): Operation not permitted
exim(8016): Operation not permitted
exim(15618): Operation not permitted
exim(15626): Operation not permitted
exim(16751): Operation not permitted
exim(16765): Operation not permitted
exim(32207): Operation not permitted
exim: no process killed
No exim process data
UPDATE:
I added the following line via visudo and my sudo commands now work
Defaults:myuser !requiretty
Is that save to leave like that though?
Edit your /etc/sudoers file and remove the line about Default requiretty.
**Update I guess this options enabled by default so add something like the following instead:
Defaults:myuser !requiretty
I have a script in /var/www/myscript.sh which creates folders and runs the command svn update for my projects. I need to execute this script by calling it in a PHP file in the browser (i.e. Localhost/test.php). I tried using functions shell_exec() and exec() but those did not work. I ran my shell script in terminal with su www-data && ./myscript.sh and it worked. What else am I missing?
<?php
$output = shell_exec("./myscript.sh");
?>
Update 5/4/2011:
I added www-data ALL=(ALL) NOPASSWD:ALL to /etc/sudoers and it works, but this is very insecure. Is there another way to do this?
Several possibilities:
You have safe mode enabled. That way, only exec() is working, and then only on executables in safe_mode_exec_dir
exec and shell_exec are disabled in php.ini
The path to the executable is wrong. If the script is in the same directory as the php file, try exec(dirname(__FILE__) . '/myscript.sh');
You might have disabled the exec privileges, most of the LAMP packages have those disabled. Check your php.ini for this line:
disable_functions = exec
And remove the exec, shell_exec entries if there are there.
Good Luck!
Residuum did provide a correct answer to how you should get shell exec to find your script, but in regards to security, there are a couple of points.
I would imagine you don't want your shell script to be in your web root, as it would be visible to anyone with web access to your server.
I would recommend moving the shell script to outside of the webroot
<?php
$tempFolder = '/tmp';
$webRootFolder = '/var/www';
$scriptName = 'myscript.sh';
$moveCommand = "mv $webRootFolder/$scriptName $tempFolder/$scriptName";
$output = shell_exec($moveCommand);
?>
In regards to the:
i added www-data ALL=(ALL) NOPASSWD:ALL to /etc/sudoers works
You can modify this to only cover the specific commands in your script which require sudo. Otherwise, if none of the commands in your sh script require sudo to execute, you don't need to do this at all anyway.
Try running the script as the apache user (use the su command to switch to the apache user) and if you are not prompted for sudo or given permission denied, etc, it'll be fine.
ie:
sudo su apache (or www-data)
cd /var/www
sh ./myscript
Also... what brought me here was that I wanted to run a multi line shell script using commands that are dynamically generated. I wanted all of my commands to run in the same shell, which won't happen using multiple calls to shell_exec(). The answer to that one is to do it like Jenkins - create your dynamically generated multi line of commands, put it in a variable, save it to a file in a temp folder, execute that file (using shell_exec in() php as Jenkins is Java), then do whatever you want with the output, and delete the temp file
... voila
If you are having a small script that you need to run (I simply needed to copy a file), I found it much easier to call the commands on the PHP script by calling
exec("sudo cp /tmp/testfile1 /var/www/html/testfile2");
and enabling such transaction by editing (or rather adding) a permitting line to the sudoers by first calling sudo visudo and adding the following line to the very end of it
www-data ALL=(ALL) NOPASSWD:/bin/cp /tmp/testfile1 /var/www/html/testfile2
All I wanted to do was to copy a file and I have been having problems with doing so because of the root password problem, and as you mentioned I did NOT want to expose the system to have no password for all root transactions.
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.