Spec-Zone.ru › Ruby 3.1

модуль Process

Модуль содержит несколько групп функциональности для обработки процессов ОС:

  • Низкоуровневое изучение свойств и управление текущим процессом, например Process.argv0, Process.pid;

  • Низкоуровневое изучение других процессов, например Process.getpgid, Process.getpriority;

  • Управление текущим процессом: Process.abort, Process.exit, Process.daemon и т. д. (для удобства большинство из них также доступны как глобальные функции и функции модуля Kernel);

  • Создание и управление дочерними процессами: Process.fork, Process.spawn и связанные методы;

  • Управление низкоуровневыми системными часами: Process.times и Process.clock_gettime, что может быть важно для правильного бенчмаркинга и других задач измерения времени выполнения.

Константы

CLOCK_BOOTTIME

см. Process.clock_gettime

CLOCK_BOOTTIME_ALARM

см. Process.clock_gettime

CLOCK_MONOTONIC

см. Process.clock_gettime

CLOCK_MONOTONIC_COARSE

см. Process.clock_gettime

CLOCK_MONOTONIC_FAST

см. Process.clock_gettime

CLOCK_MONOTONIC_PRECISE

см. Process.clock_gettime

CLOCK_MONOTONIC_RAW

см. Process.clock_gettime

CLOCK_MONOTONIC_RAW_APPROX

см. Process.clock_gettime

CLOCK_PROCESS_CPUTIME_ID

см. Process.clock_gettime

CLOCK_PROF

см. Process.clock_gettime

CLOCK_REALTIME

см. Process.clock_gettime

CLOCK_REALTIME_ALARM

см. Process.clock_gettime

CLOCK_REALTIME_COARSE

см. Process.clock_gettime

CLOCK_REALTIME_FAST

см. Process.clock_gettime

CLOCK_REALTIME_PRECISE

см. Process.clock_gettime

CLOCK_SECOND

см. Process.clock_gettime

CLOCK_TAI

см. Process.clock_gettime

CLOCK_THREAD_CPUTIME_ID

см. Process.clock_gettime

CLOCK_UPTIME

см. Process.clock_gettime

CLOCK_UPTIME_FAST

см. Process.clock_gettime

CLOCK_UPTIME_PRECISE

см. Process.clock_gettime

CLOCK_UPTIME_RAW

см. Process.clock_gettime

CLOCK_UPTIME_RAW_APPROX

см. Process.clock_gettime

CLOCK_VIRTUAL

см. Process.clock_gettime

PRIO_PGRP

см. Process.setpriority

PRIO_PROCESS

см. Process.setpriority

PRIO_USER

см. Process.setpriority

RLIMIT_AS

Максимальный размер виртуальной памяти (адресного пространства) процесса в байтах.

см. руководство системы getrlimit(2) для получения подробностей.

RLIMIT_CORE

Максимальный размер файла ядра.

см. руководство системы getrlimit(2) для получения подробностей.

RLIMIT_CPU

Предел времени выполнения процессора в секундах.

см. руководство системы getrlimit(2) для получения подробностей.

RLIMIT_DATA

Максимальный размер сегмента данных процесса.

см. руководство системы getrlimit(2) для получения подробностей.

RLIMIT_FSIZE

Максимальный размер файлов, которые может создать процесс.

см. руководство системы getrlimit(2) для получения подробностей.

RLIMIT_MEMLOCK

Максимальное количество байтов памяти, которые могут быть заблокированы в оперативной памяти.

см. руководство системы getrlimit(2) для получения подробностей.

RLIMIT_MSGQUEUE

Устанавливает предел количества байтов, которые могут быть выделены для очередей сообщений POSIX для реального идентификатора пользователя вызывающего процесса.

см. руководство системы getrlimit(2) для получения подробностей.

RLIMIT_NICE

Устанавливает предел, до которого можно повысить значение nice процесса.

см. руководство системы getrlimit(2) для получения подробностей.

RLIMIT_NOFILE

Указывает значение на единицу больше максимального номера дескриптора файла, который может быть открыт этим процессом.

см. руководство системы getrlimit(2) для получения подробностей.

RLIMIT_NPROC

Максимальное количество процессов, которые могут быть созданы для реального идентификатора пользователя вызывающего процесса.

см. руководство системы getrlimit(2) для получения подробностей.

RLIMIT_RSS

Устанавливает предел (в страницах) резидентного набора процесса.

см. руководство системы getrlimit(2) для получения подробностей.

RLIMIT_RTPRIO

Устанавливает предел реального приоритета, который может быть установлен для данного процесса.

см. руководство системы getrlimit(2) для получения подробностей.

RLIMIT_RTTIME

Устанавливает предел времени процессора, которое может использовать этот процесс, запланированный по политике планирования реального времени.

см. руководство системы getrlimit(2) для получения подробностей.

RLIMIT_SBSIZE

Максимальный размер буфера сокета.

RLIMIT_SIGPENDING

Устанавливает предел количества сигналов, которые могут быть поставлены в очередь для реального идентификатора пользователя вызывающего процесса.

см. руководство системы getrlimit(2) для получения подробностей.

RLIMIT_STACK

Максимальный размер стека в байтах.

см. руководство системы getrlimit(2) для получения подробностей.

RLIM_INFINITY

см. Process.setrlimit

RLIM_SAVED_CUR

см. Process.setrlimit

RLIM_SAVED_MAX

см. Process.setrlimit

WNOHANG

см. Process.wait

WUNTRACED

см. Process.wait

Публичные методы класса

_fork → integer Показать исходный код
VALUE
rb_proc__fork(VALUE _obj)
{
    rb_pid_t pid = rb_fork_ruby(NULL);

    if (pid == -1) {
        rb_sys_fail("fork(2)");
    }

    return PIDT2NUM(pid);
}

Внутренний API для fork. Не вызывать этот метод напрямую. В настоящее время он вызывается через Kernel#fork, Process.fork и IO.popen с "-".

Этот метод не предназначен для обычного кода, но для библиотек мониторинга приложений. Вы можете добавить пользовательский код перед и после событий fork, переопределив этот метод.

abort Показать исходный код
Kernel::abort([msg])
abort([msg])
static VALUE
f_abort(int c, const VALUE *a, VALUE _)
{
    rb_f_abort(c, a);
    UNREACHABLE_RETURN(Qnil);
}

Немедленно завершить выполнение, фактически вызвав Kernel.exit(false). Если msg задан, он записывается в STDERR перед завершением.

argv0 → frozen_string Показать исходный код
static VALUE
proc_argv0(VALUE process)
{
    return rb_orig_progname;
}

Возвращает имя скрипта, который выполняется. Значение не изменяется при присвоении нового значения $0.

Этот метод впервые появился в Ruby 2.1 для того, чтобы обеспечить глобальную переменную для получения имени скрипта.

clock_getres(clock_id [, unit]) → number Показать исходный код
static VALUE
rb_clock_getres(int argc, VALUE *argv, VALUE _)
{
    struct timetick tt;
    timetick_int_t numerators[2];
    timetick_int_t denominators[2];
    int num_numerators = 0;
    int num_denominators = 0;

    VALUE unit = (rb_check_arity(argc, 1, 2) == 2) ? argv[1] : Qnil;
    VALUE clk_id = argv[0];

    if (SYMBOL_P(clk_id)) {
#ifdef RUBY_GETTIMEOFDAY_BASED_CLOCK_REALTIME
        if (clk_id == RUBY_GETTIMEOFDAY_BASED_CLOCK_REALTIME) {
            tt.giga_count = 0;
            tt.count = 1000;
            denominators[num_denominators++] = 1000000000;
            goto success;
        }
#endif

#ifdef RUBY_TIME_BASED_CLOCK_REALTIME
        if (clk_id == RUBY_TIME_BASED_CLOCK_REALTIME) {
            tt.giga_count = 1;
            tt.count = 0;
            denominators[num_denominators++] = 1000000000;
            goto success;
        }
#endif

#ifdef RUBY_TIMES_BASED_CLOCK_MONOTONIC
        if (clk_id == RUBY_TIMES_BASED_CLOCK_MONOTONIC) {
            tt.count = 1;
            tt.giga_count = 0;
            denominators[num_denominators++] = get_clk_tck();
            goto success;
        }
#endif

#ifdef RUBY_GETRUSAGE_BASED_CLOCK_PROCESS_CPUTIME_ID
        if (clk_id == RUBY_GETRUSAGE_BASED_CLOCK_PROCESS_CPUTIME_ID) {
            tt.giga_count = 0;
            tt.count = 1000;
            denominators[num_denominators++] = 1000000000;
            goto success;
        }
#endif

#ifdef RUBY_TIMES_BASED_CLOCK_PROCESS_CPUTIME_ID
        if (clk_id == RUBY_TIMES_BASED_CLOCK_PROCESS_CPUTIME_ID) {
            tt.count = 1;
            tt.giga_count = 0;
            denominators[num_denominators++] = get_clk_tck();
            goto success;
        }
#endif

#ifdef RUBY_CLOCK_BASED_CLOCK_PROCESS_CPUTIME_ID
        if (clk_id == RUBY_CLOCK_BASED_CLOCK_PROCESS_CPUTIME_ID) {
            tt.count = 1;
            tt.giga_count = 0;
            denominators[num_denominators++] = CLOCKS_PER_SEC;
            goto success;
        }
#endif

#ifdef RUBY_MACH_ABSOLUTE_TIME_BASED_CLOCK_MONOTONIC
        if (clk_id == RUBY_MACH_ABSOLUTE_TIME_BASED_CLOCK_MONOTONIC) {
            const mach_timebase_info_data_t *info = get_mach_timebase_info();
            tt.count = 1;
            tt.giga_count = 0;
            numerators[num_numerators++] = info->numer;
            denominators[num_denominators++] = info->denom;
            denominators[num_denominators++] = 1000000000;
            goto success;
        }
#endif
    }
    else {
#if defined(HAVE_CLOCK_GETRES)
        struct timespec ts;
        clockid_t c = NUM2CLOCKID(clk_id);
        int ret = clock_getres(c, &ts);
        if (ret == -1)
            rb_sys_fail("clock_getres");
        tt.count = (int32_t)ts.tv_nsec;
        tt.giga_count = ts.tv_sec;
        denominators[num_denominators++] = 1000000000;
        goto success;
#endif
    }
    /* EINVAL emulates clock_getres behavior when clock_id is invalid. */
    rb_syserr_fail(EINVAL, 0);

  success:
    if (unit == ID2SYM(id_hertz)) {
        return timetick2dblnum_reciprocal(&tt, numerators, num_numerators, denominators, num_denominators);
    }
    else {
        return make_clock_result(&tt, numerators, num_numerators, denominators, num_denominators, unit);
    }
}

