модуль Etc
Модуль Etc предоставляет доступ к информации, обычно хранящейся в файлах в каталоге /etc на системах Unix.
Доступная информация состоит из информации, содержащейся в файлах /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 в свой класс.
Константы
- VERSION
-
Версия
Методы публичного класса
Исходный код
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);
} Возвращает системную конфигурационную переменную с помощью confstr().
name должно быть константой в Etc, которая начинается с CS_.
Возвращаемое значение — строка или nil. nil означает, что нет значения, определённого в конфигурации. (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_endgrent(VALUE obj)
{
#ifdef HAVE_GETGRENT
endgrent();
#endif
return Qnil;
} Завершает процесс сканирования файла /etc/group, начатого функцией ::getgrent, и закрывает файл.
Исходный код
static VALUE
etc_endpwent(VALUE obj)
{
#ifdef HAVE_GETPWENT
endpwent();
#endif
return Qnil;
} Завершает процесс сканирования файла /etc/passwd, начатого функцией ::getpwent, и закрывает файл.
Исходный код
static VALUE
etc_getgrent(VALUE obj)
{
#ifdef HAVE_GETGRENT
struct group *gr;
if ((gr = getgrent()) != 0) {
return setup_group(gr);
}
#endif
return Qnil;
} Возвращает запись из файла /etc/group.
В первый раз вызова открывает файл и возвращает первую запись; каждый последующий вызов возвращает следующую запись или nil, если достигнут конец файла.
Для закрытия файла по завершении обработки вызовите ::endgrent.
Каждая запись возвращается как структура Group.
Исходный код
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
} Возвращает информацию о группе с указанным целочисленным group_id, найденную в /etc/group.
Информация возвращается как структура Group.
См. страницу man unix для getgrgid(3) для получения подробной информации.
Пример:
Etc.getgrgid(100) #=> #<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;
const char *p = StringValueCStr(nam);
grp = getgrnam(p);
if (grp == 0) rb_raise(rb_eArgError, "can't find group for %"PRIsVALUE, nam);
return setup_group(grp);
#else
return Qnil;
#endif
} Возвращает информацию о группе с указанным name, найденную в /etc/group.
Информация возвращается как структура Group.
См. страницу man unix для getgrnam(3) для получения подробной информации.
Пример:
Etc.getgrnam('users')
#=> #<struct Etc::Group name="users", passwd="x", gid=100, mem=["meta", "root"]>
Исходный код
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;
} Возвращает короткое имя пользователя текущего вошедшего пользователя. К сожалению, часто довольно легко обмануть ::getlogin.
Избегайте использования ::getlogin в целях безопасности.
Если ::getlogin терпит неудачу, попробуйте ::getpwuid.
См. страницу man unix для getpwuid(3) для получения подробной информации.
Пример:
Etc.getlogin -> 'guest'
Исходный код
static VALUE
etc_getpwent(VALUE obj)
{
#ifdef HAVE_GETPWENT
struct passwd *pw;
if ((pw = getpwent()) != 0) {
return setup_passwd(pw);
}
#endif
return Qnil;
} Возвращает запись из файла /etc/passwd.
В первый раз вызова открывает файл и возвращает первую запись; каждый последующий вызов возвращает следующую запись или nil, если достигнут конец файла.
Для закрытия файла по завершении обработки вызовите ::endpwent.
Каждая запись возвращается как структура Passwd.
Исходный код
static VALUE
etc_getpwnam(VALUE obj, VALUE nam)
{
#ifdef HAVE_GETPWENT
struct passwd *pwd;
const char *p = StringValueCStr(nam);
pwd = getpwnam(p);
if (pwd == 0) rb_raise(rb_eArgError, "can't find user for %"PRIsVALUE, nam);
return setup_passwd(pwd);
#else
return Qnil;
#endif
} Возвращает информацию о пользователе с указанным логином name.
Информация возвращается как структура Passwd.
См. страницу man unix для getpwnam(3) для получения подробной информации.
Пример:
Etc.getpwnam('root')
#=> #<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
} Возвращает информацию о пользователе с указанным целочисленным uid.
Информация возвращается как структура Passwd.
Если uid опущено, возвращается значение из Passwd[:uid].
См. страницу man unix для getpwuid(3) для получения подробной информации.
Пример:
Etc.getpwuid(0) #=> #<struct Etc::Passwd name="root", passwd="x", uid=0, gid=0, gecos="root",dir="/root", shell="/bin/bash">
Исходный код
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;
} Предоставляет удобный итератор Ruby, который выполняет блок для каждой записи в файле /etc/group.
Блок кода получает структуру Group.
См. ::getgrent для получения подробной информации.
Пример:
require 'etc'
Etc.group {|g|
puts g.name + ": " + g.mem.join(', ')
}
Исходный код
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);
} Возвращает количество активных процессоров.
Результат предназначен для определения числа процессов, использующих все доступные процессоры.
Этот метод реализован с помощью:
-
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
Результат может быть меньше числа физических процессоров, особенно когда процесс Ruby привязан к определённым процессорам. Это предназначено для улучшения параллельной обработки.
Пример: (Linux)
linux$ taskset 0x3 ./ruby -retc -e "p Etc.nprocessors" #=> 2
Исходный код
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;
} Предоставляет удобный итератор Ruby, который выполняет блок для каждой записи в файле /etc/passwd.
Блок кода получает структуру Passwd.
См. ::getpwent выше для получения подробностей.
Пример:
require 'etc'
Etc.passwd {|u|
puts u.name + " = " + u.gecos
}
Исходный код
static VALUE
etc_setgrent(VALUE obj)
{
#ifdef HAVE_GETGRENT
setgrent();
#endif
return Qnil;
} Сбрасывает процесс чтения файла /etc/group, чтобы следующий вызов ::getgrent вернул первую запись снова.
Исходный код
static VALUE
etc_setpwent(VALUE obj)
{
#ifdef HAVE_GETPWENT
setpwent();
#endif
return Qnil;
} Сбрасывает процесс чтения файла /etc/passwd, чтобы следующий вызов ::getpwent вернул первую запись снова.
Исходный код
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);
} Возвращает системную конфигурационную переменную с помощью sysconf().
name должен быть константой в Etc, которая начинается с SC_.
Возвращаемое значение — целое число или nil. nil означает неопределенный предел. (sysconf() возвращает -1, но errno не устанавливается.)
Etc.sysconf(Etc::SC_ARG_MAX) #=> 2097152 Etc.sysconf(Etc::SC_LOGIN_NAME_MAX) #=> 256
Исходный код
static VALUE
etc_sysconfdir(VALUE obj)
{
#ifdef _WIN32
return rb_w32_special_folder(CSIDL_COMMON_APPDATA);
#elif defined(LOAD_RELATIVE)
return rb_hash_aref(rbconfig(), rb_str_new_lit("sysconfdir"));
#else
return rb_filesystem_str_new_cstr(SYSCONFDIR);
#endif
} Возвращает системный каталог конфигурации.
Как правило, это "/etc", но изменяется префиксом, используемым при компиляции Ruby. Например, если Ruby построен и установлен в /usr/local, то возвращает "/usr/local/etc" на платформах, отличных от Windows.
В Windows всегда возвращает каталог, предоставляемый системой.
Исходный код
static VALUE
etc_systmpdir(VALUE _)
{
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
#ifndef RB_PASS_KEYWORDS
/* untaint on Ruby < 2.7 */
FL_UNSET(tmpdir, FL_TAINT);
#endif
return tmpdir;
} Возвращает системный временный каталог; обычно «/tmp».
Исходный код
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, SYMBOL_LIT("sysname"), rb_str_new_cstr(sysname));
release = rb_sprintf("%lu.%lu.%lu", v.dwMajorVersion, v.dwMinorVersion, v.dwBuildNumber);
rb_hash_aset(result, SYMBOL_LIT("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, SYMBOL_LIT("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, SYMBOL_LIT("nodename"), nodename);
# ifndef PROCESSOR_ARCHITECTURE_AMD64
# define PROCESSOR_ARCHITECTURE_AMD64 9
# 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_INTEL:
mach = "x86";
break;
default:
mach = "unknown";
break;
}
rb_hash_aset(result, SYMBOL_LIT("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, SYMBOL_LIT("sysname"), rb_str_new_cstr(u.sysname));
rb_hash_aset(result, SYMBOL_LIT("nodename"), rb_str_new_cstr(u.nodename));
rb_hash_aset(result, SYMBOL_LIT("release"), rb_str_new_cstr(u.release));
rb_hash_aset(result, SYMBOL_LIT("version"), rb_str_new_cstr(u.version));
rb_hash_aset(result, SYMBOL_LIT("machine"), rb_str_new_cstr(u.machine));
#endif
return result;
} Возвращает системную информацию, полученную с помощью системного вызова 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"}
Ruby Core © 1993–2024 Yukihiro Matsumoto
Licensed under the Ruby License.
Ruby Standard Library © contributors
Licensed under their own licenses.