6

próbuję uruchomić to narzędzie w obrębie funkcji lambda: https://github.com/nicolas-f/7DTD-leafletnie można uruchomić z poziomu Pythona binarny AWS lambda funkcji

Narzędzie zależy na poduszki, która zależy od bibliotek obrazowania niedostępnych w pojemniku lambda AWS. Aby spróbować obejść ten problem, uruchomiłem program piorący, aby utworzyć plik binarny, który mam nadzieję wykonać. Ten plik ma nazwę map_reader i znajduje się na najwyższym poziomie pakietu zamków lambda.

Poniżej znajduje się kod używam, aby spróbować uruchomić narzędzie:

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) 

I tu jest błąd, który pojawia się na drugim subprocess.Popen rozmowy:

<subprocess.Popen object at 0x7f08fa100d10> 
[Errno 13] Permission denied: OSError 

Jak mogę uruchomić to poprawnie?

+0

Domyślam się, że środowisko, w którym pracujesz, działa nie zezwala na ustawianie plików lokalnych jako wykonywalnych. "Odmowa uprawnień" może oznaczać dokładnie to, co mówi. – Blckknght

Odpowiedz

3

Być może wprowadzono Cię w błąd w rzeczywistości.

Nie sądzę, że pierwszy Popen działał pomyślnie. Myślę, że po prostu wyrzucił wiadomość ze standardowym błędem, a ty jej nie widzisz. To chyba powiedzieć, że

chmod: map_reader: No such file or directory 

Proponuję można spróbować jednego z tych 2:

  1. Rozpakuj map_reader z pakietu w/tmp. Następnie odwołaj się do niego za pomocą /tmp/map_reader.
  2. Zrób to zalecane przez Tim Wagner, szef AWS Lambda, który powiedział, co następuje w artykule Running Arbitrary Executables in AWS Lambda:

tym własnych plików wykonywalnych jest łatwe; po prostu zapakuj je w pliku ZIP, który przesyłasz, a następnie odsyłaj do nich (w tym względną ścieżkę do utworzonego pliku ZIP), gdy będziesz je wywoływał z Node.js lub z innych procesów, które wcześniej uruchomiłeś. Upewnić się, że dołączyć następujące na początku kodu funkcyjnego:

process.env[‘PATH’] = process.env[‘PATH’] + ‘:’ + process.env[‘LAMBDA_TASK_ROOT’] 

Powyższy kod jest dla Węzła JS ale dla Pythona, to jak następnym

import os os.environ['PATH']

Że powinien zadziałać komenda command = './map_reader <arguments>.

Jeśli nadal nie działają, można także rozważyć uruchomienie chmod 755 map_readerprzed tworząc pakiet i przesłać go (jak sugeruje in this other question).

+0

Oznaczenie jako poprawne, chociaż nie było dla mnie pełnym rozwiązaniem. Napiszę inną odpowiedź z innym problemem. Najważniejszą rzeczą było przeniesienie pliku binarnego do/tmp, aby móc na nim działać. – stevepkr84

+0

Zapomniałem wspomnieć o upewnieniu się, że skompilowałeś dla Amazon Linux. Zakładałem, że to załatwiłeś. Cieszę się, że to wymyśliłeś. –

+0

czy dodanie LAMBDA_TASK_ROOT do twojej ścieżki nie zadziałało? –

2

Tutaj były dwa problemy. Po pierwsze, zgodnie z odpowiedzią Jeshana, musiałem przenieść plik binarny do/tmp, zanim będę mógł poprawnie uzyskać do niego dostęp.

Innym problemem było to, że uruchomiłem program do usuwania paczek ubuntu, tworząc pojedynczy plik. Zobaczyłem gdzieś indziej komentarze na temat pewności kompilacji w tej samej architekturze co kontener lambda. Dlatego uruchomiłem program do usuwania puntów na ec2 w oparciu o AMI Amazon Linux. Dane wyjściowe to wiele plików .os, które po przeniesieniu do tmp działały zgodnie z oczekiwaniami.

1
copyfile('/var/task/yourbinary', '/tmp/yourbinary') 
os.chmod('/tmp/yourbinary', 0555) 

Przeniesienie pliku na /tmp i uczynienie go wykonywalnym pracował dla mnie

3

Wiem, że jestem trochę za późno na to, ale jeśli chcesz bardziej ogólny sposób to zrobić (na przykład, jeśli masz wiele plików binarnych i nie może ich wszystkich) używać, to w jaki sposób to zrobić, warunkiem umieścić wszystkie swoje pliki binarne w folderze bin obok pliku py, a wszystkie biblioteki w folderze 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)