跳转至

配置标准开发环境

约 2841 个字 255 行代码 21 张图片 预计阅读时间 13 分钟

工欲善其事,必先利其器

我们强烈推荐使用linux系统作为学习计算机学生的开发环境。为方便大家进行后续章节的学习,我们基于Ubuntu24.04为大家配置了标准开发环境,只需按照下述的教程完成配置之后即可作为后续章节学习的开发环境,同时该环境也可以作为大部分计算机相关工作的开发环境。

我们提供了虚拟机、WSL(windows subsystem for linux)、docker三种方式来配置你的开发环境。如果你对上述三种配置方式均不了解,我们推荐你使用虚拟机。完成配置后我们推荐你将虚拟机作为远程主机,使用VSCode通过SSH进行远程开发

VSCode也提供了WSL和docker的拓展用于开发

尽管VSCode也提供了WSL和docker的拓展用于在WSL和docker上更便捷的开发,其相较于SSH拓展提供了更多的功能,但我们仍然建议你基于SSH协议来进行开发。因为校内赛时你需要连接到交我算集群进行开发,此时仅可使用SSH协议来进行开发。同时对于学习计算机的同学之后将进程需要连接到服务器进行开发,此时也仅可使用SSH协议来进行开发。因此我们强烈推荐你使用SSH协议来进行开发。

虚拟机

虚拟机是一种通过软件模拟硬件环境的技术,允许在单一物理主机上运行多个独立的操作系统实例。它通过虚拟化技术将硬件资源抽象为虚拟化的计算单元,从而实现不同操作系统之间的隔离和资源隔离。该技术的主要优势在与完全与主机隔离,可以避免在开发环境中进行误操作影响到主机环境,劣势是相对来说会占用更多的硬件资源。

标准开发环境的虚拟硬盘文件(.vmdk)可通过此链接下载,因原文件较大我们提供了压缩的文件,下载后请解压。虚拟机默认用户名与密码均为xflops。我们提供了使用VMware、VirtualBox两种方式来启动虚拟机。

(可选)校验你的下载文件
SHA256(xflops_standard_env.vmdk.zip)= f308edacf588f0bdbf38d3031bc1f04afdd3e3c3c8394bb55c433dfa757ac64b

计算下载文件的SHA256值并与上述值进行对比,确认两者完全一致。

VMware

VMware是常见的商用虚拟机软件,其现在可供个人开发者免费使用,可前往官网下载。windows用户可以通过此链接下载windows版本的安装程序。

安装完成后参考下述教程完成VMWare中虚拟机的安装。

VMware配置虚拟机
  1. 打开VMWare程序点击左上角的“文件”->“新建虚拟机”。
  2. 在新建向导中选择高级。 vmware1
  3. 如下图所示选择稍后安装操作系统。 vmware2 vmware3
  4. 如下图所示选择操作系统类型。 vmware4
  5. 给你的虚拟机起一个名字如xflops_ubuntu2404vmware5
  6. 虚拟机的处理器核心数推荐为4,内存大小推荐为4096MB。可根据你的计算机的配置适当调整,但是请保证CPU核心数大于等于4。 vmware6 vmware7
  7. 网络类型选择NAT。 vmware8
  8. IO控制器与磁盘类型按照默认选项选择。 vmware9 vmware10
  9. 磁盘设置选择使用现有磁盘并选择你下载的.vmdk文件。 vmware11 vmware12
  10. 完成之后启动虚拟机并打开终端输入ip a查看IP地址。例如下图中我们要找的IP地址为192.168.203.132vmware_ip
  11. 打开主机的终端输入ssh xflops@192.168.203.132,如能成功连接则证明虚拟机安装成功。基于SSH开发可参考计算机网络-SSH章节。

VirtualBox

VirtualBox是常见的开源虚拟机软件,安装后可按照下述方法安装。

VirtualBox配置虚拟机
  1. 打开VirtualBox程序点击左上角的“管理”->“新建”
  2. 按照下图所示填写“虚拟电脑名称和类型” 虚拟电脑名称和类型
  3. 硬件配置推荐按照下图方式填写。CPU选择4核心,内存选择4096MB。可根据你的计算机的配置适当调整,但是请保证CPU核心数大于等于4。 硬件配置
  4. 虚拟硬盘处选择“使用已有的虚拟硬盘”,选择你下载的.vmdk文件。 虚拟硬盘
  5. 点击完成后启动虚拟机。

