sudo in php exec()

2018-12-31 16:50发布

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.

标签: php linux sudo
7条回答
唯独是你
2楼-- · 2018-12-31 17:09

Run sudo visudo command then set -%sudo ALL=(ALL:ALL) to %sudo ALL=(ALL:ALL) NOPASSWD: ALL it will work.

查看更多
十年一品温如言
3楼-- · 2018-12-31 17:15

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');
查看更多
不流泪的眼
4楼-- · 2018-12-31 17:20

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.

查看更多
荒废的爱情
5楼-- · 2018-12-31 17:25

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
查看更多
荒废的爱情
6楼-- · 2018-12-31 17:29

If anyone still requires this. You can write a plain text file, say ~./.sudopass/sudopass.secret, with the root password there. Let's say the root password is '12345'. You create ~./.sudopass/sudopass.secret with only '12345' as its content:

12345

And then you do the following:

exec('sudo -u root -S {{ your command }} < ~/.sudopass/sudopass.secret');

Remember to use this only in controlled environments.

查看更多
琉璃瓶的回忆
7楼-- · 2018-12-31 17:29

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);
  1. /home/www/start.bash

    #!/bin/bash
    /usr/bin/sudo /home/www/myMount.bash $1
    
  2. 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
查看更多
登录 后发表回答