Ruby 2.4

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; }