首页 > 解决方案 > 管道:运行 make 命令时文件描述符错误

问题描述

任何人都可以帮助我解决这个问题吗?我正在尝试运行一个应用程序,每当我在终端中运行make时都会出现该错误

process_begin: CreateProcess(NULL, python3.8 -c "import sys; print(sys.version_info[:2] >= (3, 8))", ...) failed.enter code here
Makefile:24: pipe: Bad file descriptor

SETUP  Creating virtualenv

FATAL  Python not found (python3.8)

make: *** [Makefile:21: .venv] Error 1

我在运行和安装 python8.3 之前创建了一个 venv,pip 也是如此。

生成文件

PYTHON ?= python3.8
FLASK_HOST ?= 127.0.0.1
FLASK_PORT ?= 5000
VENV ?= .venv

SHELL := /bin/bash
PIP := ${VENV}/Scripts/pip
FLASK := ${VENV}/Scripts/flask
CONFIG := licmon/licmon.cfg
SERVERS := licmon/servers.cfg

.PHONY: all
all: ${VENV} config
    @printf "\033[38;5;154mSETUP\033[0m  \033[38;5;105mInstalling licmon python package\033[0m\n"
    @${PIP} install -q -e '.[dev]'

 
${VENV}:
    @printf "\033[38;5;154mSETUP\033[0m  \033[38;5;105mCreating virtualenv\033[0m\n"
ifeq (, $(shell which ${PYTHON} 2> /dev/null))
    @printf "\033[38;5;220mFATAL\033[0m  \033[38;5;196mPython not found (${PYTHON})\033[0m\n"
    @exit 1
endif
ifneq (True, $(shell ${PYTHON} -c 'import sys; print(sys.version_info[:2] >= (3, 8))'))
    @printf "\033[38;5;220mFATAL\033[0m  \033[38;5;196mYou need at least Python 3.8\033[0m\n"
    @exit 1
endif
    @${PYTHON} -m venv --prompt licmon .venv
    @${PIP} install -q -U pip setuptools


${CONFIG}: | ${CONFIG}.example
    @printf "\033[38;5;154mSETUP\033[0m  \033[38;5;105mCreating config [\033[38;5;147m${CONFIG}\033[38;5;105m]\033[0m\n"
    @cp ${CONFIG}.example ${CONFIG}
    @printf "\033[38;5;154mSETUP\033[0m  \033[38;5;105mCreating config [\033[38;5;147m${SERVERS}\033[38;5;105m]\033[0m\n"
    @cp ${SERVERS}.example ${SERVERS}
    @sed -i.bak "s/^SECRET_KEY = None/SECRET_KEY = '$$(LC_ALL=C tr -dc A-Za-z0-9 < /dev/urandom | head -c 32)'/" ${CONFIG}
    @sed -i.bak "s/^SKIP_LOGIN = False/SKIP_LOGIN = True/" ${CONFIG}
    @sed -i.bak "s/^EMAIL_BACKEND = '[^']\+'/EMAIL_BACKEND = 'licmon.vendor.django_mail.backends.console.EmailBackend'/" ${CONFIG}
    @rm -f ${CONFIG}.bak
    @printf "       \033[38;5;82mDon't forget to update the config files if needed!\033[0m\n"


.PHONY: flask-server
flask-server:
    @printf "  \033[38;5;154mRUN\033[0m  \033[38;5;75mRunning Flask dev server [\033[38;5;81m${FLASK_HOST}\033[38;5;75m:\033[38;5;81m${FLASK_PORT}\033[38;5;75m]\033[0m\n"
    @${FLASK} run -h ${FLASK_HOST} -p ${FLASK_PORT} --extra-files $(abspath licmon/licmon.cfg):$(abspath licmon/servers.cfg)


.PHONY: build
build:
    @printf "  \033[38;5;154mBUILD\033[0m  \033[38;5;176mBuilding production package\033[0m\n"
    @rm -rf build
    @source ${VENV}/bin/activate
    @${PIP} list
    @python setup.py bdist_wheel -q


.PHONY: config
config: ${CONFIG}


.PHONY: clean
clean:
    @printf "\033[38;5;154mCLEAN\033[0m  \033[38;5;202mDeleting all generated files...\033[0m\n"
    @rm -rf .venv newdle.egg-info pip-wheel-metadata dist build
    @find newdle/ -name __pycache__ -exec rm -rf {} +
    


标签: pythonmakefile

解决方案


在确定makefile 工作正常之前,永远不要使用@来抑制回显 makefile 命令。即便如此,考虑不这样做。

另外,我敦促您避免将 ANSI 转义序列放入您的 makefile。它们读起来令人讨厌,而且并非在所有情况下都有效。绝对从您在此处提供的任何 makefile 中省略它们,因为它们不是任何最小可重现示例的一部分,除非它专门询问它们。

反正这个问题...

process_begin: CreateProcess(NULL, python3.8 -c "import sys; print(sys.version_info[:2] >= (3, 8))", ...) failed.enter code here
Makefile:24: pipe: Bad file descriptor

...似乎是这个问题的结果...

FATAL  Python not found (python3.8)

. 消息在输出中以这种方式排序,因为这是它们的生成顺序,反映了您的方法中的一个严重缺陷。

GNUmake指令,例如ifeq,在解析 makefile 时,在运行任何配方之前进行评估。因此,这段代码...

ifeq (, $(shell which ${PYTHON} 2> /dev/null))
    @printf "\033[38;5;220mFATAL\033[0m  \033[38;5;196mPython not found (${PYTHON})\033[0m\n"
    @exit 1
endif

... 如果未找到请求的 Python 解释器,则不会立即停止构建。该exit命令是配方的一部分,尚未(尚未)运行。因此,make继续以任一方式评估下一个指令:

ifneq (True, $(shell ${PYTHON} -c 'import sys; print(sys.version_info[:2] >= (3, 8))'))

. 如果确实${PYTHON}没有找到,那么正在执行的 shell 命令将失败并报告错误,但是,在函数执行过程中发生这种情况$(shell),不会终止构建。Make 决定构建${VENV}目标,并在执行该目标的配方时,最终会打印“FATAL”消息并执行@exit 1由上述保护的ifeq。这会导致make停止构建并报告.venv(== ${VENV}) 的配方有错误。

我在运行和安装 python8.3 之前创建了一个 venv,pip 也是如此。

无论可能安装或未安装什么软件,make用于执行功能的任何 shell(也将用于执行配方)在其可执行搜索路径$(shell)中没有命令。python3.8没有提供足够的信息来进一步排除故障。

此外,在其工作目录make中看不到子目录.venv,因为否则它不会为.venv目标执行配方。如果这让您感到惊讶,那么可能是make从错误的工作目录运行造成的。对此也无话可说。


总的来说,我认为你太努力了,至少在make侧面。${PYTHON}如果需要,我只会让配方中的执行失败,而不是抑制命令回显。makefile 更容易编写,诊断输出更容易解释。


推荐阅读