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

Download history 11148/week @ 2024-05-03 11503/week @ 2024-05-10 9599/week @ 2024-05-17 9045/week @ 2024-05-24 9571/week @ 2024-05-31 8619/week @ 2024-06-07 9078/week @ 2024-06-14 11695/week @ 2024-06-21 9594/week @ 2024-06-28 10943/week @ 2024-07-05 12023/week @ 2024-07-12 11302/week @ 2024-07-19 12497/week @ 2024-07-26 14703/week @ 2024-08-02 14702/week @ 2024-08-09 14168/week @ 2024-08-16

58,518 个月下载量
用于 48 个crate (26 直接)

MIT 许可证

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接口。此包装库提供了一个安全接口,使用 UserGroup 类型以及如 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_useradd_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);

依赖关系