user994165
user994165

Reputation: 9502

Running GraphicsMagick in AWS Lambda Node app produces no output

I have GraphicsMagick compiled in my Node app's bin directory. When I spawn a child process to run gm directly, I'm able to get the standard output and not see any errors.

Then I tied in the gm module. My app finds gm because if I change the path to gm, I get an error stating that it can't find gm. However, when I run code as pasted below, there's no resizing done and no error message logged. If I change the image path to something that doesn't exist, I still get no errors.

const BIN_PATH = `${process.env.LAMBDA_TASK_ROOT}/graphicsmagick/bin/`;
const gm = require('gm');
...

const file = './spec/large.png';
gm(file)
  .resize(240, 240)
  // .autoOrient()
  // .noProfile()
  .write('./resize.png', (err) => {
    if (err) {
      logger.error(err);
      const err2 = createError(err, event, `Failed to resize image ${file}`);
      throw err2;
    }
    logger.info(`done resizing ${file}`);
  });

Upvotes: 1

Views: 410

Answers (1)

user994165
user994165

Reputation: 9502

I added the ./graphicsmagick/bin directory containing gm to the PATH variable and also set the LD_LIBRARY_PATH environment variable. I compiled GraphicsMagick in an Amazon AMI EC2, and added it to my repo in the ./graphicsmagick directory.

There were also several shared libraries that were installed in the EC2 which I had to copy over as well to the ./graphicsmagick/lib directory (lib already had some files but not all of the libraries required). I don't remember which directory contained the shared libraries but it was probably /usr/lib or /usr/local/lib. If you run the Lambda on AWS or locally using the SAM tool, it would tell you which file is missing and simply executing `find / -name filename.so' on the EC2 results in the directory where the file is located. There were 42 files I had to copy over to lib.

I should also note that I later added a check to make sure the exit status is 0. I believe this is what was missing to be able to know that an error occurred.

// Globally outside of the handler

const BIN_PATH = `${process.env.LAMBDA_TASK_ROOT}/graphicsmagick/bin/`;
process.env.PATH = `${process.env.PATH}:${BIN_PATH}`;

...

//In the handler
      const cmd = 'gm';
      const params = ['convert', sourceFile, '-resize', size, outputFilePath];
      logger.debug({ command: { cmd, params } });
      const childProcess = spawn(cmd, params, {
        env: {
          ...process.env,
          PATH: `./graphicsmagick/bin/:${process.env.PATH}`,
          LD_LIBRARY_PATH: './graphicsmagick/lib',
        },
      });

      childProcess.stdout.on('data', (chunk) => {
        stdOut = `${stdOut}${chunk}`;
      });
      childProcess.stderr.on('data', (chunk) => {
        errorOut = `${errorOut}${chunk}`;
      });
      exitCode = await childProcessPromise({ logger }, event, childProcess);
    } else {
      await copyFile(sourceFile, outputFilePath);
    }

Upvotes: 1

Related Questions