Etc
module Etc
Etc模块提供访问通常存储在Unix系统上/ etc目录中的文件中的信息。
可访问的信息包含/ etc / passwd和/ etc / group文件中的信息,以及有关系统临时目录(/ tmp)和配置目录(/ etc)的信息。
Etc模块提供了比环境变量(如+ $ USER +)更可靠的方式来访问登录用户的信息。
例:
require 'etc'
login = Etc.getlogin
info = Etc.getpwnam(login)
username = info.gecos.split(/,/).first
puts "Hello #{username}, I see your login name is #{login}"
请注意,该模块提供的方法并不总是安全的。它应该用于信息目的,而不是用于保证安全。
在这个模块中定义的所有操作都是类方法,因此您可以将Etc模块包含到您的类中。
常量
组
组是一个Struct,只有在编译时才可用HAVE_GETGRENT
。
该结构包含以下成员:
name
以String形式包含组的名称。
passwd
包含加密密码作为字符串。如果组的密码访问不可用,则返回'x'; 如果不需要密码来获取组的成员资格,则返回空字符串。
必须使用HAVE_STRUCT_GROUP_GR_PASSWD进行编译。
gid
包含组的数字ID(整数形式)。
mem
是包含组成员简短登录名的字符串数组。
Passwd
Passwd是包含以下成员的Struct:
name
包含用户的短登录名作为字符串。
passwd
包含用户的加密密码作为字符串。如果正在使用阴影密码,则会返回'x'。如果用户无法使用密码登录,则会返回'*'。
uid
包含用户的整数用户ID(uid)。
gid
包含用户主组的整数组ID(gid)。
dir
以String形式包含用户主目录的路径。
shell
包含用户的登录shell的路径作为字符串。
以下成员是可选的,并且必须使用特殊标志进行编译:
gecos
包含用户的更长字符串描述,例如全名。 一些Unix系统在gecos领域提供结构化信息,但这是依赖于系统的。 必须使用HAVE_STRUCT_PASSWD_PW_GECOS进行编译
change
password change time(integer) 必须使用HAVE_STRUCT_PASSWD_PW_CHANGE
编译
quota
quota value(integer)必须使用HAVE_STRUCT_PASSWD_PW_QUOTA进行编译
age
password age(integer)必须使用HAVE_STRUCT_PASSWD_PW_AGE进行编译
class
user access class(string)必须使用HAVE_STRUCT_PASSWD_PW_CLASS进行编译
comment
comment(string) 必须使用HAVE_STRUCT_PASSWD_PW_COMMENT进行编译
expire
account expiration time(integer) 必须使用 HAVE_STRUCT_PASSWD_PW_EXPIRE
编译
公共类方法
confstr(p1) Show source
使用confstr()返回系统配置变量。
名称应该是一个以CS_开头的常量。
返回值是一个字符串或零。 零表示没有配置定义的值。 (confstr()返回0,但没有设置errno。)
Etc.confstr(Etc::CS_PATH) #=> "/bin:/usr/bin"
# GNU/Linux
Etc.confstr(Etc::CS_GNU_LIBC_VERSION) #=> "glibc 2.18"
Etc.confstr(Etc::CS_GNU_LIBPTHREAD_VERSION) #=> "NPTL 2.18"
static VALUE
etc_confstr(VALUE obj, VALUE arg)
{
int name;
char localbuf[128], *buf = localbuf;
size_t bufsize = sizeof(localbuf), ret;
VALUE tmp;
name = NUM2INT(arg
errno = 0;
ret = confstr(name, buf, bufsize
if (bufsize < ret) {
bufsize = ret;
buf = ALLOCV_N(char, tmp, bufsize
errno = 0;
ret = confstr(name, buf, bufsize
}
if (bufsize < ret)
rb_bug("required buffer size for confstr() changed dynamically."
if (ret == 0) {
if (errno == 0) /* no configuration-defined value */
return Qnil;
rb_sys_fail("confstr"
}
return rb_str_new_cstr(buf
}
endgrent() Show source
结束对通过:: getgrent开始的/ etc / group文件进行扫描的过程,并关闭文件。
static VALUE
etc_endgrent(VALUE obj)
{
#ifdef HAVE_GETGRENT
endgrent(
#endif
return Qnil;
}
endpwent() Show source
结束通过以:: getpwent开头的/ etc / passwd文件进行扫描的过程,并关闭文件。
static VALUE
etc_endpwent(VALUE obj)
{
#ifdef HAVE_GETPWENT
endpwent(
#endif
return Qnil;
}
getgrent() Show source
从/ etc / group文件返回一个条目。
第一次被调用时,它打开文件并返回第一个条目; 每个连续的调用都会返回下一个条目,如果文件已到达结尾则返回nil
。
要在处理完成时关闭文件,请调用:: endgrent。
每个条目都以组结构的形式返回
static VALUE
etc_getgrent(VALUE obj)
{
#ifdef HAVE_GETGRENT
struct group *gr;
if ((gr = getgrent()) != 0) {
return setup_group(gr
}
#endif
return Qnil;
}
getgrgid(group_id) → Group Show source
返回与/ etc / group中指定的具有指定整数group_id的组有关的信息。
信息以组结构的形式返回。
有关更多详细信息,请参阅getgrgid(3)的unix联机帮助页。
例:
Etc.getgrgid(100)
#=> #<struct Etc::Group name="users", passwd="x", gid=100, mem=["meta", "root"]>
static VALUE
etc_getgrgid(int argc, VALUE *argv, VALUE obj)
{
#ifdef HAVE_GETGRENT
VALUE id;
gid_t gid;
struct group *grp;
if (rb_scan_args(argc, argv, "01", &id) == 1) {
gid = NUM2GIDT(id
}
else {
gid = getgid(
}
grp = getgrgid(gid
if (grp == 0) rb_raise(rb_eArgError, "can't find group for %d", (int)gid
return setup_group(grp
#else
return Qnil;
#endif
}
getgrnam(name) → Group Show source
返回有关指定组的信息name
,如/ etc / group中所示。
信息以组结构的形式返回。
有关getgrnam(3)
更多详细信息,请参见unix联机帮助页。
例:
Etc.getgrnam('users')
#=> #<struct Etc::Group name="users", passwd="x", gid=100, mem=["meta", "root"]>
static VALUE
etc_getgrnam(VALUE obj, VALUE nam)
{
#ifdef HAVE_GETGRENT
struct group *grp;
SafeStringValue(nam
grp = getgrnam(RSTRING_PTR(nam)
if (grp == 0) rb_raise(rb_eArgError, "can't find group for %"PRIsVALUE, nam
return setup_group(grp
#else
return Qnil;
#endif
}
getlogin → String Show source
返回当前登录用户的简短用户名。不幸的是,fool ::getlogin往往很容易。
Avoid ::getlogin 出于安全目的而考虑.
If ::getlogin fails, try ::getpwuid.
有关getpwuid(3)
更多详细信息,请参见unix联机帮助页。
e.g.
Etc.getlogin -> 'guest'
static VALUE
etc_getlogin(VALUE obj)
{
char *login;
#ifdef HAVE_GETLOGIN
login = getlogin(
if (!login) login = getenv("USER"
#else
login = getenv("USER"
#endif
if (login) {
#ifdef _WIN32
rb_encoding *extenc = rb_utf8_encoding(
#else
rb_encoding *extenc = rb_locale_encoding(
#endif
return rb_external_str_new_with_enc(login, strlen(login), extenc
}
return Qnil;
}
getpwent() Show source
从/ etc / passwd文件返回一个条目。
第一次被调用时,它打开文件并返回第一个条目; 每个连续的调用返回下一个条目,如果文件已到达,则返回nil。
要在处理完成时关闭文件,请调用:: endpwent。
每个条目都以Passwd结构的形式返回。
static VALUE
etc_getpwent(VALUE obj)
{
#ifdef HAVE_GETPWENT
struct passwd *pw;
if ((pw = getpwent()) != 0) {
return setup_passwd(pw
}
#endif
return Qnil;
}
getpwnam(name) → Passwd Show source
以指定的登录名返回用户的/ etc / passwd信息。
该信息作为Passwd结构返回。
有关getpwnam(3)
更多详细信息,请参见unix联机帮助页。
例:
Etc.getpwnam('root')
#=> #<struct Etc::Passwd name="root", passwd="x", uid=0, gid=0, gecos="root",dir="/root", shell="/bin/bash">
static VALUE
etc_getpwnam(VALUE obj, VALUE nam)
{
#ifdef HAVE_GETPWENT
struct passwd *pwd;
SafeStringValue(nam
pwd = getpwnam(RSTRING_PTR(nam)
if (pwd == 0) rb_raise(rb_eArgError, "can't find user for %"PRIsVALUE, nam
return setup_passwd(pwd
#else
return Qnil;
#endif
}
getpwuid(uid) → Passwd Show source
使用给定的整数uid返回用户的/ etc / passwd信息。
该信息作为Passwd结构返回。
如果省略了uid,则会返回Passwd [:uid]中的值。
有关getpwuid(3)
更多详细信息,请参见unix联机帮助页。
例:
Etc.getpwuid(0)
#=> #<struct Etc::Passwd name="root", passwd="x", uid=0, gid=0, gecos="root",dir="/root", shell="/bin/bash">
static VALUE
etc_getpwuid(int argc, VALUE *argv, VALUE obj)
{
#if defined(HAVE_GETPWENT)
VALUE id;
rb_uid_t uid;
struct passwd *pwd;
if (rb_scan_args(argc, argv, "01", &id) == 1) {
uid = NUM2UIDT(id
}
else {
uid = getuid(
}
pwd = getpwuid(uid
if (pwd == 0) rb_raise(rb_eArgError, "can't find user for %d", (int)uid
return setup_passwd(pwd
#else
return Qnil;
#endif
}
group() Show source
提供一个方便的Ruby迭代器,为/ etc / group文件中的每个条目执行一个块。
代码块通过一个组结构。
详情请参阅上面的:: getgrent。
例:
require 'etc'
Etc.group {|g|
puts g.name + ": " + g.mem.join(', ')
}
static VALUE
etc_group(VALUE obj)
{
#ifdef HAVE_GETGRENT
struct group *grp;
if (rb_block_given_p()) {
each_group(
}
else if ((grp = getgrent()) != 0) {
return setup_group(grp
}
#endif
return Qnil;
}
nprocessors() Show source
返回在线处理器的数量。
结果的目的是作为使用所有可用处理器的进程数量。
该方法使用以下方法实现:
- sched_getaffinity(): Linux
- sysconf(_SC_NPROCESSORS_ONLN): GNU/Linux, NetBSD, FreeBSD, OpenBSD, DragonFly BSD, OpenIndiana, Mac OS X, AIX
例:
require 'etc'
p Etc.nprocessors #=> 4
结果可能比物理cpu更小,特别是当ruby进程绑定到特定的cpus时。这是为了获得更好的并行处理。
Example: (Linux)
linux$ taskset 0x3 ./ruby -retc -e "p Etc.nprocessors" #=> 2
static VALUE
etc_nprocessors(VALUE obj)
{
long ret;
#if !defined(_WIN32)
#if defined(HAVE_SCHED_GETAFFINITY) && defined(CPU_ALLOC)
int ncpus;
ncpus = etc_nprocessors_affin(
if (ncpus != -1) {
return INT2NUM(ncpus
}
/* fallback to _SC_NPROCESSORS_ONLN */
#endif
errno = 0;
ret = sysconf(_SC_NPROCESSORS_ONLN
if (ret == -1) {
rb_sys_fail("sysconf(_SC_NPROCESSORS_ONLN)"
}
#else
SYSTEM_INFO si;
GetSystemInfo(&si
ret = (long)si.dwNumberOfProcessors;
#endif
return LONG2NUM(ret
}
passwd { |struct| block } → Passwd Show source
passwd → Passwd
提供一个方便的Ruby迭代器,它为/ etc / passwd文件中的每个条目执行一个块。
代码块传递一个Passwd结构。
有关详细信息,请参见上面的getpwent。
例:
require 'etc'
Etc.passwd {|u|
puts u.name + " = " + u.gecos
}
static VALUE
etc_passwd(VALUE obj)
{
#ifdef HAVE_GETPWENT
struct passwd *pw;
if (rb_block_given_p()) {
each_passwd(
}
else if ((pw = getpwent()) != 0) {
return setup_passwd(pw
}
#endif
return Qnil;
}
setgrent() Show source
重置读取/ etc / group文件的过程,以便下一次对:: getgrent的调用将再次返回第一个条目。
static VALUE
etc_setgrent(VALUE obj)
{
#ifdef HAVE_GETGRENT
setgrent(
#endif
return Qnil;
}
setpwent() Show source
重置读取/ etc / passwd文件的过程,以便下次调用:: getpwent时将再次返回第一个条目。
static VALUE
etc_setpwent(VALUE obj)
{
#ifdef HAVE_GETPWENT
setpwent(
#endif
return Qnil;
}
sysconf(p1) Show source
使用sysconf()返回系统配置变量。
名称应该是一个以SC_开头的常量。
返回值是一个整数或零。零意味着无限期的限制。(sysconf()返回-1,但没有设置errno。)
Etc.sysconf(Etc::SC_ARG_MAX) #=> 2097152
Etc.sysconf(Etc::SC_LOGIN_NAME_MAX) #=> 256
static VALUE
etc_sysconf(VALUE obj, VALUE arg)
{
int name;
long ret;
name = NUM2INT(arg
errno = 0;
ret = sysconf(name
if (ret == -1) {
if (errno == 0) /* no limit */
return Qnil;
rb_sys_fail("sysconf"
}
return LONG2NUM(ret
}
sysconfdir() Show source
返回系统配置目录。
这通常是“/ etc”,但是被Ruby编译时使用的前缀修改。例如,如果Ruby被构建并安装在/ usr / local中,则返回“/ usr / local / etc”。
static VALUE
etc_sysconfdir(VALUE obj)
{
#ifdef _WIN32
return rb_w32_special_folder(CSIDL_COMMON_APPDATA
#else
return rb_filesystem_str_new_cstr(SYSCONFDIR
#endif
}
systmpdir() Show source
返回系统临时目录; 通常是“/ tmp”。
static VALUE
etc_systmpdir(void)
{
VALUE tmpdir;
#ifdef _WIN32
WCHAR path[_MAX_PATH];
UINT len = rb_w32_system_tmpdir(path, numberof(path)
if (!len) return Qnil;
tmpdir = rb_w32_conv_from_wchar(path, rb_filesystem_encoding()
#else
const char default_tmp[] = "/tmp";
const char *tmpstr = default_tmp;
size_t tmplen = strlen(default_tmp
# if defined _CS_DARWIN_USER_TEMP_DIR
#ifndef MAXPATHLEN
#define MAXPATHLEN 1024
#endif
char path[MAXPATHLEN];
size_t len;
len = confstr(_CS_DARWIN_USER_TEMP_DIR, path, sizeof(path)
if (len > 0) {
tmpstr = path;
tmplen = len - 1;
if (len > sizeof(path)) tmpstr = 0;
}
# endif
tmpdir = rb_filesystem_str_new(tmpstr, tmplen
# if defined _CS_DARWIN_USER_TEMP_DIR
if (!tmpstr) {
confstr(_CS_DARWIN_USER_TEMP_DIR, RSTRING_PTR(tmpdir), len
}
# endif
#endif
FL_UNSET(tmpdir, FL_TAINT
return tmpdir;
}
uname() Show source
返回uname系统调用获得的系统信息。
返回值是一个散列,至少有5个键:
:sysname, :nodename, :release, :version, :machine
例:
require 'etc'
require 'pp'
pp Etc.uname
#=> {:sysname=>"Linux",
# :nodename=>"boron",
# :release=>"2.6.18-6-xen-686",
# :version=>"#1 SMP Thu Nov 5 19:54:42 UTC 2009",
# :machine=>"i686"}
static VALUE
etc_uname(VALUE obj)
{
#ifdef _WIN32
OSVERSIONINFOW v;
SYSTEM_INFO s;
const char *sysname, *mach;
VALUE result, release, version;
VALUE vbuf, nodename = Qnil;
DWORD len = 0;
WCHAR *buf;
v.dwOSVersionInfoSize = sizeof(v
if (!GetVersionExW(&v))
rb_sys_fail("GetVersionEx"
result = rb_hash_new(
switch (v.dwPlatformId) {
case VER_PLATFORM_WIN32s:
sysname = "Win32s";
break;
case VER_PLATFORM_WIN32_NT:
sysname = "Windows_NT";
break;
case VER_PLATFORM_WIN32_WINDOWS:
default:
sysname = "Windows";
break;
}
rb_hash_aset(result, ID2SYM(rb_intern("sysname")), rb_str_new_cstr(sysname)
release = rb_sprintf("%lu.%lu.%lu", v.dwMajorVersion, v.dwMinorVersion, v.dwBuildNumber
rb_hash_aset(result, ID2SYM(rb_intern("release")), release
version = rb_sprintf("%s Version %"PRIsVALUE": %"PRIsVALUE, sysname, release,
rb_w32_conv_from_wchar(v.szCSDVersion, rb_utf8_encoding())
rb_hash_aset(result, ID2SYM(rb_intern("version")), version
# if defined _MSC_VER && _MSC_VER < 1300
# define GET_COMPUTER_NAME(ptr, plen) GetComputerNameW(ptr, plen)
# else
# define GET_COMPUTER_NAME(ptr, plen) GetComputerNameExW(ComputerNameDnsFullyQualified, ptr, plen)
# endif
GET_COMPUTER_NAME(NULL, &len
buf = ALLOCV_N(WCHAR, vbuf, len
if (GET_COMPUTER_NAME(buf, &len)) {
nodename = rb_w32_conv_from_wchar(buf, rb_utf8_encoding()
}
ALLOCV_END(vbuf
if (NIL_P(nodename)) nodename = rb_str_new(0, 0
rb_hash_aset(result, ID2SYM(rb_intern("nodename")), nodename
# ifndef PROCESSOR_ARCHITECTURE_AMD64
# define PROCESSOR_ARCHITECTURE_AMD64 9
# endif
# ifndef PROCESSOR_ARCHITECTURE_IA64
# define PROCESSOR_ARCHITECTURE_IA64 6
# endif
# ifndef PROCESSOR_ARCHITECTURE_INTEL
# define PROCESSOR_ARCHITECTURE_INTEL 0
# endif
GetSystemInfo(&s
switch (s.wProcessorArchitecture) {
case PROCESSOR_ARCHITECTURE_AMD64:
mach = "x64";
break;
case PROCESSOR_ARCHITECTURE_ARM:
mach = "ARM";
break;
case PROCESSOR_ARCHITECTURE_IA64:
mach = "IA64";
break;
case PROCESSOR_ARCHITECTURE_INTEL:
mach = "x86";
break;
default:
mach = "unknown";
break;
}
rb_hash_aset(result, ID2SYM(rb_intern("machine")), rb_str_new_cstr(mach)
#else
struct utsname u;
int ret;
VALUE result;
ret = uname(&u
if (ret == -1)
rb_sys_fail("uname"
result = rb_hash_new(
rb_hash_aset(result, ID2SYM(rb_intern("sysname")), rb_str_new_cstr(u.sysname)
rb_hash_aset(result, ID2SYM(rb_intern("nodename")), rb_str_new_cstr(u.nodename)
rb_hash_aset(result, ID2SYM(rb_intern("release")), rb_str_new_cstr(u.release)
rb_hash_aset(result, ID2SYM(rb_intern("version")), rb_str_new_cstr(u.version)
rb_hash_aset(result, ID2SYM(rb_intern("machine")), rb_str_new_cstr(u.machine)
#endif
return result;
}