このツールをラムダ関数内で実行しようとしています: https://github.com/nicolas-f/7DTD-leaflet
このツールは、AWSラムダコンテナで利用できないイメージングライブラリに依存するPillowに依存しています。これを回避するために、pyinstallerを実行して、うまくいけば実行できるバイナリを作成しました。このファイルの名前はmap_reader
で、ラムダZipパッケージのトップレベルにあります。
以下は、ツールを試して実行するために使用しているコードです。
command = 'chmod 755 map_reader'
args = shlex.split(command)
print subprocess.Popen(args)
command = './map_reader -g "{}" -t "{}"'.format('/tmp/mapFiles', '/tmp/tiles')
args = shlex.split(command)
print subprocess.Popen(args)
そして、2番目のsubprocess.Popen
呼び出しで発生するエラーは次のとおりです。
<subprocess.Popen object at 0x7f08fa100d10>
[Errno 13] Permission denied: OSError
どうすればこれを正しく実行できますか?
あなたは問題が実際に何であるかについて誤解されているかもしれません。
最初のポペンがうまく走ったとは思いません。標準エラーでメッセージをダンプしただけで、表示されていないと思います。それはおそらくそれを言っている
chmod: map_reader: No such file or directory
これらの2のいずれかを試すことができることをお勧めします:
/tmp/map_reader
で参照します。独自の実行可能ファイルを含めるのは簡単です。アップロードするZipファイルにパッケージ化し、Node.jsまたは以前に開始した他のプロセスから呼び出すときに参照します(作成したZipファイル内の相対パスを含む)。必ず関数コードの先頭に以下を含めてください:
process.env[‘PATH’] = process.env[‘PATH’] + ‘:’ + process.env[‘LAMBDA_TASK_ROOT’]
上記のコードはNode JS用ですが、Pythonの場合は次のようになります
import os os.environ['PATH']
これにより、コマンドcommand = './map_reader <arguments>
が機能するはずです。
それでも機能しない場合は、chmod 755 map_reader
beforeパッケージを作成してアップロードすることも検討してください(提案されているように この他の質問で )。
私はこれに少し遅れていることを知っていますが、これを行うためのより一般的な方法が必要な場合(たとえば、バイナリがたくさんあり、すべてを使用しない可能性がある場合)、これは私がそれを行う方法です提供すべてのバイナリをpyファイルの隣のbinフォルダーに配置し、すべてのライブラリをlibフォルダーに配置します:
import shutil
import time
import os
import subprocess
LAMBDA_TASK_ROOT = os.environ.get('LAMBDA_TASK_ROOT', os.path.dirname(os.path.abspath(__file__)))
CURR_BIN_DIR = os.path.join(LAMBDA_TASK_ROOT, 'bin')
LIB_DIR = os.path.join(LAMBDA_TASK_ROOT, 'lib')
### In order to get permissions right, we have to copy them to /tmp
BIN_DIR = '/tmp/bin'
# This is necessary as we don't have permissions in /var/tasks/bin where the lambda function is running
def _init_bin(executable_name):
start = time.clock()
if not os.path.exists(BIN_DIR):
print("Creating bin folder")
os.makedirs(BIN_DIR)
print("Copying binaries for "+executable_name+" in /tmp/bin")
currfile = os.path.join(CURR_BIN_DIR, executable_name)
newfile = os.path.join(BIN_DIR, executable_name)
shutil.copy2(currfile, newfile)
print("Giving new binaries permissions for lambda")
os.chmod(newfile, 0775)
elapsed = (time.clock() - start)
print(executable_name+" ready in "+str(elapsed)+'s.')
# then if you're going to call a binary in a cmd, for instance pdftotext :
_init_bin('pdftotext')
cmdline = [os.path.join(BIN_DIR, 'pdftotext'), '-nopgbrk', '/tmp/test.pdf']
subprocess.check_call(cmdline, Shell=False, stderr=subprocess.STDOUT)
ここには2つの問題がありました。まず、Jeshanの回答によると、適切にアクセスする前に、バイナリを/ tmpに移動する必要がありました。
もう1つの問題は、ubuntuでpyinstallerを実行して、単一のファイルを作成することでした。ラムダコンテナが実行されるのと同じアーキテクチャでコンパイルすることを確認することについて、他の場所でいくつかのコメントを見ました。そのため、Amazon LinuxAMIに基づいてec2でpyinstallerを実行しました。出力は複数の.osファイルであり、tmpに移動すると、期待どおりに機能しました。
copyfile('/var/task/yourbinary', '/tmp/yourbinary')
os.chmod('/tmp/yourbinary', 0555)
バイナリを/tmp
に移動し、実行可能にすることでうまくいきました
/tmp
ファイルをコピーする必要はありません。 ld-linux を使用して、実行可能とマークされていないファイルを含む任意のファイルを実行できます。
したがって、AWS Lambdaで実行不可能ファイルを実行するには、次のコマンドを使用します。
/lib64/ld-linux-x86-64.so.2 /opt/map_reader
P.S. map_reader
バイナリまたはその他の静的ファイルをLambdaレイヤー、つまり/opt
フォルダーに追加する方が理にかなっています。