最可靠方式是Linux/macOS用getpwuid_r(getuid())、Windows用GetUserNameW();因环境变量不可靠且易篡改,需跨平台条件编译并统一返回UTF-8字符串。
getpwuid(getuid()) 在 Linux/macOS 上取用户名最可靠POSIX 系统(Linux、macOS)下,getpwuid(getuid()) 是获取当前用户登录名的标准方式。它不依赖环境变量(比如 USER 或 LOGNAME),而是查系统密码数据库,即使用户通过 su 或 sudo 切换过身份也能返回实际登录用户(非当前有效 UID 对应的别名)。
注意:getpwuid() 返回的是 struct passwd *,其中 pw_name 字段才是用户名字符串;该函数不是线程安全的(内部用静态缓冲区),多线程中应改用 getpwuid_r()。
struct passwd *pw = getpwuid(getuid());
if (pw != nullptr) {
std::string username = pw->pw_name; // 如 "alice"
}
GetUserNameExA() 或 GetUserNameW()
Windows 没有 getpwuid,也不能信任 USERNAME 环境变量(可能被篡改或在服务进程里为空)。正确做法是调用 WinAPI:GetUserNameExA(NameSamCompatible, ...) 可得 DOMAIN\user 格式;若只要纯用户名,用 GetUserNameW() 更轻量,但返回的是宽字符,需转码。
GetUserNameW() 返回的是登录会话用户名(如 L"Bob"),不含域名WCHAR 足够),且要检查返回值是否为 FALSE 并调用 GetLastError()
std::getenv("USER") 或 "USERNAME"
环境变量不可靠:Linux 下无 USER 的情况很常见(如 systemd 服务、容器 init 进程、SSH 无 shell 登录);Windows 下 USERNAME 在某些服务上下文里为空或为 "SYSTEM",不

更危险的是,这些变量可被任意修改:
unset USER; ./myapp // Linux 下 USER 消失 set USERNAME=evil && myapp.exe // Windows 下伪造
一旦用于权限判断、日志标记或路径拼接,就可能引发越权或路径遍历。
不要写 “检测当前是不是 Windows” 的运行时逻辑(比如查 uname 输出或 GetProcAddress),既慢又易错。C++ 编译期就能确定平台,直接用 #ifdef _WIN32 分支最干净。
关键点:
getpwuid_r()(而非 getpwuid())以保证线程安全GetUserNameW(),转换时用 WideCharToMultiByte(CP_UTF8, ...),不要用 std::wstring_convert(已弃用)getenv
用户名本质是“当前登录会话的身份标识”,不是“当前进程的有效用户”。这个语义差异在容器、服务、sudo 场景下特别明显——拿错就等于认错了人。