I read nearly all topics concerning wkhtmltopdf, but my problem still exists. Actually it's not a wkhtmltopdf problem, but a permission problem.
To sum it up: wkhtmltopdf works in the command line, but not with PHP exec().
But wget works fine with php exec():
I can execute wkhtmltopdf in the command line, works fine:
/usr/local/bin/wkhtmltopdf "test.html" "/var/www/html/test/test.pdf"
exec( "/usr/local/bin/wkhtmltopdf --enable-plugins --encoding UTF-8 --javascript-delay 2000 --load-error-handling ignore --disable-smart-shrinking --image-quality 100 --orientation Portrait --minimum-font-size 10 --header-spacing '0' --margin-top '15mm' --header-html '/tmp/1568618584_generated.html' --footer-left 'Accume Partners Risk Director' --footer-right 'Residual Risk Report -- Page [page] of [toPage]' --footer-font-size '8' --footer-line /tmp/1568618584_generated.html /tmp/R_RM_2110_Residual_Risk_Report.pdf 2>&1", $output, $pdfGenerateStatus);
print_r($output).'<br>';
echo $pdfGenerateStatus;
it's return Array
( [0] => sh: /usr/local/bin/wkhtmltopdf: Permission denied ) 126 error.
I am using wkhtmltopdf 0.12.4 (with patched qt).
Also,
I have set 777 permission to /usr/local/bin/wkhtmltopdf but did not work.
Related
I am trying to execute a couple of scripts by using a remote interface. The environment is Raspbian on a Raspberry Pi (although I will be using Debian later as well) running LAMP.
The files are test.php and test.sh in the root directory of the webserver (say example.com)
test.sh
#!/bin/bash
sudo pkill chromium-browse
sudo reboot
test.php
<?php
$output=null;
$resultCode=null;
exec("./test.sh", $output, $resultCode);
// $ouptut = shell_exec('./test.sh 2>&1'); //tried this too
// echo shell_exec("./test.sh"); // as well as this
echo "Returned with status $resultCode and output:\n";
print_r($output);
?>
Initially, I had used
chmod u+x test.sh
but got an error code of 126. So I did this:
chmod 777 test.sh
Now I get an error code of 1, but it still doesn't execute. I have also tried
sudo visudo
then added
pi ALL=(ALL) NOPASSWD: ALL
(pi is the current loggedin user)
Currently I am getting this:
Array
(
[0] =>
[1] => We trust you have received the usual lecture from the local System
[2] => Administrator. It usually boils down to these three things:
[3] =>
[4] => #1) Respect the privacy of others.
[5] => #2) Think before you type.
[6] => #3) With great power comes great responsibility.
[7] =>
[8] => sudo: no tty present and no askpass program specified
)
Note: I use sudo all the time at the command line without being asked for a password.
I do have another php file in the same directory that executes an actual system command successfully. It has this line:
$uptime = exec("uptime");
which works just fine, so I know system commands are possible. Is there any way to do this? I have seen other similar questions on SO and other sites, but none of those answers have worked for me.
Any help appreciated.
Every time I execute my script with:
exec('sudo profile status-koneksi',$status);
print_r($status);
it always does nothing, I have no idea how to debug this one, my script requires root permission so I appended the following lines to /etc/sudoers file:
Cmnd_Alias ANGEL_BEATS = /usr/bin/profile, /usr/bin/socks, /usr/bin/gsm, /usr/bin/gssh, /usr/bin/ping_loop, /usr/bin/restart-openvpn, /usr/bin/sms.py, /usr/bin/sms_gateway, /usr/bin/socks, /usr/bin/ussd.py, /usr/bin/vpn, /usr/bin/wgetui
ab ALL=NOPASSWD: ANGEL_BEATS
%ab ALL=NOPASSWD: ANGEL_BEATS
However, it works just fine when I execute the command from my terminal:
How do I solve this ?
UPDATE:
As suggested by a comment below, I run this script:
if(exec("sudo sh /usr/bin/profile status-koneksi 2>&1", $output, $return_var)){ print_r($output); print_r($return_var); }
And it returns:
Array ( [0] => sudo: no tty present and no askpass program specified ) 1
Since your script requires root permission to run, it would be nice if you could set the setuid bit. Try this:
chmod u+s <your_script>
More info here (from Wikipedia)
On my server (Ubuntu 14.04.4 LTS), I have a Firefox installed, as well as xvfb for headless Firefox operation, and CasperJS with SlimerJS. I also have a CasperJS script which works fine. I want to utilize this script from PHP; this is the essence of my PHP script for this, let's call it mytest.php:
echo "php_sapi_name() " . php_sapi_name() . "\n"; // "cli" for php cli, "apache2handler" for php via webserver
chdir(dirname(__FILE__));
$nodeModPath = "/home/USERNAME/.nvm/versions/node/v4.0.0/lib/node_modules";
putenv("SLIMERJSLAUNCHER=/usr/bin/firefox46");
$cmdline = "xvfb-run $nodeModPath/casperjs/bin/casperjs --engine=slimerjs --debug=true mySlimerScript.js";
$returnString = shell_exec($cmdline);
echo "$returnString\n";
EDIT: Note that the command could as well be just:
$cmdline = "xvfb-run $nodeModPath/casperjs/bin/casperjs --engine=slimerjs --debug=true 2>&1";
... that is, without any JS script listed - in which case the help should be dumped (and is, in case of CLI access - but the same error as below is reported when accessing through webserver)
When I run this PHP script from the terminal command line (via SSH), that is through PHP in CLI mode:
$ php mytest.php
... everything runs fine, there is no problem whatsoever.
However, when I invoke this PHP script online through the webserver, that is via http://example.com/mytest.php, it fails first with the error:
Gecko error: it seems /usr/bin/firefox46 is not compatible with SlimerJS.
See Gecko version compatibility. If version is correct, launch slimerjs
with --debug=true to see Firefox error message
... and after adding --debug=true (as already included in the example above), I additionally get this error:
JavaScript error: resource://gre/modules/FileUtils.jsm, line 63: NS_ERROR_FAILURE: Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsIProperties.get]
So, apparently my headless Firefox does not want to run, when PHP is invoked through the webserver (in which case, PHP reports that it uses the apache2handler SAPI).
Would anyone know why this happens - and how can I get the script to execute properly when called from a webserver, just as when it runs under PHP CLI mode?
EDIT 2: Can now reconstruct this error via CLI mode too, and can confirm it is due to the user; so without any JS script provided in the $command, I get this:
$ sudo -H -u root php mytest.php
...
Usage: casperjs [options] script.[js|coffee] [script argument [script argument ...]]
casperjs [options] test [test path [test path ...]]
casperjs [options] selftest
...
$ sudo -H -u www-data php mytest.php
JavaScript error: resource://gre/modules/FileUtils.jsm, line 63: NS_ERROR_FAILURE: Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsIProperties.get]
Gecko error: it seems /usr/bin/firefox46 is not compatible with SlimerJS.
See Gecko version compatibility. If version is correct, launch slimerjs
with --debug=true to see Firefox error message
Well, this was a nasty problem. I ended up doing an strace, and comparing the logs, for the root user and the www-data user when running a full slimerjs (the full command line can be found by adding echoes to /path/to/slimerjs-0.10.1-pre/slimerjs):
sudo -H -u www-data strace \
/usr/bin/firefox46 -app /path/to/slimerjs-0.10.1-pre/application.ini \
--profile /path/to/firefox-46.0.1/profile-46 -no-remote --debug=true /home/USERNAME/.nvm/versions/node/v4.0.0/lib/node_modules/casperjs/bin/bootstrap.js --casper-path=/home/USERNAME/.nvm/versions/node/v4.0.0/lib/node_modules/casperjs \
--cli 2>&1 \
| tee /tmp/strace.log
sudo -H -u root strace \
/usr/bin/firefox46 -app /path/to/slimerjs-0.10.1-pre/application.ini \
--profile /path/to/firefox-46.0.1/profile-46 -no-remote --debug=true /home/USERNAME/.nvm/versions/node/v4.0.0/lib/node_modules/casperjs/bin/bootstrap.js --casper-path=/home/USERNAME/.nvm/versions/node/v4.0.0/lib/node_modules/casperjs \
--cli 2>&1 \
| tee /tmp/straceR.log
If these logs are now compared in say meld, then the eventually start diverging at a point like this:
mkdir("/root/.innophi", 0700) = 0
mkdir("/root/.innophi/slimerjs", 0700) = 0
... [vs.] ...
mkdir("/var/www/.innophi", 0700) = -1 EACCES (Permission denied)
access("/var/www/.innophi", F_OK) = -1 ENOENT (No such file or directory)
So, casperJS basically tries to create a directory in the home directory of the user; the problem is , www-data's $HOME is /var/www, where it seemingly has no write access!
So, the easiest thing for me was to "hack" the $HOME environment variable in the mytest.php script, and set it to /tmp, where www-data definitely has write permissions:
...
putenv("SLIMERJSLAUNCHER=/usr/bin/firefox46");
putenv("HOME=/tmp");
...
... and whaddayaknow, finally the script works under the www-data user from CLI too:
$ sudo -H -u www-data php test_commands.php
...
Options:
--verbose Prints log messages to the console
--log-level Sets logging level
--help Prints this help
...
Btw, this .innophi directory seems to also be mentioned in https://docs.slimerjs.org/current/configuration.html#profiles ,
I'm trying to have my web app create thumbnails for uploaded PDFs with the following command:
exec( "/usr/local/bin/convert '/path/to/file.pdf'[0] -background white -alpha remove -thumbnail 600x '/path/to/file.pdf.png'", $output, $return );
When I run this command from the command line it works, both when I run it as root and when I run it as _www (the user of the web server) using:
sudo -u _www /usr/local/bin/convert '/path/to/file.pdf'[0] -background white -alpha remove -thumbnail 600x '/path/to/file.pdf.png'
But when the exec command runs, the thumbnail is not created. The $output array is empty, and the $return value is 1 (general error).
Furthermore, when I generate thumbnails for other kinds of files, I have no problems at all. For example for GIFs I use:
exec( "/usr/local/bin/convert '/path/to/file.gif'[0] -thumbnail 600x '/path/to/file.gif'", $output, $return );
I have no problems with JPGs, PNGs or BMPs either. This leads me to think that the problem may be related to GhostScript, as only PDFs require GhostScript to generate thumbnails. As a last comment, the thumbnail generation fails both in my localhost and in my server.
I'm out of ideas, anyone has one? Thanks!
In the end, I had two different problems, one in my localhost, another in my server.
In my localhost, GhostScript was not in the PATH of the exec environment. To solve this, I added the following line just before the command:
putenv( 'PATH=' . getenv( 'PATH' ) . ':' . dirname( '/usr/local/bin/gs' ) );
This fixed the problem in my localhost. But when I pushed the new code to the server, it still didn't work. So I checked the PATH in my server and GhostScript was already in there. I then figured out that my server was using an old version of GhostScript, with no "alpha" support. So I simplified the command to:
exec( "/usr/local/bin/convert '/path/to/file.pdf'[0] -thumbnail 600x '/path/to/file.pdf.png'", $output, $return );
And now both my localhost and server work, yay!
I'm in trouble and that much confused about a php shell_exec command.
When the command is execute by PHP I have no error but the execution fails. If I use exactly the same command from a terminal it works.
Here's the command :
/usr/bin/wkhtmltopdf --lowquality --dpi 300 --encoding utf-8 "/tmp/knplabs_snappyxa9otq.html" "/tmp/knplabs_snappyv3pD7h.pdf"
When I lauch this from a terminal :
$ /usr/bin/wkhtmltopdf --lowquality --dpi 300 --encoding utf-8 "/tmp/knplabs_snappyWG9XTd.html" "/tmp/knplabs_snappyv3pD7h.pdf"
Loading page (1/2)
Printing pages (2/2)
Done
But from my php script :
// Construct the previous command
$command = $this->buildCommand($url, $path);
../..
shell_exec($command);
../..
$content = file_get_contents($path);
../..
I've test the output of shell_exec, it's empty.
The log :
Warning: file_get_contents(/tmp/knplabs_snappyv3pD7h.pdf): failed to open stream: No such file or directory in /*****/lib/snappy/SnappyMedia.class.php on line 64
No permission pb in the /tmp directory :
$ ls -la /tmp
total 448
drwxrwxrwt 16 root root 4096 mars 12 21:51 .
../..
I've tried avec the PHP exec() function to get error informations, I just get an "1" error code in return_var and nothing in output.
For information this issue appear on my test server, my desktop computer but not on my notebook. All the 3 are with sames PHP, Apache, Mysql versions.
I don't understand anything ...
Thanks for any help, I'm loosing my mind.
David.
I've found the solution here : Executing wkhtmltopdf from PHP fails
Thanks to Krzychu.
First to get information from the shell_exec command add " 2>&1" at the end of the command. In that way you will get information in return of the command :
$no_output = shell_exec($command);
echo $no_output; // nothing
$output = shell_exec($command . ' 2>&1');
echo $output; // in my case : "cannot connect to X server"
The solution :
Not use the wkhtmltopdf ubuntu package (0.9.9-4)
Use the official package from the Wkhtmltopdf download page
So no need to install xvfb ! (I've seen this advice many times)
Looks like a user's permissions issue.
When you run the command from the terminal, it is the user account, currently used, which does have the right permissions, to run a command in /usr/bin, and execute the specific file.
When you run it from the php script, it is the http server account on your system, which needs the permission to execute the file in /usr/bin. Usually this is the apache user.
How you should setup permissions depends on your system. Just remember that what is allowed for apache, is allowed for anyone accessing your http server.
I have had this problem for ages and adding . ' 2>&1' after the $command has somehow solved the problem.
this:
$output = shell_exec($command . ' 2>&1');
instead of:
$output = shell_exec($command);
No idea why but it works and I'm grateful.
Is it a shared hosting? It seems like shell_exec is a restricted function. Try running error_reporting(E_ALL); ini_set('display_errors', 1); before calling shell_exec.
I stumbled upon the same Problem, in my case an absolut Path in the exec Command like /var/www did not work, I had to use relative Paths from the point where I executed the php File.
I also wanted to notice, that it did not work using shell_exec, however it worked using normal exec command, not sure wheres the difference here.