Возвращает оценку разрешения clock_id с использованием функции POSIX clock_getres().

Обратите внимание, что указанное разрешение часто неточно на большинстве платформ из-за ошибок в данной функции, поэтому указанное разрешение часто отличается от фактического разрешения часов на практике. Неточное указанное разрешение наблюдалось для различных часов, включая CLOCK_MONOTONIC и CLOCK_MONOTONIC_RAW при использовании платформ Linux, macOS, BSD или AIX, при использовании процессоров ARM или при использовании виртуализации.

clock_id задаёт тип часов. См. документ Process.clock_gettime для получения подробностей. clock_id может быть символом, как в Process.clock_gettime.

Если заданный clock_id не поддерживается, генерируется Errno::EINVAL.

unit задаёт тип возвращаемого значения. Process.clock_getres принимает unit в качестве Process.clock_gettime. Значение по умолчанию, :float_second, также совпадает со значением Process.clock_gettime.

Process.clock_getres также принимает :hertz в качестве unit. :hertz означает обратную величину :float_second.

:hertz может использоваться для получения точного значения тактов часов в секунду для функции times() и CLOCKS_PER_SEC для функции clock().

Process.clock_getres(:TIMES_BASED_CLOCK_PROCESS_CPUTIME_ID, :hertz) возвращает такты часов в секунду.

Process.clock_getres(:CLOCK_BASED_CLOCK_PROCESS_CPUTIME_ID, :hertz) возвращает CLOCKS_PER_SEC.

p Process.clock_getres(Process::CLOCK_MONOTONIC)
#=> 1.0e-09
clock_gettime(clock_id [, unit]) → number Показать исходный код
static VALUE
rb_clock_gettime(int argc, VALUE *argv, VALUE _)
{
    int ret;

    struct timetick tt;
    timetick_int_t numerators[2];
    timetick_int_t denominators[2];
    int num_numerators = 0;
    int num_denominators = 0;

    VALUE unit = (rb_check_arity(argc, 1, 2) == 2) ? argv[1] : Qnil;
    VALUE clk_id = argv[0];

    if (SYMBOL_P(clk_id)) {
        /*
         * Non-clock_gettime clocks are provided by symbol clk_id.
         */
#ifdef HAVE_GETTIMEOFDAY
        /*
         * GETTIMEOFDAY_BASED_CLOCK_REALTIME is used for
         * CLOCK_REALTIME if clock_gettime is not available.
         */
#define RUBY_GETTIMEOFDAY_BASED_CLOCK_REALTIME ID2SYM(id_GETTIMEOFDAY_BASED_CLOCK_REALTIME)
        if (clk_id == RUBY_GETTIMEOFDAY_BASED_CLOCK_REALTIME) {
            struct timeval tv;
            ret = gettimeofday(&tv, 0);
            if (ret != 0)
                rb_sys_fail("gettimeofday");
            tt.giga_count = tv.tv_sec;
            tt.count = (int32_t)tv.tv_usec * 1000;
            denominators[num_denominators++] = 1000000000;
            goto success;
        }
#endif

#define RUBY_TIME_BASED_CLOCK_REALTIME ID2SYM(id_TIME_BASED_CLOCK_REALTIME)
        if (clk_id == RUBY_TIME_BASED_CLOCK_REALTIME) {
            time_t t;
            t = time(NULL);
            if (t == (time_t)-1)
                rb_sys_fail("time");
            tt.giga_count = t;
            tt.count = 0;
            denominators[num_denominators++] = 1000000000;
            goto success;
        }

#ifdef HAVE_TIMES
#define RUBY_TIMES_BASED_CLOCK_MONOTONIC \
        ID2SYM(id_TIMES_BASED_CLOCK_MONOTONIC)
        if (clk_id == RUBY_TIMES_BASED_CLOCK_MONOTONIC) {
            struct tms buf;
            clock_t c;
            unsigned_clock_t uc;
            c = times(&buf);
            if (c ==  (clock_t)-1)
                rb_sys_fail("times");
            uc = (unsigned_clock_t)c;
            tt.count = (int32_t)(uc % 1000000000);
            tt.giga_count = (uc / 1000000000);
            denominators[num_denominators++] = get_clk_tck();
            goto success;
        }
#endif

#ifdef RUSAGE_SELF
#define RUBY_GETRUSAGE_BASED_CLOCK_PROCESS_CPUTIME_ID \
        ID2SYM(id_GETRUSAGE_BASED_CLOCK_PROCESS_CPUTIME_ID)
        if (clk_id == RUBY_GETRUSAGE_BASED_CLOCK_PROCESS_CPUTIME_ID) {
            struct rusage usage;
            int32_t usec;
            ret = getrusage(RUSAGE_SELF, &usage);
            if (ret != 0)
                rb_sys_fail("getrusage");
            tt.giga_count = usage.ru_utime.tv_sec + usage.ru_stime.tv_sec;
            usec = (int32_t)(usage.ru_utime.tv_usec + usage.ru_stime.tv_usec);
            if (1000000 <= usec) {
                tt.giga_count++;
                usec -= 1000000;
            }
            tt.count = usec * 1000;
            denominators[num_denominators++] = 1000000000;
            goto success;
        }
#endif

#ifdef HAVE_TIMES
#define RUBY_TIMES_BASED_CLOCK_PROCESS_CPUTIME_ID \
        ID2SYM(id_TIMES_BASED_CLOCK_PROCESS_CPUTIME_ID)
        if (clk_id == RUBY_TIMES_BASED_CLOCK_PROCESS_CPUTIME_ID) {
            struct tms buf;
            unsigned_clock_t utime, stime;
            if (times(&buf) ==  (clock_t)-1)
                rb_sys_fail("times");
            utime = (unsigned_clock_t)buf.tms_utime;
            stime = (unsigned_clock_t)buf.tms_stime;
            tt.count = (int32_t)((utime % 1000000000) + (stime % 1000000000));
            tt.giga_count = (utime / 1000000000) + (stime / 1000000000);
            if (1000000000 <= tt.count) {
                tt.count -= 1000000000;
                tt.giga_count++;
            }
            denominators[num_denominators++] = get_clk_tck();
            goto success;
        }
#endif

#define RUBY_CLOCK_BASED_CLOCK_PROCESS_CPUTIME_ID \
        ID2SYM(id_CLOCK_BASED_CLOCK_PROCESS_CPUTIME_ID)
        if (clk_id == RUBY_CLOCK_BASED_CLOCK_PROCESS_CPUTIME_ID) {
            clock_t c;
            unsigned_clock_t uc;
            errno = 0;
            c = clock();
            if (c == (clock_t)-1)
                rb_sys_fail("clock");
            uc = (unsigned_clock_t)c;
            tt.count = (int32_t)(uc % 1000000000);
            tt.giga_count = uc / 1000000000;
            denominators[num_denominators++] = CLOCKS_PER_SEC;
            goto success;
        }

#ifdef __APPLE__
#define RUBY_MACH_ABSOLUTE_TIME_BASED_CLOCK_MONOTONIC ID2SYM(id_MACH_ABSOLUTE_TIME_BASED_CLOCK_MONOTONIC)
        if (clk_id == RUBY_MACH_ABSOLUTE_TIME_BASED_CLOCK_MONOTONIC) {
            const mach_timebase_info_data_t *info = get_mach_timebase_info();
            uint64_t t = mach_absolute_time();
            tt.count = (int32_t)(t % 1000000000);
            tt.giga_count = t / 1000000000;
            numerators[num_numerators++] = info->numer;
            denominators[num_denominators++] = info->denom;
            denominators[num_denominators++] = 1000000000;
            goto success;
        }
#endif
    }
    else {
#if defined(HAVE_CLOCK_GETTIME)
        struct timespec ts;
        clockid_t c;
        c = NUM2CLOCKID(clk_id);
        ret = clock_gettime(c, &ts);
        if (ret == -1)
            rb_sys_fail("clock_gettime");
        tt.count = (int32_t)ts.tv_nsec;
        tt.giga_count = ts.tv_sec;
        denominators[num_denominators++] = 1000000000;
        goto success;
#endif
    }
    /* EINVAL emulates clock_gettime behavior when clock_id is invalid. */
    rb_syserr_fail(EINVAL, 0);

  success:
    return make_clock_result(&tt, numerators, num_numerators, denominators, num_denominators, unit);
}

