通过 docker-compose 运行时,Flask CLI 抛出“OSError: \[Errno 8\] Exec format error”

新手上路,请多包涵

我正在运行带有 Custom Script 的 Flask 应用程序。或尝试,无论如何。

我在 Windows 10 上,应用程序应该使用以下命令在 linux Docker 容器中运行:

 docker-compose up api

Docker-compose 是 version 1.23.2 。在 dockerfile 中, api 服务通过以下命令运行:

 command: python manage.py run --host "0.0.0.0" --with-threads

当它尝试启动时,我看到异常

OSError: [Errno 8] Exec format error: '/api/manage.py'

我最初认为这将是可怕的 Windows 行结尾,再次为我而来,但在我所有的源文件上运行 dos2unix 并没有解决问题。

我怎样才能避免这个错误?


管理.py

     import click
    from flask.cli import FlaskGroup

    from my_app_api import create_app

    def create_my_app(info):
        return create_app()

    @click.group(cls=FlaskGroup, create_app=create_my_app)
    def cli():
        pass

    if __name__ == "__main__":
        cli()

完整追溯

api_1          | Traceback (most recent call last):
api_1          |   File "manage.py", line 22, in <module>
api_1          |     cli()
api_1          |   File "/usr/local/lib/python3.6/site-packages/click/core.py", line 764, in __call__
api_1          |     return self.main(*args, **kwargs)
api_1          |   File "/usr/local/lib/python3.6/site-packages/flask/cli.py", line 380, in main
api_1          |     return AppGroup.main(self, *args, **kwargs)
api_1          |   File "/usr/local/lib/python3.6/site-packages/click/core.py", line 717, in main
api_1          |     rv = self.invoke(ctx)
api_1          |   File "/usr/local/lib/python3.6/site-packages/click/core.py", line 1137, in invoke
api_1          |     return _process_result(sub_ctx.command.invoke(sub_ctx))
api_1          |   File "/usr/local/lib/python3.6/site-packages/click/core.py", line 956, in invoke
api_1          |     return ctx.invoke(self.callback, **ctx.params)
api_1          |   File "/usr/local/lib/python3.6/site-packages/click/core.py", line 555, in invoke
api_1          |     return callback(*args, **kwargs)
api_1          |   File "/usr/local/lib/python3.6/site-packages/click/decorators.py", line 64, in new_func
api_1          |     return ctx.invoke(f, obj, *args, **kwargs)
api_1          |   File "/usr/local/lib/python3.6/site-packages/click/core.py", line 555, in invoke
api_1          |     return callback(*args, **kwargs)
api_1          |   File "/usr/local/lib/python3.6/site-packages/flask/cli.py", line 438, in run_command
api_1          |     use_debugger=debugger, threaded=with_threads)
api_1          |   File "/usr/local/lib/python3.6/site-packages/werkzeug/serving.py", line 988, in run_simple
api_1          |     run_with_reloader(inner, extra_files, reloader_interval, reloader_type)
api_1          |   File "/usr/local/lib/python3.6/site-packages/werkzeug/_reloader.py", line 332, in run_with_reloader
api_1          |     sys.exit(reloader.restart_with_reloader())
api_1          |   File "/usr/local/lib/python3.6/site-packages/werkzeug/_reloader.py", line 176, in restart_with_reloader
api_1          |     exit_code = subprocess.call(args, env=new_environ, close_fds=False)
api_1          |   File "/usr/local/lib/python3.6/subprocess.py", line 287, in call
api_1          |     with Popen(*popenargs, **kwargs) as p:
api_1          |   File "/usr/local/lib/python3.6/subprocess.py", line 729, in __init__
api_1          |     restore_signals, start_new_session)
api_1          |   File "/usr/local/lib/python3.6/subprocess.py", line 1364, in _execute_child
api_1          |     raise child_exception_type(errno_num, err_msg, err_filename)
api_1          | OSError: [Errno 8] Exec format error: '/api/manage.py'

原文由 tessafyi 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 748
2 个回答

看起来你的 api/manage.py 没有 shebang ( [Wikipedia]: Shebang (Unix) ),所以默认的(当前的)命令处理器(一个 shell - 通常是 bash )正在尝试运行它,这(很明显)失败。

要更正此问题,请添加一个 shebang (在文件的开头,确保您的编辑器添加了 Nix 样式的行结尾( \n0x0ALF )):

  • 默认 Python 安装:
   #!/usr/bin/env python

  • 变体(明确指定 Python 3 ):

     #!/usr/bin/env python3
    
    
    
  • 自定义 Python 安装:

   #!/full/path/to/your/custom/python/executable

请注意,您还需要文件的执行权限 (--- chmod +x api/manage.py )。

例子:

>  [cfati@cfati-5510-0:/cygdrive/e/Work/Dev/StackOverflow/q055271912]> ~/sopr.sh
> ### Set shorter prompt to better fit when pasted in StackOverflow (or other) pages ###
>
> [064bit prompt]> ls
> code00.py  code01.py
> [064bit prompt]>
> [064bit prompt]> cat code00.py
> print("This is:", __file__)
>
> [064bit prompt]> python3 -c "import os, subprocess;subprocess.Popen(os.path.join(os.getcwd(), \"code00.py\")).communicate()"
> Traceback (most recent call last):
>   File "<string>", line 1, in <module>
>   File "/usr/lib/python3.6/subprocess.py", line 709, in __init__
>     restore_signals, start_new_session)
>   File "/usr/lib/python3.6/subprocess.py", line 1344, in _execute_child
>     raise child_exception_type(errno_num, err_msg, err_filename)
> OSError: [Errno 8] Exec format error: '/cygdrive/e/Work/Dev/StackOverflow/q055271912/code00.py'
> [064bit prompt]>
> [064bit prompt]> cat code01.py
> #!/usr/bin/env python3
>
> print("This is:", __file__)
>
> [064bit prompt]> python3 -c "import os, subprocess;subprocess.Popen(os.path.join(os.getcwd(), \"code01.py\")).communicate()"
> This is: /cygdrive/e/Work/Dev/StackOverflow/q055271912/code01.py
>
> ```

另一种方法是运行解释器后跟文件名,但我不知道如何从 _Flask_ 执行此操作——实际上这需要修补 _Werkzeug_ ( __reloader.py_ : __get_args_for_reloading_ ),但这只是一个蹩脚的解决方法 ( _gainarie_ ) \- 见下文。

* * *

### 更新 _\#0_

查看@AxelGrytt 的回答,发现这是一个已知问题: [\[GitHub\]: pallets/werkzeug - 0.15.0 causes OSError: \[Errno 8\] Exec format error: in Docker for Windows](https://github.com/pallets/werkzeug/issues/1482) (hmm, submitted in the same day as this问题(发布后 2 天):))。

所以,我上面所说的是正确的,但值得一提的是还有另一种修复方法:删除文件的 _执行_ 权限:

chmod -x api/manage.py “`

根据 Werkzeug 作者的说法,从现在开始, 这是期望的行为(也适用于 v 0.15.2 ):

  • 设置 exec 权限的文件,还 应该 有一个 shebang
  • 没有 shebang 的文件不 应该 设置 exec 权限

原文由 CristiFati 发布,翻译遵循 CC BY-SA 4.0 许可协议

这是 Werkzeug 0.15 中的新行为。降级到 Werkzeug 0.14.1 可能会起作用,但不再支持 0.14,因此您最好按照其他答案中的描述更正文件中的问题。

原文由 Axel Grytt 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题