--- 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: 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: 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变卡,影响同学们的正常学习。因此不建议依赖此方法。