Возвращает время, возвращённое функцией POSIX clock_gettime().

p Process.clock_gettime(Process::CLOCK_MONOTONIC)
#=> 896053.968060096

clock_id задаёт вид таймера. Он задаётся как константа, начинающаяся с Process::CLOCK_, например, Process::CLOCK_REALTIME и Process::CLOCK_MONOTONIC.

Поддерживаемые константы зависят от ОС и версии. Ruby предоставляет следующие типы clock_id, если они доступны.

CLOCK_REALTIME

SUSv2 до 4, Linux 2.5.63, FreeBSD 3.0, NetBSD 2.0, OpenBSD 2.1, macOS 10.12, Windows-8/Server-2012

CLOCK_MONOTONIC

SUSv3 до 4, Linux 2.5.63, FreeBSD 3.0, NetBSD 2.0, OpenBSD 3.4, macOS 10.12, Windows-2000

CLOCK_PROCESS_CPUTIME_ID

SUSv3 до 4, Linux 2.5.63, FreeBSD 9.3, OpenBSD 5.4, macOS 10.12

CLOCK_THREAD_CPUTIME_ID

SUSv3 до 4, Linux 2.5.63, FreeBSD 7.1, OpenBSD 5.4, macOS 10.12

CLOCK_VIRTUAL

FreeBSD 3.0, OpenBSD 2.1

CLOCK_PROF

FreeBSD 3.0, OpenBSD 2.1

CLOCK_REALTIME_FAST

FreeBSD 8.1

CLOCK_REALTIME_PRECISE

FreeBSD 8.1

CLOCK_REALTIME_COARSE

Linux 2.6.32

CLOCK_REALTIME_ALARM

Linux 3.0

CLOCK_MONOTONIC_FAST

FreeBSD 8.1

CLOCK_MONOTONIC_PRECISE

FreeBSD 8.1

CLOCK_MONOTONIC_COARSE

Linux 2.6.32

CLOCK_MONOTONIC_RAW

Linux 2.6.28, macOS 10.12

CLOCK_MONOTONIC_RAW_APPROX

macOS 10.12

CLOCK_BOOTTIME

Linux 2.6.39

CLOCK_BOOTTIME_ALARM

Linux 3.0

CLOCK_UPTIME

FreeBSD 7.0, OpenBSD 5.5

CLOCK_UPTIME_FAST

FreeBSD 8.1

CLOCK_UPTIME_RAW

macOS 10.12

CLOCK_UPTIME_RAW_APPROX

macOS 10.12

CLOCK_UPTIME_PRECISE

FreeBSD 8.1

CLOCK_SECOND

FreeBSD 8.1

CLOCK_TAI

Linux 3.10

Обратите внимание, что SUS — это Спецификация единого Unix. SUS содержит POSIX, и clock_gettime определено в части POSIX. SUS определяет CLOCK_REALTIME как обязательное, но CLOCK_MONOTONIC, CLOCK_PROCESS_CPUTIME_ID и CLOCK_THREAD_CPUTIME_ID — необязательные.

Также принимаются несколько символов в качестве clock_id. Существуют эмуляции для clock_gettime().

Например, Process::CLOCK_REALTIME определено как :GETTIMEOFDAY_BASED_CLOCK_REALTIME при отсутствии clock_gettime().

Эмуляции для CLOCK_REALTIME:

:GETTIMEOFDAY_BASED_CLOCK_REALTIME

Используйте gettimeofday(), определённую в SUS. (SUSv4 её устарела.) Разрешение — 1 микросекунда.

:TIME_BASED_CLOCK_REALTIME

Используйте time(), определённую в ISO C. Разрешение — 1 секунда.

Эмуляции для CLOCK_MONOTONIC:

:MACH_ABSOLUTE_TIME_BASED_CLOCK_MONOTONIC

Используйте mach_absolute_time(), доступную в Darwin. Разрешение зависит от процессора.

:TIMES_BASED_CLOCK_MONOTONIC

Используйте результат функции times(), определённой в POSIX. POSIX определяет её как «times() должна вернуть затраченное реальное время в тактах часов с произвольной точки в прошлом (например, времени запуска системы)». Например, GNU/Linux возвращает значение, основанное на jiffies, и оно монотонно. Однако 4.4BSD использует gettimeofday(), и оно не монотонно. (FreeBSD использует clock_gettime(CLOCK_MONOTONIC) вместо этого.) Разрешение — такт часов. Команда «getconf CLK_TCK» показывает такты часов в секунду. (Такты часов в секунду определяются макросом HZ в более старых системах.) Если это 100, а clock_t — 32-битовое целое число, разрешение — 10 миллисекунд, и оно не может представлять более 497 дней.

Эмуляции для CLOCK_PROCESS_CPUTIME_ID:

:GETRUSAGE_BASED_CLOCK_PROCESS_CPUTIME_ID

Используйте getrusage(), определённую в SUS. getrusage() используется с RUSAGE_SELF для получения времени только для вызывающего процесса (исключая время для дочерних процессов). Результат — сумма времени пользователя (ru_utime) и времени системы (ru_stime). Разрешение — 1 микросекунда.

:TIMES_BASED_CLOCK_PROCESS_CPUTIME_ID

Используйте times(), определённую в POSIX. Результат — сумма времени пользователя (tms_utime) и времени системы (tms_stime). tms_cutime и tms_cstime игнорируются для исключения времени дочерних процессов. Разрешение — такт часов. Команда «getconf CLK_TCK» показывает такты часов в секунду. (Такты часов в секунду определяются макросом HZ в более старых системах.) Если это 100, разрешение — 10 миллисекунд.

:CLOCK_BASED_CLOCK_PROCESS_CPUTIME_ID

Используйте clock(), определённую в ISO C. Разрешение — 1/CLOCKS_PER_SEC. CLOCKS_PER_SEC — макрос на уровне C, определённый в time.h. SUS определяет CLOCKS_PER_SEC как 1000000. Системы, не являющиеся Unix, могут определить его по-другому. Если CLOCKS_PER_SEC равен 1000000 (как в SUS), разрешение — 1 микросекунда. Если CLOCKS_PER_SEC равен 1000000, а clock_t — 32-битовое целое число, оно не может представлять более 72 минут.

Если заданный clock_id не поддерживается, возбуждается Errno::EINVAL.

unit задаёт тип возвращаемого значения.

:float_second

количество секунд как float (по умолчанию)

:float_millisecond

количество миллисекунд как float

:float_microsecond

количество микросекунд как float

:second

количество секунд как целое число

:millisecond

количество миллисекунд как целое число

:microsecond

количество микросекунд как целое число

:nanosecond

количество наносекунд как целое число

Базовая функция clock_gettime() возвращает количество наносекунд. Объект Float (IEEE 754 double) недостаточно для представления возвращаемого значения для CLOCK_REALTIME. Если требуется точное значение наносекунд, используйте :nanoseconds в качестве unit.

Начальное значение (ноль) возвращаемого значения варьируется. Например, время запуска системы, время запуска процесса, эпоха и т.д.

Начальное значение в CLOCK_REALTIME определено как эпоха (1970-01-01 00:00:00 UTC). Но некоторые системы учитывают високосные секунды, а другие — нет. Поэтому результат может интерпретироваться по-разному на разных системах. Рекомендуется использовать Time.now вместо CLOCK_REALTIME.

daemon() → 0 Показать исходный код
daemon(nochdir=nil,noclose=nil) → 0
static VALUE
proc_daemon(int argc, VALUE *argv, VALUE _)
{
    int n, nochdir = FALSE, noclose = FALSE;

    switch (rb_check_arity(argc, 0, 2)) {
      case 2: noclose = TO_BOOL(argv[1], "noclose");
      case 1: nochdir = TO_BOOL(argv[0], "nochdir");
    }

    prefork();
    n = rb_daemon(nochdir, noclose);
    if (n < 0) rb_sys_fail("daemon");
    return INT2FIX(n);
}

Отсоединяет процесс от управляющего терминала и запускает его в фоновом режиме как системный демон. Если аргумент nochdir не равен false, текущий рабочий каталог изменяется на корневой («/»). Если аргумент noclose не равен false, daemon() перенаправит стандартный ввод, стандартный вывод и стандартную ошибку в /dev/null. Возвращает ноль при успехе, или возбуждает одно из исключений Errno::*.

detach(pid) → thread Показать исходный код
static VALUE
proc_detach(VALUE obj, VALUE pid)
{
    return rb_detach_process(NUM2PIDT(pid));
}

Некоторые операционные системы сохраняют состояние завершённых дочерних процессов до тех пор, пока родитель не соберет это состояние (обычно с помощью варианта wait()). Если родитель никогда не собирает это состояние, дочерний процесс остаётся как зомби-процесс. Process::detach предотвращает это, создавая отдельный поток Ruby, единственная задача которого — собрать состояние процесса pid при его завершении. Используйте detach только тогда, когда вы не планируете явно ждать завершения дочернего процесса.

Ожидающий поток возвращает код завершения отсоединённого процесса при его завершении, поэтому вы можете использовать Thread#join, чтобы узнать результат. Если указанный pid не является корректным идентификатором дочернего процесса, поток возвращает nil немедленно.

Ожидающий поток имеет метод pid, который возвращает pid.

В этом первом примере мы не собираем первый дочерний процесс, поэтому он отображается как зомби в представлении состояния процесса.

p1 = fork { sleep 0.1 }
p2 = fork { sleep 0.2 }
Process.waitpid(p2)
sleep 2
system("ps -ho pid,state -p #{p1}")

вывод:

27389 Z

