5个版本
使用旧的Rust 2015
0.12.1 | 2024年8月3日 |
---|---|
0.12.0 | 2024年4月23日 |
0.11.3 | 2023年9月11日 |
0.11.2 | 2023年8月25日 |
0.11.1 | 2023年8月21日 |
#21 in Unix API
58,518 个月下载量
用于 48 个crate (26 直接)
105KB
1.5K SLoC
uzers-rs
继承并继续维护未维护的 ogham/rust-users crate。向其创建者 Benjamin Sago 表示敬意。
这是一个用于访问Unix用户和组的库。它支持获取系统用户和组,将它们存储在缓存中,并创建自己的模拟表。
安装
此crate与 Cargo 一起工作。将以下内容添加到您的 Cargo.toml
依赖关系部分
[dependencies]
uzers = "0.12"
使用
在Unix中,每个用户都有一个独特的 用户ID,每个进程都有一个 有效用户ID,表示它使用的是哪个用户的权限。此外,用户可以是 组 的成员,这些组也有名称和ID。这种功能在C标准库的libc中暴露,但作为不安全的Rust接口。此包装库提供了一个安全接口,使用 User
和 Group
类型以及如 get_user_by_id
等函数,而不是低级指针和字符串。它还提供了基本的缓存功能。
它(目前)不提供 编辑 功能;返回的值是只读的。
用户
函数 get_current_uid
返回表示当前运行程序的用户的 uid_t
值,而 get_user_by_uid
函数扫描用户数据库并返回包含用户信息的 User
。当该ID没有用户时,此函数返回 None
。
User
有以下访问器
- uid: 用户的ID
- name: 用户的名称
- primary_group: 此用户主要组的ID
这是一个完整的示例,用于打印当前用户的名称。
use uzers::{get_user_by_uid, get_current_uid};
let user = get_user_by_uid(get_current_uid()).unwrap();
println!("Hello, {}!", user.name());
此代码假设(使用 unwrap()
)程序开始运行后用户未被删除。对于任意用户ID,这 并非 一个安全的假设:可能在程序运行时删除用户,或者该用户是文件的所有者,或者该用户根本不存在。因此,总是要检查返回值!
还有一个名为 get_current_username
的函数,因为它是一个非常常见的操作,所以值得特别处理。
缓存
尽管有上述警告,但用户和组数据库很少改变。虽然短程序可能只需要获取一次用户信息,但长时间运行的程序可能需要多次查询数据库,而中等长度的程序可以通过缓存值来节省冗余的系统调用。
因此,此crate提供了一个数据库的缓存接口,它提供了相同的功能,同时保留每个结果,缓存信息以便可以重用。
要引入缓存,创建一个新的 UsersCache
并在它上面调用相同的方法。例如
use uzers::{Users, Groups, UsersCache};
let mut cache = UsersCache::new();
let uid = cache.get_current_uid();
let user = cache.get_user_by_uid(uid).unwrap();
println!("Hello again, {}!", user.name());
此缓存 仅是累加的:不能删除它,也不能删除选定的条目,因为当数据库可能已被修改时,最好是完全从头开始。因此,为了实现这一点,只需开始使用一个新的 UsersCache
。
组
最后,以类似的方式可以获取组。一个 Group
有以下访问器
- gid: 组的ID
- name: 组的名称
再次,这是一个完整的示例
use uzers::{Users, Groups, UsersCache};
let mut cache = UsersCache::new();
let group = cache.get_group_by_name("admin").expect("No such group 'admin'!");
println!("The '{}' group has the ID {}", group.name(), group.gid());
日志记录
默认启用的 logging
功能使用 log
crate 在 Trace 日志级别记录与操作系统的所有交互。
注意事项
你应该准备用户和组表可能完全损坏:不应该假设ID映射到实际的用户和组,并且用户名和组名也不保证映射。
可模拟的用户和组
当你测试你的代码时,你不希望实际依赖于系统实际上有各种用户和组存在 - 有一个自定义的用户集会更好,这些用户可以保证存在,这样你就可以针对它们进行测试。
《code>mock 模块允许你创建这些自定义用户和组定义,然后使用与主库中相同的 Users
trait 访问它们,代码更改很少。
创建模拟用户
模拟用户表需要提前知道当前用户的UID。除此之外,你可以使用 add_user
和 add_group
将用户和组添加到表中
use std::sync::Arc;
use uzers::mock::{MockUsers, User, Group};
use uzers::os::unix::{UserExt, GroupExt};
let mut users = MockUsers::with_current_uid(1000);
let bobbins = User::new(1000, "Bobbins", 1000).with_home_dir("/home/bobbins");
users.add_user(bobbins);
users.add_group(Group::new(100, "funkyppl"));
导出的内容被重新导出到模拟模块中,以便有更简单的 use
行。
使用模拟用户
要设置你的程序以使用任何类型的 Users
表,让你的函数和结构体接受一个实现了 Users
trait 的泛型参数。然后,你可以传递 OS 或 Mock 类型的值。
这是一个完整的示例
use std::sync::Arc;
use uzers::{Users, UsersCache, User};
use uzers::os::unix::UserExt;
use uzers::mock::MockUsers;
fn print_current_username<U: Users>(users: &mut U) {
println!("Current user: {:?}", users.get_current_username());
}
let mut users = MockUsers::with_current_uid(1001);
users.add_user(User::new(1001, "fred", 101));
print_current_username(&mut users);
let mut actual_users = UsersCache::new();
print_current_username(&mut actual_users);