1
0

More than 1 year has passed since last update.

AWS Lambda の実行環境でデフォルトでは用意されていないコマンドを呼ぶ

Last updated at Posted at 2020-03-04

やったこと

AWS LambdaでPythonからgsコマンドを呼んでPDFを結合しました。

経緯

PythonのPyPDF2を使って結合しようとしましたが
PyPDF2はPDFのファイル構造がPDFのbasicなファイル構造(つまりheaderがあって、bodyがあって、Cross-reference Tableがあって、Trailerがあるみたいなもの)を前提としていて、Cross-reference TableがないとかTrailerがないPDFファイルを結合しようとするとエラーになってしまっていました。
gsコマンドならいけたので、LambdaでPythonからgsコマンドを呼ぶことにしました。

環境

AWS Lambda Python3.7

解決

Pythonからlsコマンドとかを叩くのはsubprocessモジュールを使ってできるので、lambdaの実行環境のデフォルトから実行できるコマンドなら以下のような感じで十分

out = subprocess.run(['ls'], stdout=subprocess.PIPE)
print(out.stdout.decode())

これで済めば話は簡単なのですが、ghostscriptはlambda実行環境では用意されてない(昔はあったみたいだけど今はなくなってるっぽいhttps://aws.amazon.com/jp/amazon-linux-ami/2018-03-packages/ )のでバイナリを持ってきてパスを通す必要がある。

$ curl -L -# https://github.com/ArtifexSoftware/ghostpdldownloads/releases/download/gs950/ghostscript-9.50-linux-x86_64.tgz -O

でバイナリファイルを入手する

$ tar zxvf ghostscript-9.50-linux-x86_64.tgz

で解凍したghostscript-9.50-linux-x86_64の中にgs-950-linux-x86_64ってのがあるのでこれをgsに名前を変えてlambda関数と同レイヤーにbinディレクトリでも作ってその中に入れる。
そしてzipで圧縮して、lambdaへ反映させる。
lambda関数のgsを呼ぶ部分は以下のような感じ

os.environ['PATH'] = os.environ['PATH'] + ':/var/task/binary'
cmd = [
    "gs",
    "-dBATCH",
    "-dNOPAUSE",
    "-q",
    "-sDEVICE=pdfwrite",
    "-sOutputFile=out.pdf",
    "a.pdf",
    "b.pdf"
]
out = subprocess.run(cmd, stdout=subprocess.PIPE)
print(out.stdout.decode())

雑談

https://www.slideshare.net/field-works/pdf-29001511
古いけどこのスライドが言うにはAdobe Readerは間違ったPDFに寛容らしく、間違ったPDFを生成するツールが世の中に氾濫しているってさ
やめてほしい

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0