В следующем примере используется Process::detach для автоматического сбора дочернего процесса.

p1 = fork { sleep 0.1 }
p2 = fork { sleep 0.2 }
Process.detach(p1)
Process.waitpid(p2)
sleep 2
system("ps -ho pid,state -p #{p1}")

(не выводит ничего)

egid → целое Показать исходный код
Process::GID.eid → целое
Process::Sys.geteid → целое
static VALUE
proc_getegid(VALUE obj)
{
    rb_gid_t egid = getegid();

    return GIDT2NUM(egid);
}

Возвращает эффективный идентификатор группы для данного процесса. Недоступно на всех платформах.

Process.egid   #=> 500
egid = целое → целое Показать исходный код
static VALUE
proc_setegid(VALUE obj, VALUE egid)
{
#if defined(HAVE_SETRESGID) || defined(HAVE_SETREGID) || defined(HAVE_SETEGID) || defined(HAVE_SETGID)
    rb_gid_t gid;
#endif

    check_gid_switch();

#if defined(HAVE_SETRESGID) || defined(HAVE_SETREGID) || defined(HAVE_SETEGID) || defined(HAVE_SETGID)
    gid = OBJ2GID(egid);
#endif

#if defined(HAVE_SETRESGID)
    if (setresgid(-1, gid, -1) < 0) rb_sys_fail(0);
#elif defined HAVE_SETREGID
    if (setregid(-1, gid) < 0) rb_sys_fail(0);
#elif defined HAVE_SETEGID
    if (setegid(gid) < 0) rb_sys_fail(0);
#elif defined HAVE_SETGID
    if (gid == getgid()) {
        if (setgid(gid) < 0) rb_sys_fail(0);
    }
    else {
        rb_notimplement();
    }
#else
    rb_notimplement();
#endif
    return egid;
}

Устанавливает эффективный идентификатор группы для данного процесса. Недоступно на всех платформах.

euid → целое Показать исходный код
Process::UID.eid → целое
Process::Sys.geteuid → целое
static VALUE
proc_geteuid(VALUE obj)
{
    rb_uid_t euid = geteuid();
    return UIDT2NUM(euid);
}

Возвращает эффективный идентификатор пользователя для данного процесса.

Process.euid   #=> 501
euid= пользователь Показать исходный код
static VALUE
proc_seteuid_m(VALUE mod, VALUE euid)
{
    check_uid_switch();
    proc_seteuid(OBJ2UID(euid));
    return euid;
}

Устанавливает эффективный идентификатор пользователя для данного процесса. Недоступно на всех платформах.

exec([env,] command... [,options]) Показать исходный код
static VALUE
f_exec(int c, const VALUE *a, VALUE _)
{
    rb_f_exec(c, a);
    UNREACHABLE_RETURN(Qnil);
}

Заменяет текущий процесс, выполнив заданную внешнюю команду, которая может иметь один из следующих форматов:

exec(commandline)

строка командной строки, которая передаётся стандартной оболочке

exec(cmdname, arg1, ...)

имя команды и один или несколько аргументов (без оболочки)

exec([cmdname, argv0], arg1, ...)

имя команды, argv и ноль или более аргументов (без оболочки)

В первом формате строка рассматривается как командная строка, которая обрабатывается оболочкой перед выполнением.

Стандартная оболочка всегда означает "/bin/sh" на системах Unix-подобных, иначе ENV["RUBYSHELL"] или ENV["COMSPEC"] на Windows и аналогичных. Команда передаётся в качестве аргумента переключателю "-c" оболочки, за исключением случая COMSPEC.

Если строка из первого формата (exec("command")) следует этим простым правилам:

  • нет символов метакоманд

  • не начинается со служебного слова оболочки или специального встроенного

  • Ruby вызывает команду непосредственно без оболочки

Вы можете принудительно вызвать оболочку, добавив «;» к строке (потому что «;» — символ метакоманды).

