服务器端C++程序编译部署入门教程
在Linux服务器上跑C++程序,核心就三件事:装好编译工具、把源码编译成可执行文件、用systemd把它托管成后台服务。
下面按这个顺序讲,命令可以直接复制执行,环境以常见的Ubuntu/Debian和CentOS/RHEL系列为例。
先把编译环境装齐
连接服务器后,先确认系统里有没有编译器:
g++ --version
gcc --version
make --version
如果提示command not found,按系统安装。
Ubuntu/Debian执行:
sudo apt update
sudo apt install -y build-essential
CentOS/RHEL系列执行:
sudo yum groupinstall -y "Development Tools"
build-essential里包含g++、gcc、make等基础工具,装完再执行一次g++ --version,能看到版本号就说明环境就绪。
写一个最小的C++服务程序
建一个工作目录,避免文件散落在root家目录:
mkdir -p /opt/hello-cpp
cd /opt/hello-cpp
创建main.cpp,这里用监听端口的方式模拟一个常驻服务:
#include
#include
#include
#include
int main() {
int port = 9000;
int server_fd = socket(AF_INET, SOCK_STREAM, 0);
if (server_fd < 0) {
std::cerr << "socket failed" << std::endl;
return 1;
}
int opt = 1;
setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
sockaddr_in addr{};
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = INADDR_ANY;
addr.sin_port = htons(port);
if (bind(server_fd, (sockaddr*)&addr, sizeof(addr)) < 0) {
std::cerr << "bind failed on port " << port << std::endl;
return 1;
}
if (listen(server_fd, 10) < 0) {
std::cerr << "listen failed" << std::endl;
return 1;
}
std::cout << "server listening on " << port << std::endl;
while (true) {
int client = accept(server_fd, nullptr, nullptr);
if (client >= 0) {
std::string msg = "hello from cpp server\n";
write(client, msg.c_str(), msg.size());
close(client);
}
}
return 0;
}
这段代码只依赖系统自带的socket库,不需要额外装第三方依赖,适合用来验证编译链路是否通。
编译并做第一次运行验证
用g++编译,注意加-pthread的习惯(本示例没用到线程,但后续扩展常需要):
g++ -O2 -Wall -o hello_server main.cpp
参数含义:-O2开启常用优化,-Wall打开编译警告,-o指定输出文件名。
编译成功后会生成hello_server可执行文件,ls -lh能看到它。
前台试跑:
./hello_server
看到server listening on 9000说明程序正常启动。
另开一个终端验证端口:
ss -tlnp | grep 9000
curl http://127.0.0.1:9000
ss能看到监听状态,curl会收到hello from cpp server。
确认无误后按Ctrl+C停掉前台进程。
用systemd托管成后台服务
前台跑没问题,但一断开SSH进程就没了。
生产环境用systemd托管,创建服务文件:
sudo vi /etc/systemd/system/hello-cpp.service
写入以下内容:
[Unit]
Description=Hello C++ TCP Server
After=network.target
[Service]
Type=simple
User=nobody
WorkingDirectory=/opt/hello-cpp
ExecStart=/opt/hello-cpp/hello_server
Restart=on-failure
RestartSec=3
[Install]
WantedBy=multi-user.target
几个关键点:User=nobody降低权限,
避免用root跑网络服务;Restart=on-failure让程序崩溃后自动拉起;WorkingDirectory保证程序读写相对路径时位置正确。
加载并启动:
sudo systemctl daemon-reload
sudo systemctl enable --now hello-cpp
sudo systemctl status hello-cpp
status里显示active (running)即成功。
如果失败,看日志定位:
journalctl -u hello-cpp -n 50 --no-pager
新手最容易踩的几个坑
编译报错先看第一条错误。 g++报错经常连锁出现,第一条往往才是根因,后面的可能是它的连带结果。
undefined reference是链接问题。 通常是用到了某个库但没加链接参数,比如用到std::thread要加-pthread,用到zlib要加-lz。
端口被占用导致bind失败。 用ss -tlnp | grep 端口号查到占用进程,换端口或停掉冲突服务;
代码里已经加了SO_REUSEADDR,能减少重启时的TIME_WAIT干扰。
改了代码忘记重新编译。 systemd启动的是旧的可执行文件,改完源码要重新执行g++,再systemctl restart hello-cpp。
权限问题。 用nobody用户运行时,程序如果要写日志文件到/opt/hello-cpp,该目录需要对nobody可写,否则会静默失败。
怎么确认真的跑起来了
服务启动后做三步复查:systemctl is-active hello-cpp应返回active;ss -tlnp能看到9000端口在监听;curl http://127.0.0.1:9000能拿到返回内容。
三项都通过,说明编译、托管、网络链路都正常。
如果要从外网访问,还需要在防火墙或安全组放行对应端口,这一步在云服务器控制台或ufw/firewalld里配置。
后续要扩展成多线程、连接数据库或加日志库时,编译命令会变长,建议写一个Makefile或CMakeLists.txt,把编译参数固定下来,避免每次手敲出错。