0

I'm in a situation where I personally don't have access to anything but my own public html folder and sub folders, so I have to rely on the guy who owns the account to set up a cron job for me. Neither one of us had ever done this before, so we have been learning through trial and error. The file to run is a php file, but we are trying to run it through the direct path instead of using curl or wget.

At first he was getting emails that said

/usr/local/cpanel/bin/jailshell: /home/[accountname]/public_html/[domain].com/[subfolder]/[filename].php: Permission denied

(The parts in brackets are changed to protect the privacy of the owner.)

After a while the emails stopped coming. I did more googling and realized that first of all, I have to set permissions to execute the file by users other than myself (I assume he is using root), so I edited the chmod to 755. Then I realized that we were trying to access the file directly instead of through php, so I told him to add usr/bin/php before the path to the file. He is editing the crontab through a form in Cpanel rather than using shell, so the minute is 1, all the other time things are * and command is now usr/bin/php /home/[accountname]/public_html/[domain].com/[subfolder]/[filename].php I asked him if he's getting the same error message as before or if something changed, but he said he is no longer receiving any emails at all. So it sounds like cron spontaneously stopped trying to execute the file back when the command was formatted wrong and didn't start again when the usr/bin/php part was added. The php script itself is supposed to add action points to characters in a game and output the number of characters that got points added (if you are already at maximum, you don't count). It has this line in the beginning:

include_once($_SERVER['DOCUMENT_ROOT']."/_private/class_character.inc.php");

I've been thinking that it might have trouble including files because class_character.inc.php in turn contains several includes of other files, which are referred to just by the filename, so the idea is that it would search for them inside _private, but I've been thinking what if it searches for them in where ever the crontab is located instead? However, if there was a problem with the file, the emails would contain warnings or error messages, but it seems it never got as far as running the file in the first place. I assume it can no longer be a permissions issue because chmod is 755. I can run the file by typing in the url, and then it doesn't cause any errors and does what it's supposed to, so if there's anything wrong with the file itself, it's in the scope of includes.

Also I read on one site that the account that the public_html folder is associated with needs to be in a user group called cpaneluser or something like that. But I assume that even if the user group was undefined, it would still be executable now because world right to execute is also set.

Contents of the file it is trying to run:

<?
include_once("../_private/class_character.inc.php");
include_once "../_private/abbr.inc.php";
include_once "../root.inc.php";

$mysqli = new mysqli("localhost", "ACCOUNT", "PASSWORD", "DATABASE");

function getLiveCharacters($mysqli) {
$retArr = array();
$sql = "SELECT `uid` FROM `chars` WHERE `status`=1 ORDER BY `uid`";
$result = $mysqli->query($sql);
if (mysqli_num_rows($result)) {
while ($row = mysqli_fetch_row($result)) {
$retArr[] = $row[0];
}
return $retArr;
}
else return false;      
}

function doLoop($mysqli) {
$chars = getLiveCharacters($mysqli);
if (!$chars) return 0;
$counter = 0;
foreach ($chars as $ci) {
$c = new Character($mysqli, $ci);
$result = $c->rest_auto();
if ($result>0) $counter++;
}
return $counter;
}

$result = doLoop($mysqli);

echo $result;

?>

Parts of class_character related

<?

public function rest_auto() {
$oldAP = $this->getAP();
if ($oldAP>=1000) return 0;
$ap = $this->getRestAP();
if ($oldAP+$ap>1000) $ap = max(0, 1000-$oldAP);
$pos = $this->getPosition();

$this->updateCharLocTime($pos->x, $pos->y, $pos->lx, $pos->ly, 0, 5, $ap);

if ($oldAP==-1) {
$sql = "INSERT INTO `char_ap` (`rowID`, `charFK`, `ap`) VALUES (NULL, '$this->uid', '$ap')";
$this->mysqli->query($sql);
}
else if ($ap>0) {
$sql = "UPDATE `char_ap` SET `ap`=`ap`+$ap WHERE `charFK`=$this->uid LIMIT 1";
$this->mysqli->query($sql);
}
return $ap;
}

function getRestAP() {
        //automatic resting is triggered once per real life hour
        //Starts from 250 AP/rl hour
        $ap_rec = 250;
        $pos = $this->getPosition();
        $curTime = new Time($this->mysqli); 
        $currentLocation = new GlobalMap($this->mysqli, $pos->x, $pos->y);
        $local = new LocalMap($this->mysqli, $pos->x, $pos->y);
        $pixArr = $currentLocation->getMajorPixel($currentLocation->x, $currentLocation->y);
        $timeofday = $curTime->getTimeofDay($pos->x, $pos->y);
        $weather = $curTime->getWeather($pos->x, $pos->y, $timeofday, $currentLocation->getTerrains($pixArr["x"], $pixArr["y"]), $currentLocation->getWaterLevel($pixArr["x"], $pixArr["y"]));
        $bodyObj = new Obj($this->mysqli, $this->bodyId);
        $blood_per = $bodyObj->getBloodPercentage($this->uid);

        //-10 if you don't have a bed
        $beds = $local->checkBed($pos->lx, $pos->ly);
        if ($beds == -1) $ap_rec -= 10;
        //-10 if you don't have shelter
        $ap_rec -= 10;//No shelter has been implemented yet
        //-10 if it's raining and you don't have shelter
        if ($weather["rain"]>0) {
            $ap_rec -= 10;
        }
        //-10 if you are cold
        if ($weather["temp"]<16) {
            $minus = max($weather["temp"]-16,-10);
            $ap_rec += $minus;
        }
        //-10 if you are too hot
        if ($weather["temp"]>36) {
            $plus = max(($weather["temp"]-36)*2,10);
            $ap_rec -= $plus;
        }
        //-10 if you're hungry
        //Hunger isn't implemented yet
        //-10 if you are wounded
        if ($blood_per<95) {
            $minus = round(($blood_per-96)/2);
            $ap_rec += $minus;
        }

        return $ap_rec;
    }
?>

Actually I'm not going to start posting every function that is called in another function because that would take ages. The point is it works when run in the browser, so if something is not compatible when not run through a browser, that is pretty annoying. Of course I could go and change the command to use curl but that still does not explain why it was sending emails in the first place, then stopped.

  • `$_SERVER['DOCUMENT_ROOT']` doesn't exist when using the CLI. Try using a relative or absolute path to the included file instead. – aynber Apr 28 '17 at 13:39
  • Thanks, that is good to know. I'll go change that. – Ilona Ward Apr 28 '17 at 13:40
  • If you have access to the command line, try running the command yourself to make sure everything works as it should. If the command works for you, then cron should run it. If you don't have access to the command line, try running it locally. It should work the same as on the server. – aynber Apr 28 '17 at 13:52
  • I don't have access to command line. I do everything through ftp and have to rely on the guy who pays for the server on anything outside public html. I don't think I can run it locally because I don't have Linux. I'm on Windows, and the local setup where I test things is using Apache. Or did I misunderstand what you meant? – Ilona Ward Apr 28 '17 at 15:57
  • You can set up a VM with linux for testing purposes, or install PHP for Windows. – aynber Apr 28 '17 at 16:09
  • Correct me if I'm wrong but wouldn't the path to php and file path be different than on the web server? I don't think it's a syntax issue, I think something else is wrong. It seems suspect that cron spontaneously stopped sending emails. You'd think it would always at least email an error message. – Ilona Ward May 14 '17 at 13:11
  • The path to PHP is usually the same or similar, but yes, the file path would be different. The key into make sure the script works at all. If it works locally, then barring a few configuration issues, it *should* work on the server. – aynber May 15 '17 at 12:35
  • I was able to run it through cmd on Windows by referencing C:\xampp\php\php.exe Turns out it's searching for the includes inside php/PEAR instead of the parent folder of the folder where the script is located. I changed the paths to absolute and now it works through cmd. This might potentially be a duplicate of this: https://stackoverflow.com/questions/1969374/relative-path-not-working-in-cron-php-script although I still don't know why it stopped sending emails. – Ilona Ward May 23 '17 at 17:25

0 Answers0