Обратите внимание, что это поведение можно наблюдать по полученному pid (возвращаемое значение spawn() и IO#pid для IO.popen) — это pid вызванной команды, а не оболочки.

Во втором формате (exec("command1", "arg1", ...)) первый элемент рассматривается как имя команды, а остальные передаются как параметры команде без обработки оболочки.

В третьем формате (exec(["command", "argv0"], "arg1", ...)) с начала команды начинается двухелементный массив, первый элемент — это команда, которая должна быть выполнена, а второй аргумент используется в качестве значения argv[0], которое может отображаться в списках процессов.

Для выполнения команды используются одни из exec(2) системных вызовов, поэтому выполняемая команда может унаследовать часть среды исходной программы (включая открытые дескрипторы файлов).

Это поведение изменяется заданными env и options параметрами. Подробнее см. ::spawn.

Если выполнение команды завершается неудачно (обычно Errno::ENOENT, когда она не найдена), возникает исключение SystemCallError.

Этот метод изменяет атрибуты процесса в соответствии с заданными options перед exec(2) системным вызовом. Подробнее см. ::spawn для более подробной информации об указанных options.

Изменённые атрибуты могут сохраняться, когда exec(2) системный вызов завершается неудачно.

Например, жёсткие ограничения ресурсов не восстанавливаются.

Рассмотрите возможность создания дочернего процесса с помощью ::spawn или Kernel#system, если это недопустимо.

exec "echo *"       # echoes list of files in current directory
# never get here

exec "echo", "*"    # echoes an asterisk
# never get here
exit(status=true) Показать исходный код
Kernel::exit(status=true)
Process::exit(status=true)
static VALUE
f_exit(int c, const VALUE *a, VALUE _)
{
    rb_f_exit(c, a);
    UNREACHABLE_RETURN(Qnil);
}

Инициирует завершение скрипта Ruby, вызвав исключение SystemExit. Это исключение может быть перехвачено. Необязательный параметр используется для возвращения кода состояния вызывающей среде. true и FALSE параметра status означают успех и неудачу соответственно. Интерпретация других целочисленных значений зависит от системы.

begin
  exit
  puts "never get here"
rescue SystemExit
  puts "rescued a SystemExit exception"
end
puts "after begin block"

вывод:

rescued a SystemExit exception
after begin block

Непосредственно перед завершением Ruby выполняет все at_exit функции (см. Kernel::at_exit) и выполняет все финализаторы объектов (см. ObjectSpace::define_finalizer).

at_exit { puts "at_exit function" }
ObjectSpace.define_finalizer("string",  proc { puts "in finalizer" })
exit

вывод:

at_exit function
in finalizer
exit!(status=false) Показать исходный код
static VALUE
rb_f_exit_bang(int argc, VALUE *argv, VALUE obj)
{
    int istatus;

    if (rb_check_arity(argc, 0, 1) == 1) {
        istatus = exit_status_code(argv[0]);
    }
    else {
        istatus = EXIT_FAILURE;
    }
    _exit(istatus);

    UNREACHABLE_RETURN(Qnil);
}

Немедленно завершает процесс. Обработчики завершения не выполняются. status возвращается в базовую систему в качестве кода завершения.

Process.exit!(true)
fork [{ block }] → целое или nil Показать исходный код
fork [{ block }] → целое или nil
static VALUE
rb_f_fork(VALUE obj)
{
    rb_pid_t pid;

    pid = rb_call_proc__fork();

    if (pid == 0) {
        if (rb_block_given_p()) {
            int status;
            rb_protect(rb_yield, Qundef, &status);
            ruby_stop(status);
        }
        return Qnil;
    }

    return PIDT2NUM(pid);
}

Создаёт дочерний процесс. Если указан блок, этот блок выполняется в дочернем процессе, и дочерний процесс завершается со статусом ноль. В противном случае вызов fork возвращается дважды: один раз в родительском процессе, возвращая идентификатор процесса дочернего процесса, и один раз в дочернем процессе, возвращая nil. Дочерний процесс может завершить свою работу с помощью Kernel.exit!, чтобы избежать выполнения любых at_exit функций. Родительский процесс должен использовать Process.wait для сбора кодов завершения своих дочерних процессов или использовать Process.detach для регистрации отсутствия интереса к их статусу; в противном случае операционная система может накапливать процессы-зомби.

Поток, вызывающий fork, является единственным потоком в созданном дочернем процессе. fork не копирует другие потоки.

Если fork недоступен, Process.respond_to?(:fork) возвращает false.

Обратите внимание, что fork(2) недоступен на некоторых платформах, таких как Windows и NetBSD 4. Поэтому следует использовать spawn() вместо fork().

getpgid(pid) → целое Показать исходный код
static VALUE
proc_getpgid(VALUE obj, VALUE pid)
{
    rb_pid_t i;

    i = getpgid(NUM2PIDT(pid));
    if (i < 0) rb_sys_fail(0);
    return PIDT2NUM(i);
}

Возвращает идентификатор группы процессов для заданного идентификатора процесса. Недоступно на всех платформах.

Process.getpgid(Process.ppid())   #=> 25527
getpgrp → целое Показать исходный код
static VALUE
proc_getpgrp(VALUE _)
{
    rb_pid_t pgrp;

#if defined(HAVE_GETPGRP) && defined(GETPGRP_VOID)
    pgrp = getpgrp();
    if (pgrp < 0) rb_sys_fail(0);
    return PIDT2NUM(pgrp);
#else /* defined(HAVE_GETPGID) */
    pgrp = getpgid(0);
    if (pgrp < 0) rb_sys_fail(0);
    return PIDT2NUM(pgrp);
#endif
}

Возвращает идентификатор группы процессов для данного процесса. Недоступно на всех платформах.

Process.getpgid(0)   #=> 25527
Process.getpgrp      #=> 25527
getpriority(kind, integer) → целое Показать исходный код
static VALUE
proc_getpriority(VALUE obj, VALUE which, VALUE who)
{
    int prio, iwhich, iwho;

    iwhich = NUM2INT(which);
    iwho   = NUM2INT(who);

    errno = 0;
    prio = getpriority(iwhich, iwho);
    if (errno) rb_sys_fail(0);
    return INT2FIX(prio);
}

Получает приоритет планирования для указанного процесса, группы процессов или пользователя. kind указывает тип сущности для поиска: один из Process::PRIO_PGRP, Process::PRIO_USER или Process::PRIO_PROCESS. integer — это идентификатор, указывающий на конкретный процесс, группу процессов или пользователя (идентификатор 0 означает текущий). Более низкие приоритеты предпочтительнее для планирования. Недоступно на всех платформах.

Process.getpriority(Process::PRIO_USER, 0)      #=> 19
Process.getpriority(Process::PRIO_PROCESS, 0)   #=> 19
getrlimit(resource) → [cur_limit, max_limit] Показать исходный код
static VALUE
proc_getrlimit(VALUE obj, VALUE resource)
{
    struct rlimit rlim;

    if (getrlimit(rlimit_resource_type(resource), &rlim) < 0) {
        rb_sys_fail("getrlimit");
    }
    return rb_assoc_new(RLIM2NUM(rlim.rlim_cur), RLIM2NUM(rlim.rlim_max));
}

Получает ограничение ресурсов процесса. cur_limit означает текущее (мягкое) ограничение, а max_limit означает максимальное (жёсткое) ограничение.

resource указывает тип ресурса, который нужно ограничить. Он задаётся в виде символа, такого как :CORE, строки, такой как "CORE" или константы, такой как Process::RLIMIT_CORE. Подробнее см. Process.setrlimit.

cur_limit и max_limit могут быть Process::RLIM_INFINITY, Process::RLIM_SAVED_MAX или Process::RLIM_SAVED_CUR. Подробнее см. Process.setrlimit и руководство по системе getrlimit(2).

getsid() → integer Показать исходный код
getsid(pid) → integer
static VALUE
proc_getsid(int argc, VALUE *argv, VALUE _)
{
    rb_pid_t sid;
    rb_pid_t pid = 0;

    if (rb_check_arity(argc, 0, 1) == 1 && !NIL_P(argv[0]))
        pid = NUM2PIDT(argv[0]);

    sid = getsid(pid);
    if (sid < 0) rb_sys_fail(0);
    return PIDT2NUM(sid);
}

Возвращает идентификатор сессии для указанного идентификатора процесса. Если не указан, возвращает текущий идентификатор сессии процесса. Недоступно на всех платформах.

Process.getsid()                #=> 27422
Process.getsid(0)               #=> 27422
Process.getsid(Process.pid())   #=> 27422
gid → integer Показать исходный код
Process::GID.rid → integer
Process::Sys.getgid → integer
static VALUE
proc_getgid(VALUE obj)
{
    rb_gid_t gid = getgid();
    return GIDT2NUM(gid);
}

Возвращает (действительный) идентификатор группы для этого процесса.

Process.gid   #=> 500
gid= integer → integer Показать исходный код
static VALUE
proc_setgid(VALUE obj, VALUE id)
{
    rb_gid_t gid;

    check_gid_switch();

    gid = OBJ2GID(id);
#if defined(HAVE_SETRESGID)
    if (setresgid(gid, -1, -1) < 0) rb_sys_fail(0);
#elif defined HAVE_SETREGID
    if (setregid(gid, -1) < 0) rb_sys_fail(0);
#elif defined HAVE_SETRGID
    if (setrgid(gid) < 0) rb_sys_fail(0);
#elif defined HAVE_SETGID
    {
        if (getegid() == gid) {
            if (setgid(gid) < 0) rb_sys_fail(0);
        }
        else {
            rb_notimplement();
        }
    }
#endif
    return GIDT2NUM(gid);
}

Устанавливает идентификатор группы для этого процесса.

groups → array Показать исходный код
static VALUE
proc_getgroups(VALUE obj)
{
    VALUE ary, tmp;
    int i, ngroups;
    rb_gid_t *groups;

    ngroups = getgroups(0, NULL);
    if (ngroups == -1)
        rb_sys_fail(0);

    groups = ALLOCV_N(rb_gid_t, tmp, ngroups);

    ngroups = getgroups(ngroups, groups);
    if (ngroups == -1)
        rb_sys_fail(0);

    ary = rb_ary_new();
    for (i = 0; i < ngroups; i++)
        rb_ary_push(ary, GIDT2NUM(groups[i]));

    ALLOCV_END(tmp);

    return ary;
}

Получает Array идентификаторов групп в дополнительном списке доступа к группам для этого процесса.

Process.groups   #=> [27, 6, 10, 11]

Обратите внимание, что этот метод является просто обёрткой для getgroups(2). Это означает, что следующие характеристики результата полностью зависят от вашей системы:

  • результат отсортирован

  • результат включает эффективные GID

  • результат не включает дублирующиеся GID

Вы можете убедиться, что получите отсортированный уникальный список GID идентификаторов групп текущего процесса с помощью этого выражения:

Process.groups.uniq.sort
groups= array → array Показать исходный код
static VALUE
proc_setgroups(VALUE obj, VALUE ary)
{
    int ngroups, i;
    rb_gid_t *groups;
    VALUE tmp;
    PREPARE_GETGRNAM;

    Check_Type(ary, T_ARRAY);

    ngroups = RARRAY_LENINT(ary);
    if (ngroups > maxgroups())
        rb_raise(rb_eArgError, "too many groups, %d max", maxgroups());

    groups = ALLOCV_N(rb_gid_t, tmp, ngroups);

    for (i = 0; i < ngroups; i++) {
        VALUE g = RARRAY_AREF(ary, i);

        groups[i] = OBJ2GID1(g);
    }
    FINISH_GETGRNAM;

    if (setgroups(ngroups, groups) == -1) /* ngroups <= maxgroups */
        rb_sys_fail(0);

    ALLOCV_END(tmp);

    return proc_getgroups(obj);
}

Set дополнительный список доступа к группам на заданный Array идентификаторов групп.

Process.groups   #=> [0, 1, 2, 3, 4, 6, 10, 11, 20, 26, 27]
Process.groups = [27, 6, 10, 11]   #=> [27, 6, 10, 11]
Process.groups   #=> [27, 6, 10, 11]
initgroups(username, gid) → array Показать исходный код
static VALUE
proc_initgroups(VALUE obj, VALUE uname, VALUE base_grp)
{
    if (initgroups(StringValueCStr(uname), OBJ2GID(base_grp)) != 0) {
        rb_sys_fail(0);
    }
    return proc_getgroups(obj);
}

Инициализирует дополнительный список доступа к группам, считывая системную базу данных групп и используя все группы, членами которых является указанный пользователь. Группа с указанным gid также добавляется в список. Возвращает результирующий Array идентификаторов всех групп в дополнительном списке доступа к группам. Недоступно на всех платформах.

Process.groups   #=> [0, 1, 2, 3, 4, 6, 10, 11, 20, 26, 27]
Process.initgroups( "mgranger", 30 )   #=> [30, 6, 10, 11]
Process.groups   #=> [30, 6, 10, 11]
kill(signal, pid, ...) → integer Показать исходный код
static VALUE
proc_rb_f_kill(int c, const VALUE *v, VALUE _)
{
    return rb_f_kill(c, v);
}

Посылает указанный сигнал указанному(ым) идентификатору(ам) процесса(ов), если pid положителен. Если pid равен нулю, signal посылается всем процессам, идентификатор группы которых равен идентификатору группы процесса. Если pid отрицателен, результаты зависят от операционной системы. signal может быть целым числом номера сигнала или именем сигнала POSIX (с префиксом SIG или без него). Если signal отрицателен (или начинается с минуса), уничтожает группы процессов, а не процессы. Не все сигналы доступны на всех платформах. Ключи и значения Signal.list являются известными именами и номерами сигналов соответственно.

pid = fork do
   Signal.trap("HUP") { puts "Ouch!"; exit }
   # ... do some work ...
end
# ...
Process.kill("HUP", pid)
Process.wait

возвращает:

Ouch!

Если signal является целым числом, но неверным для сигнала, будет вызвано Errno::EINVAL или RangeError. В противном случае, если signal не является String или Symbol, и известным именем сигнала, будет вызвано ArgumentError.

Также будет вызвано Errno::ESRCH или RangeError для недопустимого pid, Errno::EPERM при неудаче из-за отсутствия прав. В этих случаях сигналы могли быть отправлены предыдущим процессам.

last_status → Process::Status or nil Показать исходный код
static VALUE
proc_s_last_status(VALUE mod)
{
    return rb_last_status_get();
}

Возвращает состояние последнего выполненного дочернего процесса в текущем потоке.

Process.wait Process.spawn("ruby", "-e", "exit 13")
Process.last_status   #=> #<Process::Status: pid 4825 exit 13>

Если в текущем потоке никогда не выполнялся ни один дочерний процесс, это возвращает nil.

Process.last_status   #=> nil
maxgroups → integer Показать исходный код
static VALUE
proc_getmaxgroups(VALUE obj)
{
    return INT2FIX(maxgroups());
}

Возвращает максимальное количество GID, допустимых в дополнительном списке доступа к группам.

Process.maxgroups   #=> 32
maxgroups= integer → integer Показать исходный код
static VALUE
proc_setmaxgroups(VALUE obj, VALUE val)
{
    int ngroups = FIX2INT(val);
    int ngroups_max = get_sc_ngroups_max();

    if (ngroups <= 0)
        rb_raise(rb_eArgError, "maxgroups %d should be positive", ngroups);

    if (ngroups > RB_MAX_GROUPS)
        ngroups = RB_MAX_GROUPS;

    if (ngroups_max > 0 && ngroups > ngroups_max)
        ngroups = ngroups_max;

    _maxgroups = ngroups;

    return INT2FIX(_maxgroups);
}

Устанавливает максимальное количество GID, допустимых в дополнительном списке доступа к группам.

pid → integer Показать исходный код
static VALUE
proc_get_pid(VALUE _)
{
    return get_pid();
}

Возвращает идентификатор процесса этого процесса. Недоступно на всех платформах.

Process.pid   #=> 27415
ppid → integer Показать исходный код
static VALUE
proc_get_ppid(VALUE _)
{
    return get_ppid();
}

Возвращает идентификатор процесса родителя этого процесса. Возвращает недостоверное значение в Win32/64. Недоступно на всех платформах.

puts "I am #{Process.pid}"
Process.fork { puts "Dad is #{Process.ppid}" }

возвращает:

I am 27417
Dad is 27417
setpgid(pid, integer) → 0 Показать исходный код
static VALUE
proc_setpgid(VALUE obj, VALUE pid, VALUE pgrp)
{
    rb_pid_t ipid, ipgrp;

    ipid = NUM2PIDT(pid);
    ipgrp = NUM2PIDT(pgrp);

    if (setpgid(ipid, ipgrp) < 0) rb_sys_fail(0);
    return INT2FIX(0);
}

Устанавливает идентификатор группы процессов pid (0 указывает на этот процесс) на integer. Недоступно на всех платформах.

setpgrp → 0 Показать исходный код
static VALUE
proc_setpgrp(VALUE _)
{
  /* check for posix setpgid() first; this matches the posix */
  /* getpgrp() above.  It appears that configure will set SETPGRP_VOID */
  /* even though setpgrp(0,0) would be preferred. The posix call avoids */
  /* this confusion. */
#ifdef HAVE_SETPGID
    if (setpgid(0,0) < 0) rb_sys_fail(0);
#elif defined(HAVE_SETPGRP) && defined(SETPGRP_VOID)
    if (setpgrp() < 0) rb_sys_fail(0);
#endif
    return INT2FIX(0);
}

Эквивалентно setpgid(0,0). Недоступно на всех платформах.

setpriority(kind, integer, priority) → 0 Показать исходный код
static VALUE
proc_setpriority(VALUE obj, VALUE which, VALUE who, VALUE prio)
{
    int iwhich, iwho, iprio;

    iwhich = NUM2INT(which);
    iwho   = NUM2INT(who);
    iprio  = NUM2INT(prio);

    if (setpriority(iwhich, iwho, iprio) < 0)
        rb_sys_fail(0);
    return INT2FIX(0);
}

См. Process.getpriority.

Process.setpriority(Process::PRIO_USER, 0, 19)      #=> 0
Process.setpriority(Process::PRIO_PROCESS, 0, 19)   #=> 0
Process.getpriority(Process::PRIO_USER, 0)          #=> 19
Process.getpriority(Process::PRIO_PROCESS, 0)       #=> 19
setproctitle(string) → string Показать исходный код
static VALUE
proc_setproctitle(VALUE process, VALUE title)
{
    return ruby_setproctitle(title);
}

Устанавливает заголовок процесса, который отображается в команде ps(1). Не обязательно эффективно на всех платформах. Исключение не будет вызвано независимо от результата, и NotImplementedError не будет вызвано, даже если платформа не поддерживает эту функцию.

Вызов этого метода не влияет на значение $0.

Process.setproctitle('myapp: worker #%d' % worker_id)

Этот метод впервые появился в Ruby 2.1, чтобы служить средством изменения заголовка процесса без использования глобальных переменных.

setrlimit(resource, cur_limit, max_limit) → nil Показать исходный код
setrlimit(resource, cur_limit) → nil
static VALUE
proc_setrlimit(int argc, VALUE *argv, VALUE obj)
{
    VALUE resource, rlim_cur, rlim_max;
    struct rlimit rlim;

    rb_check_arity(argc, 2, 3);
    resource = argv[0];
    rlim_cur = argv[1];
    if (argc < 3 || NIL_P(rlim_max = argv[2]))
        rlim_max = rlim_cur;

    rlim.rlim_cur = rlimit_resource_value(rlim_cur);
    rlim.rlim_max = rlimit_resource_value(rlim_max);

    if (setrlimit(rlimit_resource_type(resource), &rlim) < 0) {
        rb_sys_fail("setrlimit");
    }
    return Qnil;
}

Устанавливает лимит ресурсов процесса. cur_limit обозначает текущий (мягкий) лимит, а max_limit — максимальный (жёсткий) лимит.

Если max_limit не указан, используется cur_limit.

resource указывает тип ресурса, который нужно ограничить. Он должен быть символом, например :CORE, строкой, например "CORE" или константой, например Process::RLIMIT_CORE. Доступные ресурсы зависят от операционной системы. Ruby может поддерживать следующие ресурсы.

AS

общий объём доступной памяти (байты) (SUSv3, NetBSD, FreeBSD, OpenBSD, но не 4.4BSD-Lite)

CORE

размер файла ядра (байты) (SUSv3)

CPU

время процессорного времени (секунды) (SUSv3)

DATA

размер сегмента данных (байты) (SUSv3)

FSIZE

размер файла (байты) (SUSv3)

MEMLOCK

общий размер для mlock(2) (байты) (4.4BSD, GNU/Linux)

MSGQUEUE

распределение для очередей сообщений POSIX (байты) (GNU/Linux)

NICE

верхний предел значения nice(2) процесса (число) (GNU/Linux)

NOFILE

дескрипторы файлов (число) (SUSv3)

NPROC

количество процессов для пользователя (число) (4.4BSD, GNU/Linux)

RSS

размер резидентной памяти (байты) (4.2BSD, GNU/Linux)

RTPRIO

верхний предел приоритета реального времени процесса (число) (GNU/Linux)

RTTIME

процессорное время для процесса реального времени (мкс) (GNU/Linux)

SBSIZE

все буферы сокетов (байты) (NetBSD, FreeBSD)

SIGPENDING

разрешенное количество ожидающих сигналов (сигналы) (GNU/Linux)

STACK

размер стека (байты) (SUSv3)

cur_limit и max_limit могут быть :INFINITY, "INFINITY" или Process::RLIM_INFINITY, что означает, что ресурс не ограничен. Они также могут быть Process::RLIM_SAVED_MAX, Process::RLIM_SAVED_CUR и соответствующими символами и строками. Подробнее см. системную справку setrlimit(2).

Следующий пример повышает мягкий лимит размера файла ядра до жёсткого лимита, чтобы попробовать сделать возможным дамп файла ядра.

Process.setrlimit(:CORE, Process.getrlimit(:CORE)[1])
setsid → integer Показать исходный код
static VALUE
proc_setsid(VALUE _)
{
    rb_pid_t pid;

    pid = setsid();
    if (pid < 0) rb_sys_fail(0);
    return PIDT2NUM(pid);
}

Делает этот процесс лидером новой сессии и группы процессов без контролирующего терминала. Возвращает идентификатор сессии. Не доступно на всех платформах.

Process.setsid   #=> 27422
spawn([env,] command... [,options]) → pid Показать исходный код
spawn([env,] command... [,options]) → pid
static VALUE
rb_f_spawn(int argc, VALUE *argv, VALUE _)
{
    rb_pid_t pid;
    char errmsg[CHILD_ERRMSG_BUFLEN] = { '\0' };
    VALUE execarg_obj, fail_str;
    struct rb_execarg *eargp;

    execarg_obj = rb_execarg_new(argc, argv, TRUE, FALSE);
    eargp = rb_execarg_get(execarg_obj);
    fail_str = eargp->use_shell ? eargp->invoke.sh.shell_script : eargp->invoke.cmd.command_name;

    pid = rb_execarg_spawn(execarg_obj, errmsg, sizeof(errmsg));

    if (pid == -1) {
        int err = errno;
        rb_exec_fail(eargp, err, errmsg);
        RB_GC_GUARD(execarg_obj);
        rb_syserr_fail_str(err, fail_str);
    }
#if defined(HAVE_WORKING_FORK) || defined(HAVE_SPAWNV)
    return PIDT2NUM(pid);
#else
    return Qnil;
#endif
}

spawn выполняет указанную команду и возвращает её идентификатор процесса.

pid = spawn("tar xf ruby-2.0.0-p195.tar.bz2")
Process.wait pid

pid = spawn(RbConfig.ruby, "-eputs'Hello, world!'")
Process.wait pid

Этот метод похож на Kernel#system, но не ожидает завершения команды.

Родительский процесс должен использовать Process.wait для получения статуса завершения своего дочернего процесса или использовать Process.detach для регистрации отсутствия интереса к их статусу; в противном случае операционная система может накапливать процессы-зомби.

spawn имеет множество опций для указания атрибутов процесса:

env: hash
  name => val : set the environment variable
  name => nil : unset the environment variable

  the keys and the values except for +nil+ must be strings.
command...:
  commandline                 : command line string which is passed to the standard shell
  cmdname, arg1, ...          : command name and one or more arguments (This form does not use the shell. See below for caveats.)
  [cmdname, argv0], arg1, ... : command name, argv[0] and zero or more arguments (no shell)
options: hash
  clearing environment variables:
    :unsetenv_others => true   : clear environment variables except specified by env
    :unsetenv_others => false  : don't clear (default)
  process group:
    :pgroup => true or 0 : make a new process group
    :pgroup => pgid      : join the specified process group
    :pgroup => nil       : don't change the process group (default)
  create new process group: Windows only
    :new_pgroup => true  : the new process is the root process of a new process group
    :new_pgroup => false : don't create a new process group (default)
  resource limit: resourcename is core, cpu, data, etc.  See Process.setrlimit.
    :rlimit_resourcename => limit
    :rlimit_resourcename => [cur_limit, max_limit]
  umask:
    :umask => int
  redirection:
    key:
      FD              : single file descriptor in child process
      [FD, FD, ...]   : multiple file descriptor in child process
    value:
      FD                        : redirect to the file descriptor in parent process
      string                    : redirect to file with open(string, "r" or "w")
      [string]                  : redirect to file with open(string, File::RDONLY)
      [string, open_mode]       : redirect to file with open(string, open_mode, 0644)
      [string, open_mode, perm] : redirect to file with open(string, open_mode, perm)
      [:child, FD]              : redirect to the redirected file descriptor
      :close                    : close the file descriptor in child process
    FD is one of follows
      :in     : the file descriptor 0 which is the standard input
      :out    : the file descriptor 1 which is the standard output
      :err    : the file descriptor 2 which is the standard error
      integer : the file descriptor of specified the integer
      io      : the file descriptor specified as io.fileno
  file descriptor inheritance: close non-redirected non-standard fds (3, 4, 5, ...) or not
    :close_others => false  : inherit
  current directory:
    :chdir => str

Форма cmdname, arg1, ... не использует оболочку. Однако на разных ОС разные вещи предоставляются как встроенные команды. Примером этого является +‘echo’+, которая является встроенной на Windows, но является обычной программой на Linux и Mac OS X. Это означает, что Process.spawn 'echo', '%Path%' будет отображать содержимое переменной среды %Path% на Windows, но Process.spawn 'echo', '$PATH' выведет литеральную строку $PATH.

Если в качестве env передаётся хеш, среда обновляется env перед exec(2) в дочернем процессе. Если пара в env имеет nil в качестве значения, переменная удаляется.

# set FOO as BAR and unset BAZ.
pid = spawn({"FOO"=>"BAR", "BAZ"=>nil}, command)

Если в качестве options передаётся хеш, он задаёт группу процессов, создание новой группы процессов, ограничения ресурсов, текущий каталог, umask и перенаправления для дочернего процесса. Также может быть указано очищение переменных среды.

Ключ :unsetenv_others в options указывает на очистку переменных среды, кроме тех, которые указаны env.

pid = spawn(command, :unsetenv_others=>true) # no environment variable
pid = spawn({"FOO"=>"BAR"}, command, :unsetenv_others=>true) # FOO only

Ключ :pgroup в options задаёт группу процессов. Соответствующее значение должно быть true, ноль, положительным целым числом или nil. true и ноль заставляют процесс стать лидером группы процессов. Неноль положительное целое число заставляет процесс присоединиться к заданной группе процессов. Значение по умолчанию, nil, заставляет процесс остаться в той же группе процессов.

pid = spawn(command, :pgroup=>true) # process leader
pid = spawn(command, :pgroup=>10) # belongs to the process group 10

Ключ :new_pgroup в options указывает на передачу CREATE_NEW_PROCESS_GROUP флага в CreateProcessW(), что является API Windows. Этот параметр предназначен только для Windows. true означает, что новый процесс является корневым процессом новой группы процессов. Новый процесс имеет отключенный CTRL+C. Этот флаг необходим для Process.kill(:SIGINT, pid) в дочернем процессе. По умолчанию :new_pgroup равен false.

pid = spawn(command, :new_pgroup=>true)  # new process group
pid = spawn(command, :new_pgroup=>false) # same process group

Ключ :rlimit_foo задаёт ограничение ресурсов. foo должен быть одним из типов ресурсов, например core. Соответствующее значение должно быть целым числом или массивом, содержащим одно или два целых числа: такие же, как аргументы cur_limit и max_limit для Process.setrlimit.

cur, max = Process.getrlimit(:CORE)
pid = spawn(command, :rlimit_core=>[0,max]) # disable core temporary.
pid = spawn(command, :rlimit_core=>max) # enable core dump
pid = spawn(command, :rlimit_core=>0) # never dump core.

Ключ :umask в options задаёт umask.

pid = spawn(command, :umask=>077)

Ключи :in, :out, :err, целое число, IO и массив задают перенаправление. Перенаправление сопоставляет дескриптор файла в дочернем процессе.

Например, stderr можно объединить со stdout следующим образом:

pid = spawn(command, :err=>:out)
pid = spawn(command, 2=>1)
pid = spawn(command, STDERR=>:out)
pid = spawn(command, STDERR=>STDOUT)

Ключи хеша задают дескриптор файла в дочернем процессе, запущенном с помощью spawn. :err, 2 и STDERR задают поток стандартной ошибки (stderr).

Значения хеша задают дескриптор файла в родительском процессе, который вызывает spawn. :out, 1 и STDOUT задают поток стандартного вывода (stdout).

В приведённом примере стандартный вывод в дочернем процессе не указан. Поэтому он наследуется от родительского процесса.

Поток стандартного ввода (stdin) можно указать с помощью :in, 0 и STDIN.

Можно указать имя файла в качестве значения хеша.

pid = spawn(command, :in=>"/dev/null") # read mode
pid = spawn(command, :out=>"/dev/null") # write mode
pid = spawn(command, :err=>"log") # write mode
pid = spawn(command, [:out, :err]=>"/dev/null") # write mode
pid = spawn(command, 3=>"/dev/null") # read mode

Для stdout и stderr (и их комбинации) он открывается в режиме записи. В противном случае используется режим чтения.

Для явного указания флагов и разрешений при создании файла используется массив.

pid = spawn(command, :in=>["file"]) # read mode is assumed
pid = spawn(command, :in=>["file", "r"])
pid = spawn(command, :out=>["log", "w"]) # 0644 assumed
pid = spawn(command, :out=>["log", "w", 0600])
pid = spawn(command, :out=>["log", File::WRONLY|File::EXCL|File::CREAT, 0600])

Массив задаёт имя файла, флаги и разрешения. Флаги могут быть строкой или целым числом. Если флаги опущены или равны nil, предполагается File::RDONLY. Разрешения должны быть целым числом. Если разрешения опущены или равны nil, предполагается 0644.

Если в качестве ключа хеша указан массив IOs и целых чисел, все элементы перенаправляются.

# stdout and stderr is redirected to log file.
# The file "log" is opened just once.
pid = spawn(command, [:out, :err]=>["log", "w"])

Другой способ объединить несколько дескрипторов — [:child, fd]. [:child, fd] обозначает дескриптор файла в дочернем процессе. Это отличается от fd. Например, :err=>:out означает перенаправление child stderr в родительский stdout. Но :err=>[:child, :out] означает перенаправление child stderr в child stdout. Они различаются, если stdout перенаправляется в дочернем процессе следующим образом.

# stdout and stderr is redirected to log file.
# The file "log" is opened just once.
pid = spawn(command, :out=>["log", "w"], :err=>[:child, :out])

[:child, :out] можно использовать для объединения stderr и stdout в IO.popen. В этом случае, IO.popen перенаправляет stdout в канал в дочернем процессе, а [:child, :out] ссылается на перенаправленный stdout.

io = IO.popen(["sh", "-c", "echo out; echo err >&2", :err=>[:child, :out]])
p io.read #=> "out\nerr\n"

Ключ :chdir в options задаёт текущий каталог.

pid = spawn(command, :chdir=>"/var/tmp")

spawn по умолчанию закрывает все нестандартные неуказанные дескрипторы. «Стандартные» дескрипторы — 0, 1 и 2. Это поведение задаётся параметром :close_others. :close_others не влияет на стандартные дескрипторы, которые закрываются только если :close указан явно.

pid = spawn(command, :close_others=>true)  # close 3,4,5,... (default)
pid = spawn(command, :close_others=>false) # don't close 3,4,5,...

:close_others по умолчанию равен false для spawn и IO.popen.

Обратите внимание, что fds, для которых уже установлен флаг close-on-exec, закрываются независимо от параметра :close_others.

Поэтому IO.pipe и spawn можно использовать как IO.popen.

# similar to r = IO.popen(command)
r, w = IO.pipe
pid = spawn(command, :out=>w)   # r, w is closed in the child process.
w.close

:close задаётся в качестве значения хеша для закрытия fd по отдельности.

f = open(foo)
system(command, f=>:close)        # don't inherit f.

Если требуется унаследовать дескриптор файла, можно использовать io=>io.

# valgrind has --log-fd option for log destination.
# log_w=>log_w indicates log_w.fileno inherits to child process.
log_r, log_w = IO.pipe
pid = spawn("valgrind", "--log-fd=#{log_w.fileno}", "echo", "a", log_w=>log_w)
log_w.close
p log_r.read

Также возможно обмен дескрипторами файлов.

pid = spawn(command, :out=>:err, :err=>:out)

Ключи хеша задают дескрипторы файлов в дочернем процессе. Значения хеша задают дескрипторы файлов в родительском процессе. Таким образом, вышеуказанное указывает на обмен stdout и stderr. Внутренне, spawn использует дополнительный дескриптор для разрешения такого циклического сопоставления дескрипторов файлов.

См. Kernel.exec для стандартной оболочки.

times → aProcessTms Показать исходный код
VALUE
rb_proc_times(VALUE obj)
{
    VALUE utime, stime, cutime, cstime, ret;
#if defined(RUSAGE_SELF) && defined(RUSAGE_CHILDREN)
    struct rusage usage_s, usage_c;

    if (getrusage(RUSAGE_SELF, &usage_s) != 0 || getrusage(RUSAGE_CHILDREN, &usage_c) != 0)
        rb_sys_fail("getrusage");
    utime = DBL2NUM((double)usage_s.ru_utime.tv_sec + (double)usage_s.ru_utime.tv_usec/1e6);
    stime = DBL2NUM((double)usage_s.ru_stime.tv_sec + (double)usage_s.ru_stime.tv_usec/1e6);
    cutime = DBL2NUM((double)usage_c.ru_utime.tv_sec + (double)usage_c.ru_utime.tv_usec/1e6);
    cstime = DBL2NUM((double)usage_c.ru_stime.tv_sec + (double)usage_c.ru_stime.tv_usec/1e6);
#else
    const double hertz = (double)get_clk_tck();
    struct tms buf;

    times(&buf);
    utime = DBL2NUM(buf.tms_utime / hertz);
    stime = DBL2NUM(buf.tms_stime / hertz);
    cutime = DBL2NUM(buf.tms_cutime / hertz);
    cstime = DBL2NUM(buf.tms_cstime / hertz);
#endif
    ret = rb_struct_new(rb_cProcessTms, utime, stime, cutime, cstime);
    RB_GC_GUARD(utime);
    RB_GC_GUARD(stime);
    RB_GC_GUARD(cutime);
    RB_GC_GUARD(cstime);
    return ret;
}

Возвращает структуру Tms (см. Process::Tms), содержащую время процессорного времени пользователя и системы для данного процесса, а также для дочерних процессов.

t = Process.times
[ t.utime, t.stime, t.cutime, t.cstime ]   #=> [0.0, 0.02, 0.00, 0.00]
uid → целое Показать исходный код
Process::UID.rid → целое
Process::Sys.getuid → целое
static VALUE
proc_getuid(VALUE obj)
{
    rb_uid_t uid = getuid();
    return UIDT2NUM(uid);
}

Возвращает (действительный) идентификатор пользователя этого процесса.

Process.uid   #=> 501
uid= пользователь → числовое Показать исходный код
static VALUE
proc_setuid(VALUE obj, VALUE id)
{
    rb_uid_t uid;

    check_uid_switch();

    uid = OBJ2UID(id);
#if defined(HAVE_SETRESUID)
    if (setresuid(uid, -1, -1) < 0) rb_sys_fail(0);
#elif defined HAVE_SETREUID
    if (setreuid(uid, -1) < 0) rb_sys_fail(0);
#elif defined HAVE_SETRUID
    if (setruid(uid) < 0) rb_sys_fail(0);
#elif defined HAVE_SETUID
    {
        if (geteuid() == uid) {
            if (setuid(uid) < 0) rb_sys_fail(0);
        }
        else {
            rb_notimplement();
        }
    }
#endif
    return id;
}

Устанавливает (пользовательский) идентификатор пользователя для этого процесса. Недоступно на всех платформах.

wait() → целое Показать исходный код
wait(pid=-1, flags=0) → целое
waitpid(pid=-1, flags=0) → целое
static VALUE
proc_m_wait(int c, VALUE *v, VALUE _)
{
    return proc_wait(c, v);
}

Ожидает завершения дочернего процесса, возвращает его идентификатор процесса и устанавливает $? в объект Process::Status, содержащий информацию об этом процессе. Какой дочерний процесс ожидать зависит от значения pid:

> 0

Ожидает дочерний процесс с идентификатором процесса, равным pid.

0

Ожидает любой дочерний процесс, группа процессов которого совпадает с группой процессов вызывающего процесса.

-1

Ожидает любой дочерний процесс (по умолчанию, если pid не указан).

< -1

Ожидает любой дочерний процесс, группа процессов которого совпадает с абсолютным значением pid.

Аргумент flags может быть логическим или оператором «или» из значений флагов Process::WNOHANG (не блокировать, если дочерних процессов нет) или Process::WUNTRACED (возвращать остановленные дочерние процессы, которые ещё не были сообщены). Не все флаги доступны на всех платформах, но значение нуля будет работать на всех платформах.

Вызов этого метода вызывает исключение SystemCallError, если дочерние процессы отсутствуют. Недоступно на всех платформах.

include Process
fork { exit 99 }                 #=> 27429
wait                             #=> 27429
$?.exitstatus                    #=> 99

pid = fork { sleep 3 }           #=> 27440
Time.now                         #=> 2008-03-08 19:56:16 +0900
waitpid(pid, Process::WNOHANG)   #=> nil
Time.now                         #=> 2008-03-08 19:56:16 +0900
waitpid(pid, 0)                  #=> 27440
Time.now                         #=> 2008-03-08 19:56:19 +0900
wait2(pid=-1, flags=0) → [pid, status] Показать исходный код
waitpid2(pid=-1, flags=0) → [pid, status]
static VALUE
proc_wait2(int argc, VALUE *argv, VALUE _)
{
    VALUE pid = proc_wait(argc, argv);
    if (NIL_P(pid)) return Qnil;
    return rb_assoc_new(pid, rb_last_status_get());
}

Ожидает завершения дочернего процесса (см. Process::waitpid для точного семантического соответствия) и возвращает массив, содержащий идентификатор процесса и код завершения (объект Process::Status) этого дочернего процесса. Вызывает исключение SystemCallError, если дочерние процессы отсутствуют.

Process.fork { exit 99 }   #=> 27437
pid, status = Process.wait2
pid                        #=> 27437
status.exitstatus          #=> 99
waitall → [ [pid1,status1], ...] Показать исходный код
static VALUE
proc_waitall(VALUE _)
{
    VALUE result;
    rb_pid_t pid;
    int status;

    result = rb_ary_new();
    rb_last_status_clear();

    for (pid = -1;;) {
        pid = rb_waitpid(-1, &status, 0);
        if (pid == -1) {
            int e = errno;
            if (e == ECHILD)
                break;
            rb_syserr_fail(e, 0);
        }
        rb_ary_push(result, rb_assoc_new(PIDT2NUM(pid), rb_last_status_get()));
    }
    return result;
}

Ожидает всех дочерних процессов, возвращая массив пар pid/status (где status — объект Process::Status).

fork { sleep 0.2; exit 2 }   #=> 27432
fork { sleep 0.1; exit 1 }   #=> 27433
fork {            exit 0 }   #=> 27434
p Process.waitall

возвращает:

[[30982, #<Process::Status: pid 30982 exit 0>],
 [30979, #<Process::Status: pid 30979 exit 1>],
 [30976, #<Process::Status: pid 30976 exit 2>]]
wait() → целое Показать исходный код
wait(pid=-1, flags=0) → целое
waitpid(pid=-1, flags=0) → целое
static VALUE
proc_m_wait(int c, VALUE *v, VALUE _)
{
    return proc_wait(c, v);
}

Ожидает завершения дочернего процесса, возвращает его идентификатор процесса и устанавливает $? в объект Process::Status, содержащий информацию об этом процессе. Какой дочерний процесс ожидать зависит от значения pid:

> 0

Ожидает дочерний процесс с идентификатором процесса, равным pid.

0

Ожидает любой дочерний процесс, группа процессов которого совпадает с группой процессов вызывающего процесса.

-1

Ожидает любой дочерний процесс (по умолчанию, если pid не указан).

< -1

Ожидает любой дочерний процесс, группа процессов которого совпадает с абсолютным значением pid.

Аргумент flags может быть логическим или оператором «или» из значений флагов Process::WNOHANG (не блокировать, если дочерних процессов нет) или Process::WUNTRACED (возвращать остановленные дочерние процессы, которые ещё не были сообщены). Не все флаги доступны на всех платформах, но значение нуля будет работать на всех платформах.

Вызов этого метода вызывает исключение $?, если дочерние процессы отсутствуют. Недоступно на всех платформах.

include Process
fork { exit 99 }                 #=> 27429
wait                             #=> 27429
$?.exitstatus                    #=> 99

pid = fork { sleep 3 }           #=> 27440
Time.now                         #=> 2008-03-08 19:56:16 +0900
waitpid(pid, Process::WNOHANG)   #=> nil
Time.now                         #=> 2008-03-08 19:56:16 +0900
waitpid(pid, 0)                  #=> 27440
Time.now                         #=> 2008-03-08 19:56:19 +0900
wait2(pid=-1, flags=0) → [pid, status] Показать исходный код
waitpid2(pid=-1, flags=0) → [pid, status]
static VALUE
proc_wait2(int argc, VALUE *argv, VALUE _)
{
    VALUE pid = proc_wait(argc, argv);
    if (NIL_P(pid)) return Qnil;
    return rb_assoc_new(pid, rb_last_status_get());
}

Ожидает завершения дочернего процесса (см. Process::waitpid для точного семантического соответствия) и возвращает массив, содержащий идентификатор процесса и код завершения (объект Process::Status) этого дочернего процесса. Вызывает исключение SystemCallError, если дочерние процессы отсутствуют.

Process.fork { exit 99 }   #=> 27437
pid, status = Process.wait2
pid                        #=> 27437
status.exitstatus          #=> 99

Ruby Core © 1993–2022 Yukihiro Matsumoto
Licensed under the Ruby License.
Ruby Standard Library © contributors
Licensed under their own licenses.

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API