0

Summary: I have a command that runs on a PHP page, called by Ajax.

Latest PHP example:

$linuxCmd = "cd ~/apps && node app.js > scr_log.log 2>&1 &";
exec($linuxCmd);

I've also tried:

$linuxCmd = "cd ~/apps && node app.js > scr_log.log 2>&1";
$linuxCmd = "cd ~/apps && node app.js &";
$linuxCmd = "cd ~/apps && node app.js > /dev/null 2>&1 &";
$linuxCmd = "cd ~/apps && node app.js 2>&1 /dev/null &";

And think over the past day I've covered every possible other combination of those commands. It seems that no matter what I've tried, the ajax success function on previous page does not run. I thought that running the process above in the background would let the PHP page return back to the ajax call on the javascript page and continue running scripts, but no luck.

I've also tried adding exit() and return() after the exec() function, but it's not reaching them.

Also, the script (app.js) runs in a loop. It is terminated when a value in the database changes as it checks that every time it runs in the loop. I also have a way to kill the process, which works fine and returns to the success function of that ajax request, because it just terminates the process.

To put it another way, I need the script that I'm running from PHP exec() to constantly run after started, but also need my front end javascript page to continue after starting that process in the backend.

I'm wondering if this is maybe not possible for some reason. And if so, if there is a better way than PHP's exec() function. Also tried shell_exec with a couple of the above combinations.

tim92109
  • 102
  • 9
  • 1
    What do you think `~` means? – miken32 Feb 12 '19 at 18:17
  • @miken32 user's home directory... home/app.js. That is also where log.log is located btw. Just tried "cd ~/apps && node app.js > ~/apps/scr_log.log 2>&1" in case that was what you were getting at. – tim92109 Feb 12 '19 at 18:24
  • What user though? – miken32 Feb 12 '19 at 18:24
  • Not root, but I have the exec function allowed by that user in the php.ini. The function does work. And the node script does run. And the log file does populate with output. But it 'locks up' the front end scripts. Maybe 'running in the background' doesn't necessarily release the PHP script. – tim92109 Feb 12 '19 at 18:28
  • Just to be clear, this has not been solved. Maybe it can't be solved, but need to move on. So I just took my ajax success function contents outside the ajax, wrapped it in a setTimeout function, and removed the ajax success function temporarily. Not satisfactory because if it doesn't run or throws an error, it will look like everything is fine in the UI. But have to move on. If I find a solution once I have time to come back to the issue, I'll post it. – tim92109 Feb 13 '19 at 18:47

1 Answers1

2

Tilde expansion is a function of the shell, not something intrinsic to Linux, so your script should not rely on it working. Even if that weren't the case, web servers generally run as a separate user that doesn't have a home directory. What you should do is use absolute paths throughout your script, and don't try to write into a user directory with the web server user.

<?php
$linuxCmd = "/usr/bin/node /home/user/apps/app.js > /var/log/scr_log.log 2>&1 &";
exec($linuxCmd);

Letting your web server write to /var/log may require some permissions tweaks, but best to put things where they belong. You don't want to give something exposed to the outside – like a web server – permissions to write into a sensitive location like a home directory.

As for how best to run the command persistently in the background, see the answers to this question. There's nothing in your code that would prevent an Ajax function from returning successfully; this would only happen if the address was wrong (i.e. 404) or an error occurred (e.g. 500.)

miken32
  • 42,008
  • 16
  • 111
  • 154
  • Thanks for that... did not know. My strong points are far from Linux. But... looking at my process manager in the VPS, I see that the process that the script starts (app.js), is started by the same user (lets just say 'user123') as everything else (cPanel, SSH access from powershell, login to AMP, etc.). And that's exactly where the script lies. For example, /user123/app/app.js. And I would think if the tilde was defining the wrong place, that the script would not run because it wouldn't be there, right? – tim92109 Feb 12 '19 at 18:43
  • So, does the above still hold true? Or should I be looking for something else in the case of the user being the same from the web app and the directory where the app is located? On a security note, it is by no means a public script. Most likely, I'll be the only person using the app. – tim92109 Feb 12 '19 at 18:44
  • I'm surprised to hear that, perhaps PHP invokes a shell to run the commands. Your server definitely does not have a standard configuration if your web server runs as a regular user. Regardless, using full path names is still a best practice, and just because (you think) you're the only one using something doesn't mean it isn't vulnerable to attack! I also added a link to another question about running things in the background. – miken32 Feb 12 '19 at 18:55
  • It does seem to be different. It's a managed VPS, though, so I didn't set it up. As per your comment previously regarding 404/500 error might break it... if I do something to the script that runs to purposely create an error, the Ajax success function runs properly. And when checking the log.log file, the error shows in there as it should. No PHP errors in the PHP error log. – tim92109 Feb 12 '19 at 19:08
  • If "the script that runs" means whatever you're running in the shell, then no it wouldn't affect anything in PHP because you're making no effort to determine if it runs successfully, let alone pass that information back to the client. – miken32 Feb 12 '19 at 19:10
  • Oh, and I'll worry about security later. I'm already dead in the water with this one single task and don't want to complicate it more. Would rather actually get this resolved first, then worry about security. Awesome link btw... a little more detailed than what I've been looking at previously. – tim92109 Feb 12 '19 at 19:11
  • Famous last words – miken32 Feb 12 '19 at 19:11
  • Maybe it's not running in the background then. Because breaking the node script allows PHP to continue after the exec function... in fact, I just tested that. I ran the front end javascript that calls the PHP script through the ajax call... then killed that user's process in WHM and PHP was relinquished to finish, returning to the Ajax success function. – tim92109 Feb 12 '19 at 19:15