我正在尝试在lambda函数中运行此工具:https://github.com/nicolas-f/7DTD-leaflet
该工具依赖于Pillow,它依赖于AWS lambda容器中不可用的映像库。为了试图绕过这个我运行pyinstaller来创建一个我希望可以执行的二进制文件。此文件名为map_reader
,位于lambda 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)
这是错误,发生在第二次subprocess.Popen
电话:
<subprocess.Popen object at 0x7f08fa100d10>
[Errno 13] Permission denied: OSError
如何正确运行?
答案 0 :(得分:5)
你可能被误导了问题实际上是什么。
我不认为第一个Popen成功跑了。我认为它只是在标准错误中抛出了一条消息,而你却没有看到它。它可能会说那个
<form action="" method="get">
{{ filter.form.as_p }}
<input type="submit" />
</form>
我建议您可以尝试以下两种方法之一:
chmod: map_reader: No such file or directory
。包含您自己的可执行文件很容易;只需将它们打包到您上传的ZIP文件中,然后在从Node.js或之前启动的其他进程中调用它们时引用它们(包括您创建的ZIP文件中的相对路径)。确保在功能代码的开头包含以下内容:
/tmp/map_reader
以上代码适用于Node JS,但对于Python,它类似于以下
process.env[‘PATH’] = process.env[‘PATH’] + ‘:’ + process.env[‘LAMBDA_TASK_ROOT’]
这应该使命令import os
os.environ['PATH']
起作用。
如果他们仍然无法工作,您也可以考虑在创建包并上传之前运行command = './map_reader <arguments>
(按照建议in this other question)。
答案 1 :(得分:4)
我知道我有点迟到但是如果你想要一个更通用的方法(例如,如果你有很多二进制文件并且可能不会全部使用它们),我就这样做,<如果您将所有二进制文件放在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 :(得分:2)
这里有两个问题。首先,根据Jeshan的回答,我必须先将二进制文件移动到/ tmp才能正确访问它。
另一个问题是我在ubuntu上运行了pyinstaller,创建了一个文件。我在其他地方看到了一些关于确保在与lambda容器运行相同的架构上进行编译的注释。因此,我基于Amazon Linux AMI在ec2上运行了pyinstaller。输出是多个.os文件,当移动到tmp时,按预期工作。
答案 3 :(得分:1)
copyfile('/var/task/yourbinary', '/tmp/yourbinary')
os.chmod('/tmp/yourbinary', 0555)
将二进制文件移动到/tmp
并使其可执行为我工作
答案 4 :(得分:0)
无需复制文件/tmp
。您可以只使用ld-linux执行任何文件,包括那些未标记为可执行文件的文件。
因此,要在AWS Lambda上运行不可执行程序,请使用以下命令:
/lib64/ld-linux-x86-64.so.2 /opt/map_reader
P.S。在Lambda层中添加map_reader
二进制文件或任何其他静态文件,从而在/opt
文件夹中,将更有意义。
答案 5 :(得分:0)
Like the docs mention for Node.js,您需要更新SELECT customerID, SUM(sales_volume), SUM(returned_volume),
(SUM(returned_volume) / SUM(sales_volume)) AS return_rate
FROM (SELECT s.*,
ROW_NUMBER() OVER (PARTITION BY customerID ORDER BY order_date DESC) as seqnum
FROM sales s
) s
WHERE seqnum <= 3
GROUP BY 1;
,否则在尝试运行在Lambda软件包根目录中添加的可执行文件时会得到$PATH
。在Node.js中,就是:
command not found
现在,在Python中是同一件事:
process.env['PATH'] = process.env['PATH'] + ':' + process.env['LAMBDA_TASK_ROOT']
在Python 3.8上测试正常。
(作为奖励,这里还有更多env variables used by Lambda。)