Node.js v20.11.1
PHP 7.4.33
chrome/linux-124.0.6367.91
Edit/TLDR: After more research, when I run via the command line, chrome is putting files in my home directory under .config/google-chrome-for-testing/ . I guess Chrome must be trying to find that dir when run by Apache. Looking into it now.
I have files index.js and puppeteerrc.cjs in the same directory. I am trying to make a PDF of a page at a given URL. puppeteerrc.cjs specifies the cache directory. The contents of both files are below.
This command works if I run it from within that directory
node index.js 'https://www.stackoverflow.com' output.pdf
However, in PHP, this does not:
$cmd = "cd '/path/to/script' && node 'index.js' 'https://www.stackoverflow.com' /path/to/output.pdf 2>&1";
exec($cmd, $out, $error_code);
I'm not sure what's different between the command line and Apache. I ran chrome_crashpad_handler --help
, but I'm not sure what to do with that information.
When I set the executablePath config in index.js I get the same result, it runs from cmd line, not from Apache:
const browser = await puppeteer.launch({
executablePath:'/opt/npm/.cache/puppeteer/chrome/linux-124.0.6367.91/chrome-linux64/chrome'
});
I've also tried all of the following configs and it outputs the same error:
args: ['--no-sandbox', "--disabled-setupid-sandbox"],
ignoreDefaultArgs: ['--disable-extensions'] ,
userDataDir: "/path/to/a/dir",
headless:true
Note that previously, when it couldn't find the chrome executable, I got a different error, now that I am past that error, it still doesn't work. So I know it can find the executable now. Also, I ran is_executable() on the chrome file and PHP running under Apache returns true.
I did notice that there is a ".config/google-chrome-for-testing/Crash Reports" directory in my home directory. Now I'm guessing that maybe it's looking for one of those directories when apache is running it.
Output when node command run from PHP
opt/npm/lib/node_modules/puppeteer/node_modules/@puppeteer/browsers/lib/cjs/launch.js:310
reject(new Error([
^
Error: Failed to launch the browser process!
chrome_crashpad_handler: --database is required
Try 'chrome_crashpad_handler --help' for more information.
TROUBLESHOOTING: https://pptr.dev/troubleshooting
at Interface.onClose (/opt/npm/lib/node_modules/puppeteer/node_modules/@puppeteer/browsers/lib/cjs/launch.js:310:24)
at Interface.emit (node:events:530:35)
at Interface.close (node:internal/readline/interface:527:10)
at Socket.onend (node:internal/readline/interface:253:10)
at Socket.emit (node:events:530:35)
at endReadableNT (node:internal/streams/readable:1696:12)
at process.processTicksAndRejections (node:internal/process/task_queues:82:21)
Node.js v20.11.1
index.js
/**
* Create a PDF file from a URL. First command line
* argument (besidedes JS file) is URL, second one
* is output file.
* Usage: node index.js <URL> <OUTPUT_FILE_NAME>
*/
const node_path = "/opt/npm/lib/node_modules";
module.paths.unshift(node_path);
const puppeteer = require('puppeteer');
(async () => {
// Create a browser instance
const browser = await puppeteer.launch();
// Create a new page
const page = await browser.newPage();
// Website URL to export as pdf
const website_url = process.argv[2];
// output path
const output_path = process.argv[3];
// Open URL in current page
await page.goto(website_url, { waitUntil: 'networkidle0' });
//use the print CSS
await page.emulateMediaType('print');
// Downlaod the PDF
const pdf = await page.pdf({
path: output_path,
margin: { top: '.39in', right: '.39in', bottom: '.39in', left: '.39in' },
printBackground: true,
format: 'Letter',
});
// Close the browser instance
await browser.close();
})();
.puppeteerrc.cjs
/**
* @type {import("puppeteer").Configuration}
*/
module.exports = {
// Changes the cache location for Puppeteer.
cacheDirectory: '/opt/npm/.cache/puppeteer'
};
Chrome needs a .config directory to write to, which it expects in the user's home directory. In the .config dir, it will put a google-chrome-for-testing/ directory.
So, I created a config directory, for example '/my/web/app/dir/.config
' Chmoded it to 775, Changed the directory group to a group that Apache can write.
Then, I changed the HOME environment variable before I run the node command.
$cmd = "HOME='/my/web/app/dir/' && export HOME && cd '/path/to/script' && node 'index.js' 'https://www.stackoverflow.com' /path/to/output.pdf 2>&1";
exec($cmd, $out, $error_code);