# 用B站录播姬配合Daemonize & SystemD，打造一台无人值守7\*24全自动批站录播机

**URL:** <https://meta.appinn.net/t/topic/28693>\
**Category:** 讨论分享\
**Tags:** linux\
**Created:** [2021 年12 月 25 日 10:48 UTC](https://meta.appinn.net/t/topic/28693 "2021-12-25T10:48:11Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

作者： ![future\_93](https://meta-edge.appinn.com/user_avatar/meta.appinn.net/future_93/32/10174_2.png) [@future\_93](https://meta.appinn.net/u/future_93)\
发布日期： [2021 年12 月 25 日 10:48 UTC](https://meta.appinn.net/t/topic/28693/1 "2021-12-25T10:48:11Z")

</div>

在B站录播姬更新2.0.0+版本后，似乎已不需要依赖daemonize作后台运行。请参考录播姬文档进行部署作业。

* * *

本文相对简略地记录了我在自己的Ubuntu服务器上搭建以守护进程方式运行的“[B站录播姬](https://rec.danmuji.org/)”的过程。不过正如标题所言，基本上也可以当作一个入门Sytemd和daemonize的参考。需要注意的是，本文记叙的并不能被称为达成此类需求的最正确或者最优雅的方法，归根结底，这只是一个菜鸡的实践笔记而已。

* * *

首先，记录一下我产生需求与决定方案的思考流程：

1. 我关注的某位B站主播没有直播录像，而我经常因为各种原因无法按时观看直播
2. 因此我计划使用[B站录播姬](https://rec.danmuji.org/)进行监控，并在主播开播时自动录像
3. 然而，我自己的日常PC并不能保证在开播时一定正在运行录播姬，同时我也不想再让录播姬占用这台小霸王上本已非常有限的系统资源
4. 正好，我手头有一台全天联网、运行Ubuntu 21.10 的x64服务器（不过录播姬是主流平台全覆盖的，所以指令集的影响不大），而且存储负载并不重（录播姬不转码，所以只吃存储负载），可以拿来再压榨一点剩余价值
5. 然而，录播姬没有后台运行模式，所以我计划用[daemonize](http://software.clapper.org/daemonize/)将其虚拟为守护进程。
6. 最后，这台服务器已经设置了自动更新重启与定时重启，所以要将这个守护进程加入到Systemd的启动项里，以免其在系统重启后摸鱼

* * *

## 整活前请注意

**没人能够预知到自己会在什么时候整出什么样的新活儿，所以请不要在不属于你的、以及公开的服务器上搞这些骚操作** ，除非你想像A站猴子一样将自己的肌肉娘XP昭告天下……  
另外， **阅读并参考本文进行操作前请确保您已经对Linux系统具有基础的理解与经验** ，因为本文中不会对诸如常见操作的具体内容等细节面面俱到地做出详解。

下面进入正题。

* * *

## 天才第一步，账户纸尿布

因为我本人多少有点专户专务的诡异洁癖，所以我的第一步便是为了这项任务建立一个专用账户。`useradd`然后用`passwd`加一个超长密码——因为如果没有意外我都是公钥登陆的，不取消密码登陆是因为我没法保证绝对没有意外 :rofl:

* * *

## 准备做a……作案工具

Systemd几乎可谓是时下Linux系统的基础之一，所以也没什么好准备的……什么你说你还在用SysV？那当我没说 :sweat_smile: 不过后续总归大差不差的。  
对于Ubuntu来说，Daemonize可以直接在APT里面搜索到已经编译好的，所以`apt install daemonize`即可。如果你的系统没有直接可用的包，请参考[daemonize主页](http://software.clapper.org/daemonize/)里的教程自己编译。

* * *

出于操作上的省心以及说明上的便利性，以上准备工作建议使用管理员账户进行（或者管理员权限级别的账户）；如果你也建立了专用账户的话，以下准备工作建议使用专用账户进行，以最大程度地避免权限导致的错误。

* * *

之前说过，录播姬也是有已经为各个平台编译好的CLI版本的，你可以在[它的Github发布页上](https://github.com/Bililive/BililiveRecorder/releases)找到自己需要的版本，在服务器上`wget`后`unzip`即可。然后你也可以将程序文件夹移动到你喜欢的地方，并改个你喜欢的名字。 **最后记得给程序文件夹及其内容递归附加执行权限。**  
然后，在诸如账户的家目录之类的地方放一个存放录像与录播姬配置文件的目录。录播姬的配置文件存储在录像目录下的`config.json`中，图方便的话可以用录播姬的GUI版本进行设置、然后将其内容拷贝到服务器端的相应文件中。录播姬自己生成的配置文件可读性极差，有强迫症的话也可以用诸如VScode上的格式化插件之类的给它整理一下，至少我用prettier整理过的版本录播姬是认的。

* * *

## 测试与测试

在写脚本之前，我们需要先进行一些小小的测试，以确保之前的操作没有再不知不觉中整出什么花活。

首先，（如果你设置了专用账户的话，用专用账户）`cd`到你的录播姬程序文件夹，用指令`./BililiveRecorder.Cli run "/<配置文件&录像存档目录的完整路径>/"`尝试启动录播姬。

**特别注意，这里的** `/<说明>/` **是指这里插入的路径应该以** `/` **开始、以** `/` **结束，并不是要你在路径外面再加俩斜杠的意思，另外说明文字两边的三角括号也请和说明文字一起替换掉、不需要留下。以下相同，不再赘述。**

如果没有问题，你会看到诸如“[时间] 连接弹幕服务器成功”的输出信号。使用SIGINT（Ctrl+C）信号干掉录播姬（反正我没找到别的办法），`cd`到录像存档目录，你会看到配置文件被复制了一份备份，以及如果你在配置文件中写入的某个直播间恰好正在直播的话，你应该能看到目录下生成了以房间号和主播名字命名的子目录，以及其中的录像和弹幕文件等等。如果出错的话，请参考录播姬的提示确定并修正问题。

在确认无误后，你可以删掉录像目录下除了配置文件外的其它文件（也就是恢复到初始状态），以方便我们的下一步测试。

现在我们要参考[Daemonize的说明文档](http://software.clapper.org/daemonize/daemonize.html)编写启动模拟守护进程的指令。如果你嫌这嫌那地不想看，也可以直接参考我自己用的指令：  
`daemonize -a -c /<录播姬程序目录>/ -e /<录像存档目录>/<错误日志文件名> -o /<录像存档目录>/<常规日志文件名> -u <专用账户的账户名> -v /<录播姬程序目录>/BililiveRecorder.Cli run "/<录像存档目录>/"`  
**注意不要遗漏了空格**  
执行你新写的指令，你应该能看到诸如

```auto
Appending to /<录像存档目录>/<常规日志文件名>
Appending to /<录像存档目录>/<错误日志文件名>

```

这样的输出。使用`ps x`指令查看后台进程，应该能看到输出中包含以下内容：

```auto
    PID TTY STAT TIME COMMAND
    ……
    114 ? Ssl 5:14 /<录播姬程序目录>/BililiveRecorder.Cli run "/<录像存档目录>/"
    ……

```

与之前一样，现在你的录像存档目录里应该已经有了一些新文件——除了配置文件备份和（可能恰好存在的）录像文件子目录外，如果之前你将常规与错误日志文件设置于此处，它们也应该存在。如果没有问题的话，错误日志应为空文件，而常规日志应包含与之前直接运行弹幕姬时的输出类似的内容。

确认无误后，使用`kill`指令干掉后台弹幕姬，然后删除刚才测试中产生的文件，准备最后一步。

* * *

## 坐上去，自己动（指SystemD)

首先，我们要建立一个启动脚本。切换回管理员账户，使用`nano /usr/bin/<脚本名>.sh `指令，在`/usr/bin/`下建立一个脚本并进入其编辑界面。

然后就写脚本呗。下面是我目前在使用的、最简单的脚本。

```auto
#!/bin/bash

daemonize_path="/<录播姬程序目录>/"
stderr_path="/<录像存档目录>/<错误日志文件名>"
stdout_path="/<录像存档目录>/<常规日志文件名>"
user="<专用账户的账户名>"
recorder_path="/<录播姬程序目录>/BililiveRecorder.Cli"
output_path="/<录像存档目录>/"

daemonize -a -c ${daemonize_path} -e ${stderr_path} -o ${stdout_path} -u ${user} -v ${recorder_path} run "${output_path}"

```

下面的这个是我计划在将来替换的带弹幕姬更新检查模块的脚本。 **注意，我尚未对其进行过测试，所以不保证其能否正常运行。**

```auto
#!/bin/bash
# 注意，以下的三角括号内的目录名均为目录本身的名字，不要画蛇添足加斜杠

user="<专用账户的账户名>"
user_home="/home/${user}"
recorder_path="${user_home}/<录播姬程序目录名>"
output_path="${user_home}/<录像存档目录名>"
stderr_path="${output_path}/<错误日志文件名>"
stdout_path="${output_path}/<常规日志文件名>"
local_recorder_version="v`${recorder_path}/BililiveRecorder.Cli --version | cut -d+ -f1`"
remote_recorder_version="`curl --silent "https://api.github.com/repos/Bililive/BililiveRecorder/releases/latest" | grep -Po '"tag_name": "\K.*?(?=")'`"

if [${remote_recorder_version} != ${local_recorder_version}]
then
    echo "Bilibili Live Recorder is upgrading..."
    wget -P ${user_home} -q https://github.com/Bililive/BililiveRecorder/releases/latest/download/BililiveRecorder-CLI-linux-x64.zip
    unzip -dq ${user_home} ${user_home}/BililiveRecorder-CLI-linux-x64.zip
    rm -rf ${user_home}/BililiveRecorder-CLI-linux-x64.zip
    rm -rf ${recorder_path}.bak
    mv ${recorder_path} ${recorder_path}.bak
    mv ${user_home}/BililiveRecorder-CLI-linux-x64 ${recorder_path}
    echo "Launching Recorder..."
else
    echo "Bilibili Live Recorder need no upgrade. Launching Recorder..."
fi

daemonize -a -c ${recorder_path} -e ${stderr_path} -o ${stdout_path} -u ${user} -v ${recorder_path}/BililiveRecorder.Cli run "${output_path}"

```

保存并退出。 **给脚本加上执行权限** ，然后测试一下，结果与善后参考上节Daemonize指令测试。

**补充说明：如果你设置了专用账户的话，测试请查看此账户的后台进程（执行** `ps x` **命令）。管理员账户的后台进程列表中显然是找不到录播姬进程的信息的。**

然后我们要编写供SystemD使用的.service文件。使用`nano /lib/systemd/system/<指定一个好写的服务名>.service`指令创建一个新的服务文件，并在其中写入以下内容：

```auto
[Unit]
Description=Bilibili Live Recorder Daemon

[Service]
ExecStart=/usr/bin/<脚本名>.sh
# 迟早有一天我要再写个EXECSTOP
Type=forking

[Install]
WantedBy=multi-user.target

```

_关于_`Type=forking`  
_在使用Daemonize牵引时必须加上这句，否则你会遇见没有任何报错但也没有任何输出的问题_

保存并退出。

现在是时候进行最终测试了。使用`systemctl daemon-reload`指令注入我们刚才编写的服务文件，然后用`systemctl enable <你刚才指定的服务名>`指令将其设置为开机启动。最后，你可以使用`systemctl start <服务名>`指令启动服务，又或者直接`reboot`，然后使用`systemctl status <服务名>`指令查看服务启动情况，并参考之前测试脚本和Daemonize指令时的结果检查录播姬是否在正常运转与输出。  
附录：参考用`systemctl status`输出

```auto
○ <服务名>.service - Bilibili Live Recorder Daemon
     Loaded: loaded (/lib/systemd/system/<服务名>.service; enabled; vendor preset: enabled)
     Active: inactive (dead) since Van 1919-08-10 11:45:14 CST; 1s ago
    Process: 1919 ExecStart=/usr/bin/<服务名>.sh (code=exited, status=0/SUCCESS)
   Main PID: 1919 (code=exited, status=0/SUCCESS)
        CPU: 810ms

```

如果一切正常，那么就是时候庆祝Rua~

* * *

FaQ

之后我会把一些不方便直接插入正文的补充内容等放在这里。

* * *

最后，感谢阅读！（指混在文字里的黄段子 :rofl:

* * *

## 参考资料

[录播姬命令行版](https://rec.danmuji.org/docs/cli/)  
[linux后台运行的几种方式](https://www.cnblogs.com/zsql/p/10827587.html)  
[Daemonize Manual](http://software.clapper.org/daemonize/daemonize.html)  
[systemd.service - Service unit configuration](http://manpages.ubuntu.com/manpages/xenial/man5/systemd.service.5.html)  
[How to Run Shell Script as SystemD Service in Linux](https://tecadmin.net/run-shell-script-as-systemd-service/)  
[lukechilds/get\_latest\_release.sh](https://gist.github.com/lukechilds/a83e1d7127b78fef38c2914c4ececc3c)

---

<div class="post-metadata">

作者： ![future\_93](https://meta-edge.appinn.com/user_avatar/meta.appinn.net/future_93/32/10174_2.png) [@future\_93](https://meta.appinn.net/u/future_93)\
发布日期： [2021 年12 月 26 日 07:34 UTC](https://meta.appinn.net/t/topic/28693/2 "2021-12-26T07:34:13Z")

</div>

## 更新历史：

[2021.12.26] 补上了带更新检查模块的启动脚本。  
[2021.12.27] 更新了更新模块，并添加了更新模块的参考资料。  
[2021.12.27] 小修一下标题，顺便改几个错别字。  
[2021.12.27] 谜之思考：如果我哪天写个自动部署脚本会不会让这帖子的热度稍微高那么一点……  
[2022.01.04] 一些拘泥于文字的修正。  
[2022.03.24] 补充说明。  
[2022.07.09] 发现录播姬更新了2.0.0+版本，似乎现在可以不依赖daemonize即可后台启动了。本文作废。

---

<div class="post-metadata">

作者： ![Qingwa](https://meta-edge.appinn.com/user_avatar/meta.appinn.net/qingwa/32/58632_2.png) [@Qingwa](https://meta.appinn.net/u/Qingwa)\
发布日期： [2021 年12 月 26 日 08:02 UTC](https://meta.appinn.net/t/topic/28693/3 "2021-12-26T08:02:50Z")

</div>

有点厉害了

---

<div class="post-metadata">

作者： ![z775729168](https://meta-edge.appinn.com/user_avatar/meta.appinn.net/z775729168/32/14574_2.png) [@z775729168](https://meta.appinn.net/u/z775729168)\
发布日期： [2021 年12 月 30 日 15:31 UTC](https://meta.appinn.net/t/topic/28693/4 "2021-12-30T15:31:21Z")

</div>

搜索了一下， [hr3lxphr6j/bililive-go: 一个直播录制工具 (github.com)](https://github.com/hr3lxphr6j/bililive-go)，这个不是更好？其实两个东西都有docker，不用这么麻烦吧，go的那个好像支持更多的网站，不过我都不看，twitch都不看，不过上面一些同步观看的还有点意思，那个都有archive，不需要实录。

---

<div class="post-metadata">

作者： ![darkmatter](https://meta-edge.appinn.com/user_avatar/meta.appinn.net/darkmatter/32/7517_2.png) [@darkmatter](https://meta.appinn.net/u/darkmatter)\
发布日期： [2021 年12 月 30 日 16:26 UTC](https://meta.appinn.net/t/topic/28693/5 "2021-12-30T16:26:29Z")

</div>

这个好像不能录弹幕 以前一直用这个的 HTTP API这个项目走在前面  
反正我录播就是靠这项目+PCSGo上传百度网盘 树莓派2G天天跑

---

<div class="post-metadata">

作者： ![darkmatter](https://meta-edge.appinn.com/user_avatar/meta.appinn.net/darkmatter/32/7517_2.png) [@darkmatter](https://meta.appinn.net/u/darkmatter)\
发布日期： [2021 年12 月 30 日 16:27 UTC](https://meta.appinn.net/t/topic/28693/6 "2021-12-30T16:27:20Z")

</div>

本来想回楼上的 live-go项目无法录弹幕

---

<div class="post-metadata">

作者： ![z775729168](https://meta-edge.appinn.com/user_avatar/meta.appinn.net/z775729168/32/14574_2.png) [@z775729168](https://meta.appinn.net/u/z775729168)\
发布日期： [2021 年12 月 30 日 17:24 UTC](https://meta.appinn.net/t/topic/28693/7 "2021-12-30T17:24:22Z")

</div>

所以就说不应该使用bilibili的服务，审查多不说，用户也太不友好了，不用感觉可以让你的生活变得更好:joy:  
虽然我说这话，但是我现在觉得自己不看YT会更好。现在PVR的东西都消化不了，要死要死。