当然,我们并不需要在虚拟机的界面里面进行开发,众多开发工具均提供了基于SSH协议的远程开发方法。但是在VirtualBox中导入的虚拟机默认的网络配置中无法从主机SSH连接到虚拟机,需要我们按下述操作进行配置。

  1. 在左上方菜单“管理”->“工具”中选择“网络管理”
  2. 在“仅主机(Host-only)网络”中选择创建,按照下述配置创建一个网络: 主机网络 DHCP
  3. 在我们创建的虚拟机中选择设置,进入网络设置界面,点击“网卡2”,选择启用网络连接,选择我们在上一个步骤中创建的网络。 choose_net
  4. 然后启动虚拟机,进入虚拟机中打开终端,执行ip a命令,查看输出的网络设备的IP地址,这里我们需要找到位于我们之前创建的子网中的IP地址(如果你不知道什么是子网,可以简单的找前缀与我们创建的子网的前缀最相近的IP地址),例如下图中我们找到的IP地址即为192.168.56.109find_ip
  5. 打开你当前的主机,输入ssh xflops@<ip address>即可连接到虚拟机。基于SSH开发可参考计算机网络-SSH章节。
虚拟机配置流程

这里我们给出我们的虚拟机的完整配置流程,用于展示如何从基础的ubuntu-24.04.2-desktop.iso得到我们分发的虚拟机磁盘文件,这并不是本节需要掌握的内容,仅供感兴趣的同学参考。

  1. 使用ubuntu-24.04.2-desktop的iso文件安装Ubuntu系统
  2. 进入系统在bash中完成如下配置:

    # apt 换源
    sudo sed -i 's|http://archive.ubuntu.com|https://mirrors.tuna.tsinghua.edu.cn|g' /etc/apt/sources.list.d/ubuntu.sources
    sudo apt-get update
    sudo apt-get -y upgrade
    
    # 必要软件
    sudo apt-get -y install htop tree build-essential cmake ninja-build openssh-server openmpi-bin openmpi-common libopenmpi-dev nginx traceroute vim tmux curl gparted wireshark net-tools
    
    # pip 换源
    mkdir -p ~/.pip
    printf '[global]\nindex-url = https://pypi.tuna.tsinghua.edu.cn/simple/' > ~/.pip/pip.conf
    
    # common folders
    mkdir -p ~/apps
    mkdir -p ~/scripts
    
    # install conda
    export __MY_CONDA_INTALL_PATH=~/apps/miniconda3
    mkdir -p $__MY_CONDA_INTALL_PATH
    wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh -O $__MY_CONDA_INTALL_PATH/miniconda.sh
    bash $__MY_CONDA_INTALL_PATH/miniconda.sh -b -u -p $__MY_CONDA_INTALL_PATH
    rm $__MY_CONDA_INTALL_PATH/miniconda.sh
    unset __MY_CONDA_INTALL_PATH
    
    # nginx is only used for experiment
    sudo systemctl disable nginx.service
    
    
    # 安装docker
    # Add Docker's official GPG key:
    sudo apt-get update
    sudo apt-get install ca-certificates curl
    sudo install -m 0755 -d /etc/apt/keyrings
    sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
    sudo chmod a+r /etc/apt/keyrings/docker.asc
    
    # Add the repository to Apt sources:
    echo \
    "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu \
    $(. /etc/os-release && echo "${UBUNTU_CODENAME:-$VERSION_CODENAME}") stable" | \
    sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
    sudo apt-get update
    
    # 安装docker
    sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
    
    sudo usermod -aG docker xflops
    sudo usermod -aG wireshark xflops
    
  3. 修改下述文件:

    • ~/scripts/conda.sh
    #!/bin/sh
    _CONDA_ROOT="/home/xflops/apps/miniconda3"
    # Copyright (C) 2012 Anaconda, Inc
    # SPDX-License-Identifier: BSD-3-Clause
    \. "$_CONDA_ROOT/etc/profile.d/conda.sh" || return $?
    conda activate "$@"
    
    • ~/.tmux.conf
    set -g default-terminal "screen-256color"
    set -g mouse on
    set -g history-limit 20480
    bind-key -T copy-mode-vi Enter send-keys -X copy-selection 
    bind-key -T copy-mode Enter send-keys -X copy-selection
    
    • ~/.vimrc
    set tabstop=4   " 设置 Tab 的宽度为 4 个空格
    set softtabstop=4  " 在使用退格键或光标移动时,模拟 Tab 的宽度为 4 个空格
    set shiftwidth=4  "设置自动缩进的空格数为 4
    set expandtab    " 将 Tab 键转换为空格
    

