php exec() function and different hosts

2020-04-11 19:10发布

I have a script that executes a file in a couple of directories down which looks like this:

exec("php-cli $file_path > /dev/null 2>/dev/null &"); //php command-line

This works on most hosts but some hosts don't like it and it doesn't run, without generating any error.

For the hosts that this fails on, i use

exec("php $file_path > /dev/null 2>/dev/null &"); //notice the -cli is gone

Which works fine.

$file_path is the full path to the file being executed /home/blah/path/blah.php

How can i make this uniform so it works on all servers (unix at least)

**EDIT**

Well, I'm doing it this way, it is (most likely) not the correct way but it works.

Instead of just using php-cli or php, i use both so if one fails, the other goes through. Either the php is running as cgi or cli and one of these will catch, and since there is no output, there would be no error either.

exec("php-cli $file_path > /dev/null 2>/dev/null &");
exec("php $file_path > /dev/null 2>/dev/null &");

Unless you know a better solution please let me know. Thanks for all your help.

3条回答
Luminary・发光体
2楼-- · 2020-04-11 19:14

Simple question perhaps, but does php-cli exist on all the hosts? I assume the reason its failing silently is because you're telling it to be redirecting everything away.

exec("php $file_path > /some/writable/path/output.log 2>/some/writable/path/error.log &");
查看更多
手持菜刀,她持情操
3楼-- · 2020-04-11 19:19

It depends on how the PHP-CLI binary is compiled. On most systems the executable is named just 'php' and I guess that the hosts that have 'php-cli' have it compiled by hand, while most of the others have it installed via the OS package manager.

You have two options to work around that and make it "universal":

  1. On each of the servers, add an alias for one of them where needed, or make a symlink to the PHP executable somewhere (e.g. in your home directory).
  2. Prior to executing, check which one of them exists (usually, it should be located in /usr/bin/) and set it to a variable.
查看更多
Deceive 欺骗
4楼-- · 2020-04-11 19:28
function php_exec($file_path) {
    if (!($binary = which(array('php', 'php5', 'php-cli', 'php-cgi'))))
        return false;

    return exec("$binary $file_path > /dev/null 2>/dev/null &");
}

function which($binaries) {
    if (!($path = getenv('PATH')) && !($path = getenv('Path')))
        return false;

    $arr = preg_split('/[:;]/', $path);

    foreach ($arr as $p) {
        foreach ($binaries as $b) {
            if (file_exists("$p/$b"))
                return "$p/$b";
        }
    }   

    return false;
}

var_dump(php_exec('test.php'));

Explanation: On most systems the PHP binary is called php, php5, php-cli or php-cgi. which() function checks the standard path (both *nix and windows have environment variable called PATH/Path) for each of those names and if it find a file with such name, it will return it.

The PATH variable's format is: /bin:/usr/bin:/usr/local/bin:/sbin:/usr/sbin:/usr/local/sbin for *nix (bash), and C:\Windows\System32\;C:\Windows\; for windows, so that's why I use preg_split('/[:;]/')

This solution is better than yours, because php_exec() will return false if it can't find a valid php binary. In your solution there's no way to know if the script execution failed.

查看更多
登录 后发表回答