
做音视频开发这些年遇到过太多次临时要搭一个流媒体服务的需求。前阵子手头正好有一台Ubuntu 20.04的服务器需要在上面部署SRS流媒体服务器并且要求机器重启后服务能自动拉起来不能等发现问题了再手动去敲命令。这篇文章就把完整过程理一遍从SRS在Ubuntu 20.04上的编译安装、推拉流验证到用systemd把开机自启动一次配到位。适合两种人看一是刚接触SRS、想快速在Linux服务器上把直播服务跑起来的新手二是已经能启动SRS、但还没把服务托管和日志处理做利索的进阶用户。1. 动手之前先搞清楚SRS在直播链路里的位置1.1 为什么选SRS而不是其他方案流媒体服务器这个领域不算小众但真正好落地的开源方案就那么几个。Nginx加RTMP模块是最常见的选择胜在配置简单、资料多但它的能力基本被锁死在RTMP转发这一个方向上想低成本接入WebRTC基本没戏做录制、转封装、GB28181这类扩展需求时更是捉襟见肘。Janus是WebRTC领域的老牌选手作为SFU很强但部署复杂度高配置文件和信令机制都不算友好拿来当通用直播服务器用有点大材小用。ZLMediaKit性能不错社区也活跃只是整体文档和生态相对分散新手容易绕路。SRSSimple Realtime Server在这几个方案里比较均衡协议覆盖非常全RTMP、HTTP-FLV、HLS、WebRTC、SRT、GB28181都能直接支持配置文件结构清晰自带HTTP API可以做监控和回调而且社区在国内特别活跃遇到问题翻文档或者查issue都很方便。对一台Ubuntu服务器快速搭起直播服务这个诉求来说SRS基本是性价比最高的选择。1.2 SRS在直播链路里扮演的角色很多人第一次用SRS会问我到底该把它放在哪一层从架构上看SRS既可以做边缘接入层也可以做中转层。常见用法是当推流入口OBS或者编码器通过RTMP把画面推到SRSSRS负责把流分发给不同协议的播放端。比如一个活动直播场景推流端用RTMP网页播放端要延迟低就拉HTTP-FLV或WebRTC移动端直接看HLSSRS一个进程全部搞定。安防场景里摄像头RTSP流先通过ffmpeg拉出来转成RTMP推到SRS浏览器端就能用WebRTC低延迟播放这套链路很多项目都在用。选Ubuntu 20.04做宿主系统的原因也很实际LTS版本生命周期长20.04至今仍然有大量云镜像和物理机预装系统更新源稳定社区文档覆盖面广。相比CentOS系Ubuntu的依赖工具链更新编译SRS这类C项目时踩坑概率更低。2. 从零编译SRS环境依赖、源码拉取与编译参数选择2.1 基础依赖注意那个容易漏装的tcl编译SRS需要的系统包不算多但有个关键依赖很容易被忽略tcl。SRS的configure脚本本身是用Tcl写的如果系统里没有tclsh执行配置脚本时连门都进不去直接报/usr/bin/env: tclsh: No such file or directory。这个坑我在新机器上踩过不止一次很多教程也默认读者已经有了新人最容易在这里卡住。sudo apt update sudo apt upgrade -y sudo apt install -y git gcc g make autoconf automake libtool pkg-config tcl编译完成后后面推拉流验证还需要ffmpeg顺手一起装掉sudo apt install -y ffmpeg注意这里的ffmpeg不是SRS运行时的依赖而是用来做推流测试的。SRS本身并不依赖外部ffmpeg除非你要使用SRS的转封装或转码相关能力。2.2 源码拉取仓库地址和分支选择SRS源码仓库在GitHub上有国内机器拉取可能慢建议用Gitee镜像cd /usr/local/src sudo mkdir -p /usr/local/src sudo chown $USER:$USER /usr/local/src git clone -b develop https://gitee.com/ossrs/srs.git如果你不需要在配置脚本里指定太多自定义功能直接clone develop分支就行这是当前5.0主线功能最全RTC、SRT、GB28181这些模块都在里面。在/usr/local/src下操作时注意权限问题直接clone到root拥有的目录会让后续编译以普通用户身份很被动所以先chown给当前用户后面全程用普通用户编译避免给后续systemd托管埋下权限隐患。2.3 configure和make参数怎么选进入源码目录执行configure。这里有两个选择默认配置和全功能配置。cd srs/trunk ./configure默认配置编译速度快几分钟完事包含RTMP、HTTP-FLV、HLS这些基础功能适合只需要简单推拉流的场景。如果你以后可能要接WebRTC或者涉及SRT、GB28181协议建议直接用全功能编译cd srs/trunk ./configure --full make -j$(nproc)--full会把WebRTC、SRT、GB28181等全部编译进去代价是编译时间变长。以4核8G的云主机为例基本在10到15分钟。如果机器只有1G内存或者用着swap最好把-j$(nproc)换成-j1不然编译过程中可能因为内存不足被OOM杀掉之前拷贝的头文件全得重来。编译完成后二进制文件在trunk/objs/srs可以先用-v参数确认版本./objs/srs -v能正常输出版本号说明编译链路是通的。2.4 第一次手动启动前台还是后台启动SRS最直接的方式是./objs/srs -c conf/srs.conf这里有一个很关键的细节SRS进程默认可能是以daemon方式fork到后台也可能在前台运行具体取决于编译版本和默认配置。判断方法很简单执行命令后如果终端一直没有返回说明SRS正在前台运行如果命令返回了终端提示符但ps -ef | grep srs还能看到进程说明已经daemon化到了后台。这个细节对后面配置systemd至关重要。用Typesimple托管时systemd要求主进程在前台运行如果SRS自己fork走了systemd会认为服务启动失败导致各种诡异问题。所以这里先记住一个结论后面在做开机自启动时要在配置里显式加一行daemon off;强制前台运行。现在手动测试阶段看到终端不返回反而说明行为最正常CtrlC就能停止服务。3. 第一个流RTMP推流、HTTP-FLV拉流与API自检3.1 服务启动和端口检查SRS默认配置的监听端口是1935RTMP、1985HTTP API、8080HTTP服务。手动启动后先确认端口有没有起来ss -tlnp | grep -E 1935|1985|8080如果三个端口都在监听说明服务启动成功。接着用API接口做一次状态自检curl http://127.0.0.1:1985/api/v1/versions能返回一段包含SRS版本号的JSON说明HTTP API工作正常。这个接口后面做监控告警、对接自己的管理后台都很有用。3.2 准备一个测试视频没有现成视频文件时可以用ffmpeg现场生成一个带画面和声音的测试片ffmpeg -f lavfi -i testsrcsize640x480:rate30 -f lavfi -i sinefrequency440 -t 30 -pix_fmt yuv420p -c:v libx264 -c:a aac test.mp4这条命令用ffmpeg的lavfi虚拟设备生成30秒测试视频画面是彩条声音是440Hz正弦波编码成H.264和AAC正好模拟一个真实的直播视频流。3.3 推流验证ffmpeg -re -i test.mp4 -c copy -f flv rtmp://127.0.0.1/live/livestream-re参数很关键它的作用是让ffmpeg按视频原始帧率实时读取文件而不是以最快速度一次性推完。不加载-re推流的话SRS接收到的流时间线会以肉眼可见的速度瞬间结束播放端根本来不及看到画面。推流成功时SRS的控制台会打印一条类似rtmp: stream livestream publish的日志。这条命令会一直运行不退出保持推流状态方便后续拉流测试。3.4 三种协议拉流验证推流在跑的同时另开一个终端拉流。最直接的验证是RTMPffplay rtmp://127.0.0.1/live/livestream然后是HTTP-FLV对应网页直播常用的低延迟方案ffplay http://127.0.0.1:8080/live/livestream.flvHLS也顺带验证一下ffplay http://127.0.0.1:8080/live/livestream.m3u8WebRTC场景先简单提一下浏览器打开http://127.0.0.1:8080/players/rtc_player.html播放地址填webrtc://127.0.0.1/live/livestream就能走RTC线路播放。这个方法在局域网内实测延迟能到几百毫秒级别比RTMP和HLS有明显优势。如果页面打不开多半是8080端口的HTTP静态文件目录没有随编译生成完整可以重新检查编译输出或看SRS日志。3.5 远程访问时的防火墙与安全组本机验证通过后如果播放端要跨机器访问先放行防火墙端口sudo ufw allow 1935/tcp sudo ufw allow 1985/tcp sudo ufw allow 8080/tcp云服务器用户还要记得在安全组里放行对应端口。很多人在本机能推流换成从外部访问就不通查了半天发现是安全组策略没动。另外8080端口在生产环境很容易被Nginx或其他Web服务占用。遇到这种情况可以改掉SRS配置里http_server的监听端口比如改用7080然后在stream_caster或其他外链配置里同步调整地址。4. 交给systemd托管Unit文件写法与重启验证4.1 为什么不用rc.local或crontab rebootLinux上做开机自启动的方案有好几种rc.local、crontab reboot、systemd service。rc.local在Ubuntu 20.04上默认不存在需要自己创建脚本并赋执行权限而且它是串行阻塞执行脚本里若是有阻塞命令整个开机流程都会被拖慢。crontab reboot虽然能执行命令但进程一旦崩溃没有任何守护机制会自动把它拉起来流媒体服务断了就是断了得等人发现再手动处理。systemd方案有两个核心优势一是通过Restarton-failure实现进程异常退出自动拉起二是通过network-online.target等依赖项确保在网络就绪后再启动服务。单凭这两点就已经是流媒体服务器这种需要持续在线的服务最合适的选择。4.2 部署目录规划与专用用户编译产物目前还在/usr/local/src/srs从源码目录直接跑服务不是好习惯因为目录结构里混着源码和编译中间文件。建议复制到独立的部署目录sudo mkdir -p /usr/local/srs sudo cp -r /usr/local/src/srs /usr/local/srs/trunk然后是运行用户。绝对不推荐用root跑SRS因为流媒体服务要监听端口、读写日志一旦被攻击或者配置不当带来的风险会被放大。建一个专门的系统用户sudo useradd -r -s /usr/sbin/nologin srs-r表示创建系统用户-s /usr/sbin/nologin禁止该用户登录shell权限最小化。然后把部署目录的所有权交给这个用户sudo chown -R srs:srs /usr/local/srs4.3 修改配置文件daemon off和日志落盘编辑conf/srs.conf在全局配置区加上两行daemon off; srs_log_file /var/log/srs/srs.log;daemon off;让SRS强制以前台进程方式运行这是systemd托管成功的前提。日志不要再输出到标准输出指定到独立文件方便用logrotate轮转。创建日志目录并授权sudo mkdir -p /var/log/srs sudo chown srs:srs /var/log/srs4.4 完整的systemd Unit文件在/etc/systemd/system/下创建srs.service[Unit] DescriptionSRS (Simple Realtime Server) Streaming Server Afternetwork-online.target Wantsnetwork-online.target [Service] Typesimple Usersrs Groupsrs WorkingDirectory/usr/local/srs/trunk ExecStart/usr/local/srs/trunk/objs/srs -c /usr/local/srs/trunk/conf/srs.conf ExecReload/bin/kill -1 $MAINPID ExecStop/bin/kill -15 $MAINPID Restarton-failure RestartSec3 LimitNOFILE65536 [Install] WantedBymulti-user.target这个文件有几个地方值得展开解释。Typesimple配合前台运行的进程是最简单可靠的组合。SRS不死守这个设定前面已经确认过它能在前台运行所以用simple而不是forking。如果你用的其他版本默认daemon化那要么改配置加daemon off;要么改成Typeforking并配好PIDFile成本远高于前者。WorkingDirectory/usr/local/srs/trunk是容易被忽略但极重要的配置。SRS配置文件里大量用了相对路径比如HTTP静态目录./objs/nginx/html、HLS输出目录等都是以工作目录为基准解析的。如果不显式指定工作目录systemd默认用/作为起始目录SRS启动后会找不到web根目录、写不了HLS切片各种莫名其妙的404就出现了。Restarton-failure和RestartSec3组合表示只有非正常退出才自动重启并且等待3秒后拉起。这避免了正常停服时systemd反复拉起进程也确保进程崩溃后能快速恢复。LimitNOFILE65536是给进程提高文件描述符上限。流媒体服务器每一条推流和拉流都会占用一个fd默认的1024上限在几十路并发时就会撞线。这个参数不需要内核层面修改直接在unit里声明进程启动时自动生效。4.5 启用服务并做重启验证sudo systemctl daemon-reload sudo systemctl enable srs sudo systemctl start srs sudo systemctl status srssystemctl enable会在/etc/systemd/system/multi-user.target.wants/下创建软链接这就是开机自启动的生效机制。确认运行状态正常后做一次完整的重启验证sudo reboot重启完先看服务状态再检查APIsystemctl status srs curl http://127.0.0.1:1985/api/v1/versions这一步千万别省。很多人配完systemd只在当前会话里systemctl start测试一下觉得能跑就行结果重启后发现网络依赖没写好、服务启动时序不对全部原形毕露。真重启一遍才能确认自启动链路真的通了。4.6 服务起不来的排查思路systemd托管失败的常见症状和原因我整理成一张表症状可能原因排查方向systemctl status显示failedjournal里有Child process exited with codeSRS以daemon方式运行时Typesimple判定主进程退出确认配置里有daemon off;Failed at step EXECExecStart路径写错或二进制不存在核对/usr/local/srs/trunk/objs/srs是否真实存在Permission deniedsrs用户对部署目录或日志目录没有写权限chown -R srs:srs重新授权检查父目录权限端口被占用报bind失败其他服务已经占用1935/1985/8080ss -tlnp查看占用进程改SRS配置或停掉旧服务重启后服务没起来enable没执行或依赖的网络目标没生效systemctl is-enabled srs确认已启用查看network-online状态查看日志的统一手段是journalctljournalctl -u srs -n 50 --no-pager大多数问题都能从这里找到直接线索。5. 上线前值得做的几处调整资源、日志与网络安全5.1 连接数限制与内存估算SRS的max_connections默认是1000不是所有场景都适合这个值。如果机器是2G内存以内的轻量云主机建议调低到500甚至200避免并发上来后内存被打满。反过来如果机器配置不错且预期并发高可以调高但要配套调高LimitNOFILE和系统级ulimit。这里有个原理解释SRS对每个连接会分配收发缓冲区、队列和协程栈每个连接内存消耗在几十KB到几百KB之间具体跟推流还是拉流、是否录制切片有关。用4G内存的机器跑默认1000并发理论上是够的但真遇到极端情况还是要用压测工具实际测一遍别只看理论值。5.2 日志级别和logrotate轮转生产环境不要在SRS配置里开debug级别日志SRS日志默认级别是trace信息量已经很充足。我一般保持默认或设成info日志太细会产生大量磁盘IO对推流性能有可见影响。日志文件的轮转用logrotate在/etc/logrotate.d/srs里写/var/log/srs/srs.log { daily rotate 7 compress delaycompress missingok notifempty copytruncate dateext }copytruncate在这里很关键。SRS进程始终持有日志文件句柄logrotate如果不做copytruncate而直接rename并新建文件SRS还会往旧文件的inode里写磁盘空间照样被占满。加了copytruncate后logrotate会先把日志文件内容复制走再清空原文件进程那侧完全无感知不会丢日志也不需要重启SRS。5.3 最小化暴露面和安全习惯端口层面只有真正需要对外提供服务的端口才放行。1935是RTMP推流口通常必须开8080是HTTP分发和HLS口也要开1985是HTTP API口如果只做内部监控回调不建议对公网开放。安全组和ufw里把1985限定在内网网段访问即可。如果需要用SRS的HTTP API做回调或管理可以在配置里设置API token具体配置项是http_api下的api_token客户端调用API时需要携带token避免管理接口裸奔在公网。升级SRS时官方推荐的做法是保留现有配置编译新版本二进制后替换并通过systemctl restart srs完成平滑重启。SRS支持ExecReload/bin/kill -1 $MAINPID用systemctl reload srs可以优雅重载配置不中断正在进行的推拉流。这一点在长期运行的直播服务上非常实用配置调整时不用断流。另外建议在生产环境做定时备份/usr/local/srs/trunk/conf/目录配置文件是整个服务最重要的资产比二进制文件还要值钱。最后再分享一点体会。很多人部署流媒体服务习惯把进程扔到后台就完事等到服务器重启后才发现服务没了。SRS本身只是个可执行文件真正让它成为一个服务的是systemd、日志、权限、端口规划这些外围工程。这次配置完之后我建议至少做一次完整的服务器重启演练不要只测systemctl start要真重启看看服务能不能拉起来。把这一步做好后面对接摄像头、WebRTC推流、直播录制这些功能你会轻松很多。