---
title: "你的服务器很好，现在是我的啦。"
description: "如何把你的数算课公共服务器“占为己有”（仅供娱乐）"
date: 2026-05-28T10:18:38+08:00
image: 
math: 
license: 
hidden: false
slug: "00J"
---
### 阅前须知
请自觉维护公共资源的可用性，不要大规模和他人传播此用法，不要通过此方法在服务器上运行多核重负载，更不要尝试fork炸弹。
### 背景
2026年春季学期，我加入了谢正茂老师的“数据结构与算法(B)”课程。  
这个课程有一个[课程主页](https://dsa2026.zhengmao.ltd/README.md)，在上面我发现老师贴心地为我们提供了[公用JupyterHub](https://jupyter.zhengmao.ltd/)以供我们学习课程。老师在上面发布每节课的讲义`.md`文件，上课时也直接借助JupyterHub授课。  
JupyterHub界面，左上角`File`-`New`-`Terminal`，即可打开一个Bash样式的终端窗口。  
这让我很意外。因为这意味着我可以直接登录后端服务器。
### 查成分
```bash
cat /etc/redhat-release
cat /etc/os-release
uname -r
uname -a
lscpu
free -h
df -h
```
分别返回
```
Fedora release 41 (Forty One)
```
```
NAME="Fedora Linux"
VERSION="41 (Cloud Edition)"
RELEASE_TYPE=stable
ID=fedora
VERSION_ID=41
VERSION_CODENAME=""
PLATFORM_ID="platform:f41"
PRETTY_NAME="Fedora Linux 41 (Cloud Edition)"
ANSI_COLOR="0;38;2;60;110;180"
LOGO=fedora-logo-icon
CPE_NAME="cpe:/o:fedoraproject:fedora:41"
HOME_URL="https://fedoraproject.org/"
DOCUMENTATION_URL="https://docs.fedoraproject.org/en-US/fedora/f41/"
SUPPORT_URL="https://ask.fedoraproject.org/"
BUG_REPORT_URL="https://bugzilla.redhat.com/"
REDHAT_BUGZILLA_PRODUCT="Fedora"
REDHAT_BUGZILLA_PRODUCT_VERSION=41
REDHAT_SUPPORT_PRODUCT="Fedora"
REDHAT_SUPPORT_PRODUCT_VERSION=41
SUPPORT_END=2025-12-15
VARIANT="Cloud Edition"
VARIANT_ID=cloud
```
```
6.16.7-100.fc41.x86_64
```
```
Linux nanjing.instance.cloud.lcpu.dev 6.16.7-100.fc41.x86_64 #1 SMP PREEMPT_DYNAMIC Thu Sep 11 16:41:15 UTC 2025 x86_64 GNU/Linux
```
```
Architecture:                x86_64
  CPU op-mode(s):            32-bit, 64-bit
  Address sizes:             48 bits physical, 48 bits virtual
  Byte Order:                Little Endian
CPU(s):                      16
  On-line CPU(s) list:       0-15
Vendor ID:                   AuthenticAMD
  Model name:                AMD EPYC 7773X 64-Core Processor
    CPU family:              25
    Model:                   1
    Thread(s) per core:      1
    Core(s) per socket:      1
    Socket(s):               16
    Stepping:                2
    BogoMIPS:                4391.74
    Flags:                   fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 syscall nx mmxext
                              fxsr_opt pdpe1gb rdtscp lm rep_good nopl cpuid extd_apicid tsc_known_freq pni pclmulqdq ssse3 fma cx16 pcid sse4_1
                              sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand hypervisor lahf_lm cmp_legacy svm cr8_lega
                             cy abm sse4a misalignsse 3dnowprefetch osvw perfctr_core ssbd ibrs ibpb stibp vmmcall fsgsbase tsc_adjust bmi1 avx2
                              smep bmi2 erms invpcid rdseed adx smap clflushopt clwb sha_ni xsaveopt xsavec xgetbv1 xsaves clzero xsaveerptr wbn
                             oinvd arat npt lbrv nrip_save tsc_scale vmcb_clean flushbyasid pausefilter pfthreshold v_vmsave_vmload vgif umip pk
                             u ospke vaes vpclmulqdq rdpid fsrm arch_capabilities
Virtualization features:     
  Virtualization:            AMD-V
  Hypervisor vendor:         KVM
  Virtualization type:       full
Caches (sum of all):         
  L1d:                       1 MiB (16 instances)
  L1i:                       1 MiB (16 instances)
  L2:                        8 MiB (16 instances)
  L3:                        256 MiB (16 instances)
NUMA:                        
  NUMA node(s):              1
  NUMA node0 CPU(s):         0-15
Vulnerabilities:             
  Gather data sampling:      Not affected
  Ghostwrite:                Not affected
  Indirect target selection: Not affected
  Itlb multihit:             Not affected
  L1tf:                      Not affected
  Mds:                       Not affected
  Meltdown:                  Not affected
  Mmio stale data:           Not affected
  Old microcode:             Not affected
  Reg file data sampling:    Not affected
  Retbleed:                  Not affected
  Spec rstack overflow:      Vulnerable: Safe RET, no microcode
  Spec store bypass:         Mitigation; Speculative Store Bypass disabled via prctl
  Spectre v1:                Mitigation; usercopy/swapgs barriers and __user pointer sanitization
  Spectre v2:                Mitigation; Retpolines; IBPB conditional; IBRS_FW; STIBP disabled; RSB filling; PBRSB-eIBRS Not affected; BHI Not a
                             ffected
  Srbds:                     Not affected
  Tsa:                       Vulnerable: No microcode
  Tsx async abort:           Not affected
  Vmscape:                   Not affected
```
```
               total        used        free      shared  buff/cache   available
Mem:            15Gi       2.0Gi        12Gi       5.1Mi       1.2Gi        13Gi
Swap:          8.0Gi          0B       8.0Gi
```
```
Filesystem      Size  Used Avail Use% Mounted on
/dev/sda4        29G  5.5G   23G  20% /
devtmpfs        7.8G     0  7.8G   0% /dev
tmpfs           7.8G     0  7.8G   0% /dev/shm
efivarfs        256K   17K  235K   7% /sys/firmware/efi/efivars
tmpfs           3.2G  836K  3.2G   1% /run
tmpfs           1.0M     0  1.0M   0% /run/credentials/systemd-journald.service
tmpfs           1.0M     0  1.0M   0% /run/credentials/systemd-network-generator.service
tmpfs           1.0M     0  1.0M   0% /run/credentials/systemd-udev-load-credentials.service
tmpfs           1.0M     0  1.0M   0% /run/credentials/systemd-sysctl.service
tmpfs           1.0M     0  1.0M   0% /run/credentials/systemd-tmpfiles-setup-dev-early.service
tmpfs           1.0M     0  1.0M   0% /run/credentials/systemd-tmpfiles-setup-dev.service
/dev/sda4        29G  5.5G   23G  20% /home
/dev/sda4        29G  5.5G   23G  20% /var
tmpfs           7.8G  424K  7.8G   1% /tmp
tmpfs           1.0M     0  1.0M   0% /run/credentials/systemd-vconsole-setup.service
/dev/sda3       966M  159M  742M  18% /boot
/dev/sda2       100M   18M   83M  18% /boot/efi
tmpfs           1.0M     0  1.0M   0% /run/credentials/systemd-tmpfiles-setup.service
tmpfs           1.0M     0  1.0M   0% /run/credentials/systemd-resolved.service
tmpfs           1.0M     0  1.0M   0% /run/credentials/serial-getty@ttyS0.service
tmpfs           1.0M     0  1.0M   0% /run/credentials/getty@tty1.service
```
很明显啦，这是一个来自LCPU的Fedora 41系统的Linux服务器（而且是“Cloud Edition”，这很可能意味着只有命令行环境，而没有桌面环境），运行在CLab的一个南京节点上。  
配置是基于AMD EPYC 7773X的16个vCPU，以及16GiB内存，根目录有约29GiB的存储空间。这和CLab官网的`labs_and_courses`-`l8`实例配置相吻合（一般用户可没有这么多配额捏）。  
### SSH连接
这么好的服务器，当然要试试能不能SSH进来啦。首先可以肯定的是，`sshd`服务一定是有的（不然咋管理云服务器捏）。检查一下：
```bash
systemctl status sshd
```
返回：
```
● sshd.service - OpenSSH server daemon
     Loaded: loaded (/usr/lib/systemd/system/sshd.service; enabled; preset: enabled)
    Drop-In: /usr/lib/systemd/system/service.d
             └─10-timeout-abort.conf, 50-keep-warm.conf
     Active: active (running) since Thu 2026-05-28 01:31:57 CST; 10h ago
 Invocation: 776d2e3a056b4249bf701cb7353af275
       Docs: man:sshd(8)
             man:sshd_config(5)
   Main PID: 1181 (sshd)
      Tasks: 1 (limit: 19053)
     Memory: 6.3M (peak: 9.6M)
        CPU: 140ms
     CGroup: /system.slice/sshd.service
             └─1181 "sshd: /usr/sbin/sshd -D [listener] 0 of 10-100 startups"

Warning: some journal files were not opened due to insufficient permissions.
```
没问题的话，那就直接查IP😋
```bash
ip addr show
```
返回：
```
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host noprefixroute 
       valid_lft forever preferred_lft forever
2: enp3s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether fa:16:3e:d0:7e:b6 brd ff:ff:ff:ff:ff:ff
    inet 10.<手动屏蔽IPv4>/22 brd 10.<手动屏蔽> scope global dynamic noprefixroute enp3s0
       valid_lft 50260sec preferred_lft 50260sec
    inet6 2001:<手动屏蔽IPv6>/64 scope global dynamic noprefixroute 
       valid_lft 2591999sec preferred_lft 604799sec
    inet6 fe80::f816:3eff:fed0:7eb6/64 scope link noprefixroute 
       valid_lft forever preferred_lft forever
```
这样我们就得到了IPv4和IPv6地址：分别是`10.<手动屏蔽IPv4>`和`2001:<手动屏蔽IPv6>`。  
直接SSH：在Mac上执行：（注意占位符）
```zsh
ssh <我的用户名>@2001:<手动屏蔽IPv6>
```
意外地没有报错（22端口竟然没有访问IP限制……），输入我的用户密码，就可以轻松地连上啦。  
### 设置密钥登录和VSCode Remote SSH
在Mac上输入：
```zsh
ssh-keygen -t ed25519
```
直接按3次回车，会生成私钥文件`~/.ssh/id_ed25519`和公钥文件`~/.ssh/id_ed25519.pub`。  
接下来，在Mac上输入：（注意占位符）
```zsh
ssh-copy-id -i ~/.ssh/id_ed25519.pub <我的用户名>@2001:<手动屏蔽IPv6>
```
根据提示输入一次我的密码，公钥就上传好啦。  
在Mac的`~/.ssh/config`上添加：
```
Host EPYC
  HostName 2001:<手动屏蔽IPv6>
  Port 22
  User <我的用户名>
  IdentityFile ~/.ssh/id_ed25519
  AddKeysToAgent yes
  UseKeychain yes       
```
在VSCode的“远程资源管理器”就会出现“EPYC”，连接。  
连接完成之后，这个服务器就可以用作你的远程工作区啦。不过安装VSCode扩展前，可以设置`"remote.downloadExtensionsLocally": true`，以提升安装速度。（这个服务器访问GitHub好慢诶……我也开不了代理）
### 安装命令行工具，进行C++开发
服务器上默认有`python`指令（那当然啦，JupyterHub咋不用Python……），但Clang编译器等都没有。  
Fedora 41系统使用的包管理器是DNF。常用指令：
- 安装软件：`sudo dnf install <包名>`
- 更新软件：`sudo dnf update` `sudo dnf upgrade`
- 卸载软件：`sudo dnf remove <包名>`
- 清理缓存：`sudo dnf clean all`
不幸的是，其所有命令都需要`sudo`执行，而：
```bash
sudo whoami
```
返回
```
We trust you have received the usual lecture from the local System
Administrator. It usually boils down to these three things:

    #1) Respect the privacy of others.
    #2) Think before you type.
    #3) With great power comes great responsibility.

For security reasons, the password you type will not be visible.

[sudo] password for <我的用户名>: 
```
输入密码后，返回：
```
<我的用户名> is not in the sudoers file.
```
我并没有`sudo`权限，也就无法使用DNF包管理器。  
幸运的是，我们有一个用户态包管理器：Miniconda。
```bash
curl -L https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh -o ~/Miniconda3.sh
bash ~/Miniconda3.sh -b -p ~/miniconda3
~/miniconda3/bin/conda init bash
source ~/.bashrc
conda tos accept --override-channels --channel https://repo.anaconda.com/pkgs/main
conda tos accept --override-channels --channel https://repo.anaconda.com/pkgs/r
conda config --add channels conda-forge
conda config --set channel_priority strict
```
然后就可以尽情安装软件啦。（conda-forge包生态还挺丰富的捏）
```bash
conda install git htop clang=21 clangxx=21 gcc gxx llvm libcxx-devel=21
```
（注意`libcxx-devel`是使用Clang编译器时必须额外安装的，顺便会自动安装意`libcxx-headers`，否则Clang会因为找不到libc++头文件而无法使用。这和macOS的Homebrew不一样。）  
编译C++文件时，指令需加几个参数：
```bash
clang++ -stdlib=libc++ -L$HOME/miniconda3/lib -Wl,-rpath,$HOME/miniconda3/lib cpp1.cpp -o program.out
```
因为libc++是安装到用户态的，头文件和动态链接库都不在默认查找路径，需要显式指定。
### 提供Web服务
我打算把这个服务器用作Uptime Kuma监控节点，检测我自己的服务器的运行状态。
```bash
conda install nodejs nginx                                             
```
因为服务器上不去GitHub，在本地有代理的Mac上执行：
```zsh
git clone https://github.com/louislam/uptime-kuma.git
wget -c https://github.com/louislam/uptime-kuma/releases/download/2.3.2/dist.tar.gz
```
把下载的`dist.tar.gz`放在`uptime-kuma`文件夹下，再把整个文件夹`scp`到服务器上，再在服务器上执行：
```bash
cd uptime-kuma
npm run setup
```
显示`Downloading dist https://github.com/louislam/uptime-kuma/releases/download/2.3.2/dist.tar.gz`时按Control+C取消，然后：
```bash
tar -xzf dist.tar.gz
node server/server.js
```
就可以成功启动Uptime Kuma啦。通过`10.<手动屏蔽IPv4>:3001`访问，并进行管理员初次设置。  
在我的域名控制台上把我的域名解析到这个地址后，需要通过Nginx反向代理，才能通过域名访问。  
```bash
cd ~/miniconda3/etc/nginx
mkdir -p sites.d
```
随后在`~/miniconda3/etc/nginx/sites.d/sucrose_proxy.conf`里面设置反向代理配置，在`~/miniconda3/etc/nginx/nginx.conf`设置SSL证书。  
注意：`~/miniconda3/etc/nginx/nginx.conf`里面默认的80和443端口已经被JupyterHub占用啦……我们可以改成其他端口。
再启动Nginx：
```bash
nginx
```
就好啦。  
（注意，conda安装的软件并不支持注册为系统Daemon，都是以用户身份运行在Shell窗口中，关闭Shell进程即会终止。可以配合`nohup`命令使用。）
### 总结
很好玩捏。但需要注意：不要影响公共资源的可用性，运行重负载/大量用户部署服务可能会导致JupyterHub变卡，影响同学们的正常学习。因此不建议依赖此方法。