WSL

WSL 是微软开发的一项技术,允许用户在 Windows 操作系统上直接运行 Linux 操作系统的二进制可执行文件,无需通过虚拟机或双启动方式。其具有高效资源利用和可以直接跨系统文件访问的优势。但是WSL的操作会影响主机系统,为避免因为在WSL中的误操作导致主机系统损坏,我们并不推荐刚接触Linux的同学使用WSL。

我们在WSL中配置好了标准环境并导出为文件xflops-ubuntu.tar.gz。下载此文件后在WSL中按照下述步骤完成配置标准开发环境:

(可选)校验你的下载文件
SHA256(xflops-ubuntu.tar.gz)= 38093e40d75155c684b53221a404f56ae6816efed755181c33a8ed85a51b84c5

计算下载文件的SHA256值并与上述值进行对比,确认两者完全一致。

  1. 先安装WSL,然后打开powershell使用下述命令完成导入

    wsl --import $THIS_LINUX_NAME 'X:\path\to\install' 'X:\path\to\xflops-ubuntu.tar.gz'
    

    $THIS_LINUX_NAME是你为这个发行版取的名称。

  2. 导入完成后可以在windows的菜单中输入你取的名称即可搜索到该发行版并打开。或者可以在powershell中输入下述命令启动此发行版

    wsl -d $THIS_LINUX_NAME
    

    启动发行版后运行ip a查看当前主机的IP地址。例如对于下图的情况IP地址即为172.23.232.173wsl_ip

  3. 打开powershell并输入ssh xflops@<ip>尝试连接到该发行版,如果连接成功则证明已配置完成,基于SSH开发可参考计算机网络-SSH章节。

WSL配置流程

这里给出我们的WSL的完整配置流程,用于展示如何从WSL中提供的ubuntu2404得到我们分发的WSL,这不是该部分需要学习的内容,供感兴趣的同学参考。

  1. 安装WSL提供的Ubuntu2404发行版
  2. 进入WSL在bash中运行下述命令:

    # Set hostname to xflops
    sudo bash -c "printf '[network]\nhostname=xflops\ngenerateHosts=false\n' >> /etc/wsl.conf"
    sudo bash -c "echo '127.0.0.1 localhost xflops
    ::1 ip6-localhost ip6-loopback
    fe00::0 ip6-localnet ip6-mcastprefix
    ff02::1 ip6-allnodes
    ff02::2 ip6-allrouters
    ' >> /etc/hosts"
    
    # apt 换源
    sudo sed -i 's|http://archive.ubuntu.com|https://mirrors.tuna.tsinghua.edu.cn|g' /etc/apt/sources.list.d/ubuntu.sources
    sudo apt-get update
    sudo apt-get -y upgrade
    
    # pip 换源
    mkdir -p ~/.config/pip
    printf '[global]\nindex-url = https://pypi.tuna.tsinghua.edu.cn/simple/' > ~/.config/pip/pip.conf
    
    # 必要软件
    sudo apt-get -y install htop tree zip unzip zstd build-essential cmake ninja-build openssh-server openmpi-bin openmpi-common libopenmpi-dev nginx traceroute bind9-dnsutils
    
    # nginx is only used for experiment
    sudo systemctl disable nginx
    
    # common folders
    mkdir -p ~/apps
    mkdir -p ~/scripts
    
    # conda
    wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh
    bash Miniconda3-latest-Linux-x86_64.sh -b -u -p ~/apps/miniconda3
    cat << EOF > ~/scripts/conda.sh
    #!/bin/sh
    _CONDA_ROOT="/home/xflops/apps/miniconda3"
    # Copyright (C) 2012 Anaconda, Inc
    # SPDX-License-Identifier: BSD-3-Clause
    \. "$_CONDA_ROOT/etc/profile.d/conda.sh" || return $?
    conda activate "$@"
    EOF
    rm Miniconda3-latest-Linux-x86_64.sh
    

Docker

Docker 是 Docker 公司开发的一项技术,允许用户在操作系统上通过容器化的方式运行应用程序及其依赖环境,无需依赖传统的虚拟机。其具有轻量级、启动快速和环境一致性的优势。但是 Docker 的容器隔离并非绝对安全,若在容器中进行高危操作或配置不当,可能会对主机系统的资源和安全造成潜在影响。同时由于我们的镜像中需要使用systemd管理服务,需要使用podman启动镜像。因此此方法我们推荐对 Docker 技术有一定了解的同学使用。

