如何不停止 nohup 并获取输出文件

How to not stop nohup and get output files

我是 Linux 的新手。如果这是一个愚蠢的问题,我深表歉意。尽管搜索了一个多星期,我仍然无法为我的问题得出明确的答案。

我正在 运行Nvidia CPU 上编写一个很长的 Python 程序。输出是几个 csv 文件。计算输出需要很长时间,所以我使用 nohup 来退出进程。

假设 main.py 文件是这个

import numpy as p
import pandas as pd

if __name__ == ‘__main__’:
    
    a = np.arange(1,1000)
    data = a*2

    filename = ‘results.csv’

    output = pd.DataFrame(data, columns = [“Output”])
    output.to_csv(filename)

data的计算当然要复杂一些。我构建了一个 docker 容器,并在这个容器中 运行 这个程序。当我将 python main.py 用于较小的示例时,没有问题。它写入 csv 文件。

我的问题是:

  1. 当我执行 nohup python main.py & 时,我检查 docker 容器中的 tail -f nohup.out 发生了什么,我知道当时它在做什么,但我无法退出它并让执行 运行 顺其自然。它就停在那里。如何安全退出tail -f nohup.out自带的画面?

  2. 我试着不检查代码的状态,让代码继续两天,然后我回来了。 tail -f nohup.out 的输出表明执行已完成,但找不到 csv 文件。它以某种方式捆绑在 nohup.out 内,还是表示其他地方有问题?

1-容器是前台进程。在 Dockerfile.

中使用 CMDEntrypoint

2- 将 docker 中的卷映射到 linux 目录。

如果您要 运行 在 Docker 容器中进行此设置:

  1. 一个Docker容器运行s只有一个进程,作为前台进程;当该进程退出时,容器完成。该进程几乎总是您尝试 运行 而不是交互式 shell 的脚本或服务器。但是;

  2. 可以在后台使用 Docker 构造 运行 容器本身,并在 运行ning 或完成后收集其日志。

像这样的 Python 程序的典型 Docker 文件可能如下所示:

FROM python:3.10

# Create and use some directory; it can be anything, but do
# create _some_ directory.
WORKDIR /app

# Install Python dependencies as a separate step.  Doing this first
# saves time if you repeat `docker build` without changing the
# requirements list.
COPY requirements.txt .
RUN pip install -r requirements.txt

# Copy in the rest of the application.
COPY . .

# Set the main container command to be the script.
CMD ["./main.py"]

该脚本应该是可执行的(chmod +x main.py 在您的主机上)并以“shebang”行开头 (#!/usr/bin/env python3) 以便系统知道在哪里可以找到解释器。

您会听到在最后一行同时使用 CMDENTRYPOINT 的建议。这对你的直接问题并不重要。我更喜欢 CMD 有两个原因:它更容易启动备用命令来调试您的容器(docker run --rm your-image ls -ldocker run --rm --entrypoint ls your-image -l),并且有一个非常有用的使用模式 ENTRYPOINT进行一些初始设置(动态创建环境变量,运行宁数据库迁移,...)然后启动 CMD.

构建映像后,您可以使用 docker run -d option to launch it in the background, and then run docker logs 查看生成的内容。

# Build the image.
docker build -t long-python-program .

# Run it, in the background.
docker run -d --name run1 long-python-program

# Review its logs.
docker logs run1

如果您要 运行 生成需要从主机读回的文件,则需要在启动容器时将主机目录装载到容器中。您需要进行一些更改才能成功执行此操作。

在您的代码中,您需要将结果写入与您的应用程序代码不同的地方。您不能在 /app 目录上安装主机目录,因为它会隐藏您实际尝试 运行.

的代码
data_dir = os.getenv('DATA_DIR', 'data')
filename = os.path.join(data_dir, 'results.csv')

可选地,在您的 Docker 文件中,创建此目录并设置指向它的指针。由于我的示例代码从环境变量中获取其位置,您可以再次使用您想要的任何路径。

# Create the data directory.
RUN mkdir /data
ENV DATA_DIR=/data

启动容器时,docker run -v option mounts filesystems into the container. For this sort of output file you're looking for a bind mount 直接将主机目录附加到容器。

docker run -d --name run2 \
  -v "$PWD/results:/data" \
  long-python-program

在这个例子中到目前为止我们还没有设置程序的USER,它将运行作为root。您可以更改 Docker 文件以设置备用 USER(这是一个好习惯);除了该用户拥有的 data 目录外,您不需要 chown 任何东西(让 root 拥有您的代码而不是世界可写的代码也是一个好习惯)。如果这样做,启动容器时(在本机Linux上)您需要提供可以写入主机目录的主机数字用户 ID;您不需要在 Docker 文件中进行其他更改。

docker run -d --name run2 \
  -u $(id -u) \
  -v "$PWD/results:/data" \
  long-python-program