本文主要以安装部署替代 Redis 的 Garnet 为例,介绍如何排查 Linux 系统中部署 .NET 独立应用程序时遇到的问题。通过检查文件权限、依赖库、SELinux 配置等方面,解决了应用程序无法正常运行的问题。
1. 背景
Garnet 是微软研究院的新开源项目,它是一个远程缓存存储,提供了一系列独特的优势。Garnet 采用了 Redis 的 RESP 协议作为起点,这使得开发者可以使用大多数编程语言中现成的Redis客户端,例如 .NET 中的 StackExchange.Redis,来使用 Garnet。相比于其他开源缓存存储,Garnet 在性能、延迟、可扩展性和持久性方面有显著的提升。
最近在将其作为 .NET 独立应用程序部署到 Linux 系统时,遇到了一些问题。在此记录整个排查过程,希望能为其他遇到类似问题的人提供一些帮助。
2. 环境描述
- 操作系统:Anolis OS 8
- 应用程序:Garnet(.NET 独立应用程序)
- 部署方式:systemd 服务
这边 Garnet 直接通过源码生成的二进制文件进行部署,生成非框架依赖的独立应用程序,没有进行裁剪。
3. 问题描述
这里添加了执行权限,并开放了相关端口。
在控制台手动启动 Garnet 应用程序时,一切正常:
bash
./GarnetServer
但是,通过 systemd 服务启动时,应用程序却无法正常运行,报错如下:
bash
● garnet.service - Garnet Server
Loaded: loaded (/etc/systemd/system/garnet.service; enabled; vendor preset: disabled)
Active: failed (Result: exit-code) since Fri 2024-08-16 11:57:09 CST; 497ms ago
Process: 1331875 ExecStart=/root/app/garnet/GarnetServer (code=exited, status=203/EXEC)
Main PID: 1331875 (code=exited, status=203/EXEC)
4. 排查过程
4.1 确认文件权限和路径
首先确认文件是否存在并具有执行权限:
bash
ls -l /root/app/garnet/GarnetServer
输出显示文件存在并且权限正确:
bash
-rwxr-xr-x. 1 root root 74325221 8月 16 11:29 /root/app/garnet/GarnetServer
4.2 检查依赖库
使用 ldd
命令检查依赖库是否存在:
bash
ldd /root/app/garnet/GarnetServer
输出显示所有依赖库都存在:
bash
linux-vdso.so.1 (0x00007ffcc8c44000)
libpthread.so.0 => /lib64/libpthread.so.0 (0x00007fe048e00000)
libdl.so.2 => /lib64/libdl.so.2 (0x00007fe048a00000)
libz.so.1 => /lib64/libz.so.1 (0x00007fe048600000)
libm.so.6 => /lib64/libm.so.6 (0x00007fe048200000)
librt.so.1 => /lib64/librt.so.1 (0x00007fe047e00000)
libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x00007fe047a00000)
libstdc++.so.6 => /lib64/libstdc++.so.6 (0x00007fe047600000)
libc.so.6 => /lib64/libc.so.6 (0x00007fe047200000)
4.3 检查 SELinux 配置
怀疑可能是 SELinux 的问题,检查文件的 SELinux 上下文:
bash
ls -lZ /root/app/garnet/GarnetServer
输出显示文件的当前 SELinux 上下文:
bash
-rwxr-xr-x. root root unconfined_u:object_r:default_t:s0 /root/app/garnet/GarnetServer
将文件的 SELinux 类型更改为 bin_t
,以允许其被执行:
bash
sudo chcon -t bin_t /root/app/garnet/GarnetServer
再次检查文件的 SELinux 上下文,确认已更改:
bash
ls -lZ /root/app/garnet/GarnetServer
输出显示类型已更改为 bin_t
:
bash
-rwxr-xr-x. root root unconfined_u:object_r:bin_t:s0 /root/app/garnet/GarnetServer
4.4 更新 systemd 服务单元文件
确保 systemd 服务单元文件配置正确:
ini
[Unit]
Description=Garnet Server
After=network.target
[Service]
Type=simple
ExecStart=/root/app/garnet/GarnetServer
Restart=on-failure
User=root
WorkingDirectory=/root/app/garnet
StandardOutput=journal
StandardError=journal
[Install]
WantedBy=multi-user.target
4.5 刷新并重启服务
刷新 systemd 配置并重启服务:
bash
sudo systemctl daemon-reload
sudo systemctl restart garnet.service
此时服务已可以正常启动,通过 Tiny RDM 也可以正常连接查看了。
5. 结果
调整 SELinux 上下文后,Garnet 服务成功启动并运行正常。问题的根源在于 SELinux 的安全策略,默认情况下不允许执行非 bin_t
类型的文件。通过将文件类型更改为 bin_t
,解决了 203/EXEC
错误。
6. 总结
在 Linux 系统中部署应用程序时,SELinux 的安全策略常常是导致问题的原因之一。通过正确设置文件的 SELinux 上下文,可以确保应用程序正常运行。如果你在部署过程中遇到类似问题,希望这篇文章能为你提供一些帮助。