Podman

随着容器技术的普及,Docker 成为容器领域的标杆,但 Docker 依赖守护进程(Docker Daemon)的架构逐渐暴露出安全隐患(如需 root 权限运行)和资源占用问题。2018 年,Red Hat 推出 Podman(POD MANager),旨在提供一个无守护进程、更轻量化且遵循 OCI(开放容器倡议)标准的容器运行工具,满足开发者对高效、安全容器操作的需求。

Podman 与 Docker 在功能定位上高度相似,均支持容器的创建、运行和管理,且命令行语法基本兼容(如podman run对应docker run),便于用户平滑迁移。但二者架构差异显著:Podman 采用用户空间直接执行模式,无需后台服务,支持 rootless 容器运行,安全性和灵活性更高;而 Docker 依赖中心化守护进程,需特权模式启动。二者同属 OCI 生态,可共享容器镜像格式,但 Podman 更贴合云原生环境的轻量化需求,其也在 Kubernetes 中广泛使用。

我们给出了两种导入Docker镜像的方案,分别是:使用Dockerfile自行构建镜像和导入我们预构建好的镜像,在完成镜像导入后可参考教程运行容器实例。

使用Dockerfile自行构建镜像

  1. 复制下面的 Dockerfile 到本地目录

    Dockerfile
    FROM ubuntu:noble
    
    ARG USERNAME=xflops
    ARG PASSWORD=xflops
    ARG HOSTNAME=xflops
    ARG USER_ID=1000
    ARG GROUP_ID=1000
    
    ENV DEBIAN_FRONTEND=noninteractive
    ENV LANG=C.UTF-8
    
    #
    # === Packages ===
    #
    
    RUN apt-get update \
    && apt-get install -y --no-install-recommends ca-certificates command-not-found
    
    # use TUNA APT mirror
    RUN printf '%s\n' \
        'Types: deb' \
        'URIs: https://mirrors.tuna.tsinghua.edu.cn/ubuntu' \
        'Suites: noble noble-updates noble-backports' \
        'Components: main restricted universe multiverse' \
        'Signed-By: /usr/share/keyrings/ubuntu-archive-keyring.gpg' \
        '' \
        '# Security updates are kept from the official server for timeliness' \
        'Types: deb' \
        'URIs: http://security.ubuntu.com/ubuntu/' \
        'Suites: noble-security' \
        'Components: main restricted universe multiverse' \
        'Signed-By: /usr/share/keyrings/ubuntu-archive-keyring.gpg' \
        > /etc/apt/sources.list.d/ubuntu.sources
    
    RUN apt-get update && apt-get install -y --no-install-recommends \
        systemd-sysv \
        sudo iputils-ping net-tools nano wget curl traceroute bind9-dnsutils \
        build-essential ninja-build openssh-server htop tmux vim \ 
        tree cmake git zip unzip python3-yaml \
        nginx \
        openmpi-bin libopenmpi-dev \
        && apt-get clean && rm -rf /var/lib/apt/lists/*
    
    RUN rm -f /lib/systemd/system/multi-user.target.wants/* \
        && rm -f /etc/systemd/system/*.wants/* \
        && rm -f /lib/systemd/system/local-fs.target.wants/* \
        && rm -f /lib/systemd/system/sockets.target.wants/*udev* \
        && rm -f /lib/systemd/system/sockets.target.wants/*initctl* \
        && rm -f /lib/systemd/system/basic.target.wants/* \
        && rm -f /lib/systemd/system/anaconda.target.wants/*
    
    #
    # === User and Permissions ===
    #
    
    RUN groupmod -g $GROUP_ID -n $USERNAME ubuntu \
        && usermod -l $USERNAME -u $USER_ID -d /home/$USERNAME -m -g $USERNAME -s /bin/bash ubuntu \
        && echo "$USERNAME:$PASSWORD" | chpasswd \
        && usermod -aG sudo $USERNAME
    
    RUN echo "$USERNAME ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers
    
    RUN sed -i 's/#PermitRootLogin prohibit-password/PermitRootLogin no/' /etc/ssh/sshd_config \
        && sed -i 's/#PasswordAuthentication yes/PasswordAuthentication yes/' /etc/ssh/sshd_config
    # let ssh could login
    RUN sed -i '/^account.*required.*pam_nologin\.so/s/^/# /' /etc/pam.d/sshd
    # hostname, etc.
    RUN printf '%s\n' \
        '#!/bin/sh' \
        'set -e' \
        'export HOSTNAME=xflops' \
        '' \
        '# hostname' \
        'echo "$HOSTNAME" > /etc/hostname' \
        '' \
        '# /etc/hosts' \
        'printf "%s\\n" \' \
        '    "127.0.0.1   localhost $HOSTNAME" \' \
        '    "::1         localhost ip6-localhost ip6-loopback" \' \
        '    "fe00::0     ip6-localnet" \' \
        '    "ff00::0     ip6-mcastprefix" \' \
        '    "ff02::1     ip6-allnodes" \' \
        '    "ff02::2     ip6-allrouters" \' \
        '    > /etc/hosts' \
        '' \
        '# entrypoint execute' \
        'exec "$@"' \
        > /usr/local/bin/entrypoint.sh \
        && chmod +x /usr/local/bin/entrypoint.sh
    
    RUN systemctl enable ssh && systemctl disable nginx
    RUN systemctl mask getty@.service systemd-logind.service
    
    #
    # === Tools ===
    #
    
    USER $USERNAME
    WORKDIR /home/$USERNAME
    RUN mkdir -p $HOME/apps
    RUN wget --quiet https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh -O ~/miniconda.sh && \
        /bin/bash ~/miniconda.sh -b -p $HOME/apps/miniconda3 && \
        rm ~/miniconda.sh
    ENV PATH=$HOME/miniconda/bin:$PATH
    RUN mkdir -p $HOME/scripts
    RUN printf '%s\n' \
        '#!/bin/sh' \
        '_CONDA_ROOT="/home/xflops/apps/miniconda3"' \
        '# Copyright (C) 2012 Anaconda, Inc' \
        '# SPDX-License-Identifier: BSD-3-Clause' \
        '. "$_CONDA_ROOT/etc/profile.d/conda.sh" || return $?' \
        'conda activate "$@"' \
        > $HOME/scripts/conda.sh && \
        chmod +x $HOME/scripts/conda.sh
    
    # use TUNA pypi mirror
    RUN mkdir -p $HOME/.pip
    RUN printf '%s\n' \
        '[global]' \
        'index-url = https://pypi.tuna.tsinghua.edu.cn/simple' \
        > $HOME/.pip/pip.conf
    
    RUN mkdir -p $HOME/.vim $HOME/.config/nvim
    
    # .vim/vimrc
    RUN printf '%s\n' \
        'set mouse=a' \
        'set autoindent' \
        'set tabstop=4' \
        'set softtabstop=4' \
        'set shiftwidth=4' \
        'set expandtab' \
        'set smartindent' \
        'set autoindent' \
        > $HOME/.vim/vimrc
    
    # .tmux.conf
    RUN printf '%s\n' \
        'set -g default-terminal "screen-256color"' \
        'set -g mouse on' \
        'set -g history-limit 20480' \
        'bind-key -T copy-mode-vi Enter send-keys -X copy-selection' \
        'bind-key -T copy-mode Enter send-keys -X copy-selection' \
        > $HOME/.tmux.conf
    
    USER root
    # expose ssh
    EXPOSE 22 80
    STOPSIGNAL SIGRTMIN+3
    ENTRYPOINT ["/usr/local/bin/entrypoint.sh"]
    CMD ["/lib/systemd/systemd"]
    
  2. 运行

    podman build -t xflops-ubuntu:noble .
    # for docker
    # docker build -t xflops-ubuntu:noble .
    

    构建镜像。

导入预构建的镜像文件

  1. 点击此链接下载我们预构建的镜像文件压缩包并解压得到xflops-ubuntu.tar文件。

    (可选)校验你的下载文件
    SHA256(xflops-ubuntu.tar.zip)= 2dc3f7086f0a7295becc1cf1f60c4f21eb6201bd2642b7df412c55cd8ef6f5f6
    

    计算下载文件的SHA256值并与上述值进行对比,确认两者完全一致。

  2. 运行下述命令导入预构建的镜像文件:

    podman load -i xflops-ubuntu.tar
    # for docker
    # docker load -i xflops-ubuntu.tar
    

运行容器实例

镜像构建完成后,使用下述命令启动容器:

podman run -d --privileged --name xflops_ubuntu -p 127.0.0.1:2222:22 -p 127.0.0.1:8080:80 xflops-ubuntu:release

容器启动完成后,使用下述命令ssh连接容器:

ssh -p 2222 xflops@127.0.0.1

如连接成功则证明环境搭建成功,基于SSH开发可参考计算机网络-SSH章节。