Process
module Process
常量
CLOCK_BOOTTIME CLOCK_BOOTTIME_ALARM CLOCK_MONOTONIC CLOCK_MONOTONIC_COARSE CLOCK_MONOTONIC_FAST CLOCK_MONOTONIC_PRECISE CLOCK_MONOTONIC_RAW CLOCK_MONOTONIC_RAW_APPROX CLOCK_PROCESS_CPUTIME_ID CLOCK_PROF CLOCK_REALTIME CLOCK_REALTIME_ALARM CLOCK_REALTIME_COARSE CLOCK_REALTIME_FAST CLOCK_REALTIME_PRECISE CLOCK_SECOND CLOCK_THREAD_CPUTIME_ID CLOCK_UPTIME CLOCK_UPTIME_FAST CLOCK_UPTIME_PRECISE CLOCK_UPTIME_RAW CLOCK_UPTIME_RAW_APPROX CLOCK_VIRTUAL PRIO_PGRP
see ::setpriority
PRIO_PROCESS
see ::setpriority
PRIO_USER
see ::setpriority
RLIMIT_AS
进程的虚拟内存(地址空间)的最大大小(以字节为单位)。
有关详细信息,请参阅系统getrlimit(2)手册。
RLIMIT_CORE
核心文件的最大大小。
有关详细信息,请参阅系统getrlimit(2)手册。
RLIMIT_CPU
以秒为单位的CPU时间限制。
有关详细信息,请参阅系统getrlimit(2)手册。
RLIMIT_DATA
进程数据段的最大大小。
有关详细信息,请参阅系统getrlimit(2)手册。
RLIMIT_FSIZE
该进程可能创建的文件的最大大小。
有关详细信息,请参阅系统getrlimit(2)手册。
RLIMIT_MEMLOCK
可以锁定到RAM的最大内存字节数。
有关详细信息,请参阅系统getrlimit(2)手册。
RLIMIT_MSGQUEUE
指定可为调用进程的实际用户标识分配给POSIX消息队列的字节数限制。
有关详细信息,请参阅系统getrlimit(2)手册。
RLIMIT_NICE
指定可以引发进程的良好值的上限。
有关详细信息,请参阅系统getrlimit(2)手册。
RLIMIT_NOFILE
指定一个大于此进程可以打开的最大文件描述符编号的值。
有关详细信息,请参阅系统getrlimit(2)手册。
RLIMIT_NPROC
可以为调用进程的实际用户标识创建的最大进程数。
有关详细信息,请参阅系统getrlimit(2)手册。
RLIMIT_RSS
指定进程驻留集的限制(以页为单位)。
有关详细信息,请参阅系统getrlimit(2)手册。
RLIMIT_RTPRIO
指定可为此过程设置的实时优先级的上限。
有关详细信息,请参阅系统getrlimit(2)手册。
RLIMIT_RTTIME
指定此进程在实时调度策略下可以使用的CPU时间限制。
有关详细信息,请参阅系统getrlimit(2)手册。
RLIMIT_SBSIZE
套接字缓冲区的最大大小。
RLIMIT_SIGPENDING
指定可能为调用进程的实际用户标识排队的信号数量的限制。
有关详细信息,请参阅系统getrlimit(2)手册。
RLIMIT_STACK
堆栈的最大大小(以字节为单位)。
有关详细信息,请参阅系统getrlimit(2)手册。
RLIM_INFINITY
see ::setrlimit
RLIM_SAVED_CUR
see ::setrlimit
RLIM_SAVED_MAX
see ::setrlimit
WNOHANG
see ::wait
WUNTRACED
see ::wait
公共类方法
abort Show source
Kernel::abort(msg)
abort(msg)
通过调用立即终止执行Kernel.exit(false)
。如果给出msg
,则在终止之前将其写入STDERR。
VALUE
rb_f_abort(int argc, const VALUE *argv)
{
rb_check_arity(argc, 0, 1
if (argc == 0) {
if (!NIL_P(GET_THREAD()->errinfo)) {
ruby_error_print(
}
rb_exit(EXIT_FAILURE
}
else {
VALUE args[2];
args[1] = args[0] = argv[0];
StringValue(args[0]
rb_io_puts(1, args, rb_stderr
args[0] = INT2NUM(EXIT_FAILURE
rb_exc_raise(rb_class_new_instance(2, args, rb_eSystemExit)
}
UNREACHABLE;
}
argv0 → frozen_string Show source
返回正在执行的脚本的名称。将值赋给$ 0不会影响该值。
这个方法首先出现在Ruby 2.1中,作为一个全局变量的免费手段来获取脚本名称。
static VALUE
proc_argv0(VALUE process)
{
return rb_orig_progname;
}
clock_getres(clock_id , unit) → number Show source
返回由POSIX :: clock_getres()函数返回的时间分辨率。
clock_id
指定一种时钟。详情请参阅文件Process.clock_gettime
。
clock_id
可以是一个象征Process.clock_gettime
。但结果可能不准确。例如,+ Process.clock_getres(:GETTIMEOFDAY_BASED_CLOCK_REALTIME)+返回1.0e-06,这意味着1微秒,但实际分辨率可能更粗糙。
如果给定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()函数的每秒时钟滴答的精确值和clock()函数的CLOCKS_PER_SEC的确切值。
+Process.clock_getres(:TIMES_BASED_CLOCK_PROCESS_CPUTIME_ID, :hertz)+ returns the clock ticks per second.
+Process.clock_getres(:CLOCK_BASED_CLOCK_PROCESS_CPUTIME_ID, :hertz)+ returns CLOCKS_PER_SEC.
p Process.clock_getres(Process::CLOCK_MONOTONIC)
#=> 1.0e-09
VALUE
rb_clock_getres(int argc, VALUE *argv)
{
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) {
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_gettime(clock_id , unit) → number Show source
返回由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 to 4, Linux 2.5.63, FreeBSD 3.0, NetBSD 2.0, OpenBSD 2.1, macOS 10.12
CLOCK_MONOTONIC
SUSv3 to 4, Linux 2.5.63, FreeBSD 3.0, NetBSD 2.0, OpenBSD 3.4, macOS 10.12
CLOCK_PROCESS_CPUTIME_ID
SUSv3 to 4, Linux 2.5.63, OpenBSD 5.4, macOS 10.12
CLOCK_THREAD_CPUTIME_ID
SUSv3 to 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
请注意,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
使用由SUS定义的gettimeofday()。(虽然SUSv4已经过时了。)分辨率为1微秒。
:TIME_BASED_CLOCK_REALTIME
使用ISO C定义的时间()。分辨率为1秒。
适用于CLOCK_MONOTONIC
:
:MACH_ABSOLUTE_TIME_BASED_CLOCK_MONOTONIC
使用mach_absolute_time(),在达尔文上可用。分辨率与CPU相关。
:TIMES_BASED_CLOCK_MONOTONIC
使用POSIX定义的times()的结果值。POSIX将其定义为“times()”应该以时钟滴答的形式返回过去的实时,因为过去的任意点(例如,系统启动时间)“。例如,GNU / Linux返回一个基于jiffies的值,它是单调的。但是,4.4BSD使用gettimeofday()并且它不是单调的。(不过FreeBSD使用:: clock_gettime(CLOCK_MONOTONIC))。分辨率是时钟节拍。“getconf CLK_TCK”命令显示每秒的时钟滴答。(每秒钟的时钟周期由旧系统中的HZ宏定义)。如果它是100,clock_t是32位整数类型,则分辨率为10毫秒,并且不能超过497天。
Emulations for CLOCK_PROCESS_CPUTIME_ID
:
:GETRUSAGE_BASED_CLOCK_PROCESS_CPUTIME_ID
使用由SUS定义的getrusage()。getrusage()与RUSAGE_SELF一起使用以获取仅用于调用进程的时间(不包括子进程的时间)。结果是添加了用户时间(ru_utime)和系统时间(ru_stime)。分辨率是1微秒。
:TIMES_BASED_CLOCK_PROCESS_CPUTIME_ID
使用POSIX定义的times()。结果是添加了用户时间(tms_utime)和系统时间(tms_stime)。tms_cutime和tms_cstime被忽略以排除子进程的时间。分辨率是时钟滴答。“getconf CLK_TCK”命令显示每秒的时钟滴答。(每秒钟的时钟周期由旧系统中的HZ宏定义)。如果是100,则分辨率为10毫秒。
:CLOCK_BASED_CLOCK_PROCESS_CPUTIME_ID
使用由ISO C定义的clock()。分辨率为1 / CLOCKS_PER_SEC。CLOCKS_PER_SEC是由time.h定义的C级宏。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_millisecond
毫秒数作为浮点数
:float_microsecond
作为浮点数的微秒数
:second
秒数作为整数
:millisecond
毫秒数作为整数
:microsecond
整数微秒数
:nanosecond
整数纳秒数
底层函数:: clock_gettime()返回几纳秒。Float对象(IEEE 754 double)不足以表示CLOCK_REALTIME的返回值。如果需要精确的纳秒值,请:nanoseconds
用作unit
。
返回值的原点(零)不同。例如,系统启动时间,启动时间,Epoch等。
CLOCK_REALTIME中的原点被定义为Epoch(1970-01-01 00:00:00 UTC)。但有些系统会计算闰秒,其他系统则不会。所以结果可以在不同的系统中被解释为不同。推荐使用Time.now,而不是CLOCK_REALTIME。
VALUE
rb_clock_gettime(int argc, VALUE *argv)
{
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.
*
* gettimeofday is always available on platforms supported by Ruby.
* 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;
}
#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) {
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
}
daemon() → 0 Show source
daemon(nochdir=nil,noclose=nil) → 0
从控制终端分离进程并作为系统守护进程在后台运行。除非参数nochdir为真(即非假),否则它将当前工作目录更改为根(“/”)。除非参数noclose为true,否则daemon()会将标准输入,标准输出和标准错误重定向到/ dev / null。成功返回零,或者提高Errno :: *之一。
static VALUE
proc_daemon(int argc, VALUE *argv)
{
int n, nochdir = FALSE, noclose = FALSE;
switch (rb_check_arity(argc, 0, 2)) {
case 2: noclose = RTEST(argv[1]
case 1: nochdir = RTEST(argv[0]
}
prefork(
n = rb_daemon(nochdir, noclose
if (n < 0) rb_sys_fail("daemon"
return INT2FIX(n
}
detach(pid) → thread Show source
一些操作系统保留终止的子进程的状态,直到父进程收集该状态为止(通常使用某种变体wait()
)。如果父母从未收集到这种状态,则该孩子会留在僵尸
进程中。Process::detach
通过设置一个单独的Ruby线程来防止这种情况,该线程的唯一工作是在进程pid
终止时收获其状态。detach
仅在您不打算明确等待孩子终止时才使用。
等待线程终止时会返回分离进程的退出状态,因此您可以使用它Thread#join
来了解结果。如果指定的pid
不是有效的子进程ID,则线程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}")
(不产生输出)
static VALUE
proc_detach(VALUE obj, VALUE pid)
{
return rb_detach_process(NUM2PIDT(pid)
}
egid → integer Show source
Process::GID.eid → integer
Process::Sys.geteid → integer
返回此进程的有效组ID。不适用于所有平台。
Process.egid #=> 500
static VALUE
proc_getegid(VALUE obj)
{
rb_gid_t egid = getegid(
return GIDT2NUM(egid
}
egid = integer → integer Show source
设置此过程的有效组ID。不适用于所有平台。
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 → integer Show source
Process::UID.eid → integer
Process::Sys.geteuid → integer
Returns the effective user ID for this process.
Process.euid #=> 501
static VALUE
proc_geteuid(VALUE obj)
{
rb_uid_t euid = geteuid(
return UIDT2NUM(euid
}
euid= user Show source
设置此进程的有效用户标识。不适用于所有平台。
static VALUE
proc_seteuid_m(VALUE mod, VALUE euid)
{
check_uid_switch(
proc_seteuid(OBJ2UID(euid)
return euid;
}
exec(env, command... ,options) Show source
通过运行给定的外部命令来
替换当前进程,该命令
可以采用以下形式之一:
exec(commandline)
传递给标准shell的命令行字符串
exec(cmdname, arg1, ...)
命令名称和一个或多个参数(无shell)
exec([cmdname, argv0], arg1, ...)
命令名,argv和零个或多个参数(无shell)
在第一种形式中,字符串被视为一个命令行,在执行之前需要进行shell扩展。
标准外壳总是意味着"/bin/sh"
在类Unix系统上,与Windows NT系列相同,ENV["RUBYSHELL"]
或ENV["COMSPEC"]
类似。
如果来自第一个form(exec("command")
)的字符串遵循以下简单规则:
- 没有元字符
- 没有外壳保留字,也没有特殊的内置
- Ruby不使用shell就直接调用该命令
您可以通过向字符串添加“;”来强制执行shell调用(因为“;”是元字符)。
请注意,此行为可通过获取的pid获得(IO.popen的spawn()和IO#pid的返回值)是调用的命令的pid,而不是shell。
在第二个窗体(exec("command1", "arg1", ...)
)中,第一个被作为命令名,其余的被作为参数传递给没有shell扩展的命令。
在第三种形式(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
VALUE
rb_f_exec(int argc, const VALUE *argv)
{
VALUE execarg_obj, fail_str;
struct rb_execarg *eargp;
#define CHILD_ERRMSG_BUFLEN 80
char errmsg[CHILD_ERRMSG_BUFLEN] = { '\0' };
int err;
execarg_obj = rb_execarg_new(argc, argv, TRUE
eargp = rb_execarg_get(execarg_obj
before_exec( /* stop timer thread before redirects */
rb_execarg_parent_start(execarg_obj
fail_str = eargp->use_shell ? eargp->invoke.sh.shell_script : eargp->invoke.cmd.command_name;
rb_exec_async_signal_safe(eargp, errmsg, sizeof(errmsg)
err = errno;
after_exec( /* restart timer thread */
rb_exec_fail(eargp, err, errmsg
RB_GC_GUARD(execarg_obj
rb_syserr_fail_str(err, fail_str
UNREACHABLE;
}
exit(status=true) Show source
Kernel::exit(status=true)
Process::exit(status=true)
通过引发SystemExit
异常来启动Ruby脚本的终止。这个例外可能被捕获。可选参数用于将状态
码返回到调用环境。true
和FALSE
的状态
分别意味着成功和失败。其他整数值的解释是依赖于系统的。
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
VALUE
rb_f_exit(int argc, const VALUE *argv)
{
int istatus;
if (rb_check_arity(argc, 0, 1) == 1) {
istatus = exit_status_code(argv[0]
}
else {
istatus = EXIT_SUCCESS;
}
rb_exit(istatus
UNREACHABLE;
}
exit!(status=false) Show source
立即退出流程。没有退出处理程序运行。状态
作为退出状态
返回到底层系统。
Process.exit!(true)
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;
}
fork { block } → integer or nil Show source
fork { block } → integer or nil
创建一个子流程。如果指定了一个块,则该块在子进程中运行,并且子进程终止,状态为零。否则,fork
调用会返回两次,一次返回父进程,返回该进程的ID,一次进入子进程,返回nil
。子进程可以退出使用,Kernel.exit!
以避免运行任何at_exit
功能。父母程序应该Process.wait
用来收集其子女的终止状态或用于Process.detach
注册他们的状态不感兴趣; 否则,操作系统可能会累积僵尸进程。
线程调用fork是创建的子进程中唯一的线程。fork不会复制其他线程。
如果fork不可用,则Process.respond_to?(:fork)返回false。
请注意,fork(2)在Windows和NetBSD 4等平台上不可用。因此,您应该使用spawn()而不是fork()。
static VALUE
rb_f_fork(VALUE obj)
{
rb_pid_t pid;
switch (pid = rb_fork_ruby(NULL)) {
case 0:
rb_thread_atfork(
if (rb_block_given_p()) {
int status;
rb_protect(rb_yield, Qundef, &status
ruby_stop(status
}
return Qnil;
case -1:
rb_sys_fail("fork(2)"
return Qnil;
default:
return PIDT2NUM(pid
}
}
getpgid(pid) → integer Show source
返回给定进程ID的进程组ID。不适用于所有平台。
Process.getpgid(Process.ppid()) #=> 25527
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
}
getpgrp → integer Show source
返回此进程的进程组标识。不适用于所有平台。
Process.getpgid(0) #=> 25527
Process.getpgrp #=> 25527
static VALUE
proc_getpgrp(void)
{
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
}
getpriority(kind, integer) → integer Show source
获取指定进程,进程组或用户的调度优先级。一种
表示一种
实体的发现:一Process::PRIO_PGRP
,Process::PRIO_USER
或Process::PRIO_PROCESS
。整数
是指示特定进程,进程组或用户的ID(0表示当前
的ID )。较低的优先级对调度更有利。不适用于所有平台。
Process.getpriority(Process::PRIO_USER, 0) #=> 19
Process.getpriority(Process::PRIO_PROCESS, 0) #=> 19
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
}
getrlimit(resource) → cur_limit, max_limit()
获取进程的资源限制。cur_limit
表示当前(软)限制,max_limit
表示最大(硬)限制。
资源
表示要限制的资源
种类。它被指定为一个符号,比如像:CORE
一个字符串"CORE"
或者一个常数Process::RLIMIT_CORE
。有关详细信息,请参阅:setrlimit。
cur_limit
和max_limit
可能是Process::RLIM_INFINITY
,Process::RLIM_SAVED_MAX
或者Process::RLIM_SAVED_CUR
。有关详细信息,请参阅:setrlimit和系统getrlimit(2)手册。
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)
}
getsid() → integer Show source
getsid(pid) → integer
返回给定进程ID的会话ID。如果没有给出,返回当前进程sid。不适用于所有平台。
Process.getsid() #=> 27422
Process.getsid(0) #=> 27422
Process.getsid(Process.pid()) #=> 27422
static VALUE
proc_getsid(int argc, VALUE *argv)
{
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
}
gid → integer Show source
Process::GID.rid → integer
Process::Sys.getgid → integer
返回此过程的(实际)组ID。
Process.gid #=> 500
static VALUE
proc_getgid(VALUE obj)
{
rb_gid_t gid = getgid(
return GIDT2NUM(gid
}
gid= integer → integer Show source
设置此进程的组标识。
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 Show source
找一个Array
在这个过程中,补充组访问列表组的的GID。
Process.groups #=> [27, 6, 10, 11]
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;
}
groups= array → array Show source
将补充组访问列表设置为给定Array
组ID。
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]
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
}
initgroups(username, gid) → array Show source
通过读取系统组数据库并使用给定用户所属的所有组来初始化补充组访问列表。具有指定gid
的组也被添加到列表中。返回Array
补充组访问列表中所有组的gid
的结果。不适用于所有平台。
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]
static VALUE
proc_initgroups(VALUE obj, VALUE uname, VALUE base_grp)
{
if (initgroups(StringValuePtr(uname), OBJ2GID(base_grp)) != 0) {
rb_sys_fail(0
}
return proc_getgroups(obj
}
kill(signal, pid, ...) → integer Show source
如果pid
为正值,则将给定的信号
发送到指定的进程ID 。如果pid
为零,则将信号
发送到所有进程的组ID等于进程的组ID。信号
可以是整数信号
编号或POSIX信号
名称(有或没有SIG
前缀)。如果信号
为负数(或以负号开始),则杀死进程组而不是进程。并非所有的信号
都可用于所有平台。键和值分别Signal.list
是已知的信号
名称和数字。
pid = fork do
Signal.trap("HUP") { puts "Ouch!"; exit }
# ... do some work ...
end
# ...
Process.kill("HUP", pid)
Process.wait
产生:
Ouch!
如果信号
是一个整数,但信号
错误,Errno::EINVAL
或RangeError
将被提出。否则,除非信号
是a String
或a Symbol
,并且会发出已知的信号
名称ArgumentError
。
另外,Errno::ESRCH
或者RangeError
对于无效的PID
,Errno::EPERM
当因没有特权而失败时,会被提出。在这些情况下,信号可能已经发送到前面的过程。
VALUE
rb_f_kill(int argc, const VALUE *argv)
{
#ifndef HAVE_KILLPG
#define killpg(pg, sig) kill(-(pg), (sig))
#endif
int negative = 0;
int sig;
int i;
VALUE str;
const char *s;
rb_check_arity(argc, 2, UNLIMITED_ARGUMENTS
switch (TYPE(argv[0])) {
case T_FIXNUM:
sig = FIX2INT(argv[0]
break;
case T_SYMBOL:
str = rb_sym2str(argv[0]
goto str_signal;
case T_STRING:
str = argv[0];
str_signal:
s = RSTRING_PTR(str
if (s[0] == '-') {
negative++;
s++;
}
if (strncmp(signame_prefix, s, sizeof(signame_prefix)) == 0)
s += 3;
if ((sig = signm2signo(s)) == 0) {
long ofs = s - RSTRING_PTR(str
if (ofs) str = rb_str_subseq(str, ofs, RSTRING_LEN(str)-ofs
rb_raise(rb_eArgError, "unsupported name `SIG%"PRIsVALUE"'", str
}
if (negative)
sig = -sig;
break;
default:
str = rb_check_string_type(argv[0]
if (!NIL_P(str)) {
goto str_signal;
}
rb_raise(rb_eArgError, "bad signal type %s",
rb_obj_classname(argv[0])
break;
}
if (argc <= 1) return INT2FIX(0
if (sig < 0) {
sig = -sig;
for (i=1; i<argc; i++) {
if (killpg(NUM2PIDT(argv[i]), sig) < 0)
rb_sys_fail(0
}
}
else {
const rb_pid_t self = (GET_THREAD() == GET_VM()->main_thread) ? getpid() : -1;
int wakeup = 0;
for (i=1; i<argc; i++) {
rb_pid_t pid = NUM2PIDT(argv[i]
if ((sig != 0) && (self != -1) && (pid == self)) {
int t;
/*
* When target pid is self, many caller assume signal will be
* delivered immediately and synchronously.
*/
switch (sig) {
case SIGSEGV:
#ifdef SIGBUS
case SIGBUS:
#endif
#ifdef SIGKILL
case SIGKILL:
#endif
#ifdef SIGILL
case SIGILL:
#endif
#ifdef SIGFPE
case SIGFPE:
#endif
#ifdef SIGSTOP
case SIGSTOP:
#endif
ruby_kill(pid, sig
break;
default:
t = signal_ignored(sig
if (t) {
if (t < 0 && kill(pid, sig))
rb_sys_fail(0
break;
}
signal_enque(sig
wakeup = 1;
}
}
else if (kill(pid, sig) < 0) {
rb_sys_fail(0
}
}
if (wakeup) {
rb_threadptr_check_signal(GET_VM()->main_thread
}
}
rb_thread_execute_interrupts(rb_thread_current()
return INT2FIX(i-1
}
maxgroups → integer Show source
返回补充组访问列表中允许的最大gid数。
Process.maxgroups #=> 32
static VALUE
proc_getmaxgroups(VALUE obj)
{
return INT2FIX(maxgroups()
}
maxgroups= integer → integer Show source
设置补充组访问列表中允许的最大gid数。
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 shold 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
}
pid → integer Show source
返回此进程的进程标识。不适用于所有平台。
Process.pid #=> 27415
static VALUE
get_pid(void)
{
return PIDT2NUM(getpid()
}
ppid → integer Show source
返回此进程的父进程的进程ID。在Win32 / 64上返回不值得信赖的值。不适用于所有平台。
puts "I am #{Process.pid}"
Process.fork { puts "Dad is #{Process.ppid}" }
产生:
I am 27417
Dad is 27417
static VALUE
get_ppid(void)
{
return PIDT2NUM(getppid()
}
setpgid(pid, integer) → 0 Show source
将pid
的进程组标识(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
}
setpgrp → 0 Show source
相当于setpgid(0,0)
。不适用于所有平台。
static VALUE
proc_setpgrp(void)
{
/* 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
}
setpriority(kind, integer, priority) → 0 Show source
参阅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
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
}
setproctitle(string) → string Show source
设置ps(1)命令上显示的进程标题。不一定在所有平台上都有效。无论结果如何,都不会引发异常,即使平台不支持该功能也不会引发NotImplementedError。
调用此方法不会影响$ 0的值。
Process.setproctitle('myapp: worker #%d' % worker_id)
这个方法首先出现在Ruby 2.1中,作为一个全局变量的免费方式来改变进程标题。
static VALUE
proc_setproctitle(VALUE process, VALUE title)
{
StringValue(title
setproctitle("%.*s", RSTRING_LENINT(title), RSTRING_PTR(title)
return title;
}
setrlimit(resource, cur_limit, max_limit) → nil Show source
setrlimit(resource, cur_limit) → nil
设置进程的资源限制。cur_limit
表示当前(软)限制,max_limit
表示最大(硬)限制。
如果max_limit
没有给出,cur_limit
使用。
资源
表示要限制的资源
种类。它应该是一个符号,比如像:CORE
一个字符串,"CORE"
或者一个常数Process::RLIMIT_CORE
。可用资源
取决于操作系统。Ruby可能支持以下资源
。
如
总可用内存(字节)(SUSv3,NetBSD,FreeBSD,OpenBSD,但4.4BSD-Lite)
CORE
core size (bytes) (SUSv3)
CPU
CPU time (seconds) (SUSv3)
DATA
data segment (bytes) (SUSv3)
FSIZE
file size (bytes) (SUSv3)
MEMLOCK
total size for mlock(2) (bytes) (4.4BSD, GNU/Linux)
MSGQUEUE
allocation for POSIX message queues (bytes) (GNU/Linux)
NICE
ceiling on process's nice(2) value (number) (GNU/Linux)
NOFILE
文件描述符(编号)(SUSv3)
NPROC
用户进程数(数量)(4.4BSD,GNU / Linux)
RSS
常驻内存大小(字节)(4.2BSD,GNU / Linux)
RTPRIO
进程的实时优先级(数量)上限(GNU / Linux)
RTTIME
实时进程的CPU时间(美国)(GNU / Linux)
SBSIZE
所有套接字缓冲区(字节)(NetBSD,FreeBSD)
SIGPENDING
允许排队的信号数量(信号)(GNU / Linux)
STACK
stack size (bytes) (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])
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;
}
setsid → integer Show source
建立这个过程作为一个新的会话和过程组领导,没有控制tty。返回会话ID。不适用于所有平台。
Process.setsid #=> 27422
static VALUE
proc_setsid(void)
{
rb_pid_t pid;
pid = setsid(
if (pid < 0) rb_sys_fail(0
return PIDT2NUM(pid
}
spawn(env, command... ,options) → pid Show source
spawn(env, command... ,options) → pid
spawn执行指定的命令并返回它的pid。
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#系统类似,但不等待命令完成。
父程序应该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 => true : don't inherit
current directory:
:chdir => str
The 'cmdname, arg1, ...' form does not use the shell. However,
on different OSes, different things are provided as built-in
commands. An example of this is 'echo', which is a built-in
on Windows, but is a normal program on Linux and Mac OS X.
This means that `Process.spawn 'echo', '%Path%'` will display
the contents of the `%Path%` environment variable on Windows,
but `Process.spawn 'echo', '$PATH'` prints the literal '$PATH'.
如果给出散列env
,则在子进程中env
之前更新环境exec(2)
。如果一对中env
的值为零,则该变量将被删除。
# 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使进程保留在同一个进程组中。
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()
那就是Windows API的。该选项仅适用于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
。相应的值应该是一个整数或一个有一个或两个整数的数组:与:: setrlimit的cur_limit和max_limit参数相同。
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])
该数组指定一个文件名,标志和权限。这些标志可以是一个字符串或一个整数。如果省略标志或零,则假定File :: RDONLY。权限应该是一个整数。如果权限被忽略或零,则假定为0644。
如果将IO和整数数组指定为散列键,则所有元素都将被重定向。
# 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意味着将子stderr重定向到父标准输出。但是:err =>:child,:out意味着将子stderr重定向到子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合并到IO.popen中的stdout中。在这种情况下,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,...
:spawn和IO.popen默认为close_others。
请注意,无论close_others选项如何,已关闭执行close-on-exec标志的fds都会关闭。
所以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
标准外壳。
static VALUE
rb_f_spawn(int argc, VALUE *argv)
{
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
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
}
times → aProcessTms Show source
返回一个Tms
结构(请参阅参考资料Process::Tms
),其中包含此进程的用户和系统CPU时间以及子进程。
t = Process.times
[ t.utime, t.stime, t.cutime, t.cstime ] #=> [0.0, 0.02, 0.00, 0.00]
VALUE
rb_proc_times(VALUE obj)
{
const double hertz = get_clk_tck(
struct tms buf;
VALUE utime, stime, cutime, cstime, ret;
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
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;
}
uid → integer Show source
Process::UID.rid → integer
Process::Sys.getuid → integer
返回此进程的(实际)用户标识。
Process.uid #=> 501
static VALUE
proc_getuid(VALUE obj)
{
rb_uid_t uid = getuid(
return UIDT2NUM(uid
}
uid= user → numeric Show source
设置此进程的(用户)用户标识。不适用于所有平台。
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() → integer Show source
wait(pid=-1, flags=0) → integer
waitpid(pid=-1, flags=0) → integer
等待子进程退出,返回其进程ID,并设置$?
为Process::Status
包含该进程信息的对象。它等待的孩子取决于pid
的值:
0
等待进程ID等于pid
的子进程。
0
等待进程组ID等于调用进程的任何子进程。
-1
等待任何子进程(默认情况下,如果没有给出PID
)。
< -1
等待进程组ID等于pid
绝对值的任何子进程。
该标志
参数可以是逻辑或标志
值的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
static VALUE
proc_wait(int argc, VALUE *argv)
{
rb_pid_t pid;
int flags, status;
flags = 0;
if (rb_check_arity(argc, 0, 2) == 0) {
pid = -1;
}
else {
VALUE vflags;
pid = NUM2PIDT(argv[0]
if (argc == 2 && !NIL_P(vflags = argv[1])) {
flags = NUM2UINT(vflags
}
}
if ((pid = rb_waitpid(pid, &status, flags)) < 0)
rb_sys_fail(0
if (pid == 0) {
rb_last_status_clear(
return Qnil;
}
return PIDT2NUM(pid
}
wait2(pid=-1, flags=0) → pid, status()
等待子进程退出(请参阅:: waitpid以了解确切的语义),并返回包含该子进程ID和退出状态(Process::Status
对象)的数组。如果没有子进程,则引发SystemCallError。
Process.fork { exit 99 } #=> 27437
pid, status = Process.wait2
pid #=> 27437
status.exitstatus #=> 99
static VALUE
proc_wait2(int argc, VALUE *argv)
{
VALUE pid = proc_wait(argc, argv
if (NIL_P(pid)) return Qnil;
return rb_assoc_new(pid, rb_last_status_get()
}
waitall → [pid1,status1], ...()
等待所有的孩子,返回一组pid
/ 状态
对(状态
是一个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>]]
static VALUE
proc_waitall(void)
{
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;
}
waitpid(pid=-1, flags=0) → integer Show source
等待子进程退出,返回其进程ID,并设置$?
为Process::Status
包含该进程信息的对象。它等待的孩子取决于pid
的值:
0
等待进程ID等于pid
的子进程。
0
等待进程组ID等于调用进程的任何子进程。
-1
等待任何子进程(默认情况下,如果没有给出PID
)。
< -1
等待进程组ID等于pid
绝对值的任何子进程。
该标志
参数可以是逻辑或标志
值的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
static VALUE
proc_wait(int argc, VALUE *argv)
{
rb_pid_t pid;
int flags, status;
flags = 0;
if (rb_check_arity(argc, 0, 2) == 0) {
pid = -1;
}
else {
VALUE vflags;
pid = NUM2PIDT(argv[0]
if (argc == 2 && !NIL_P(vflags = argv[1])) {
flags = NUM2UINT(vflags
}
}
if ((pid = rb_waitpid(pid, &status, flags)) < 0)
rb_sys_fail(0
if (pid == 0) {
rb_last_status_clear(
return Qnil;
}
return PIDT2NUM(pid
}
waitpid2(pid=-1, flags=0) → pid, status()
等待子进程退出(请参阅:: waitpid以了解确切的语义),并返回包含该子进程ID和退出状态(Process::Status
对象)的数组。如果没有子进程,则引发SystemCallError。
Process.fork { exit 99 } #=> 27437
pid, status = Process.wait2
pid #=> 27437
status.exitstatus #=> 99
static VALUE
proc_wait2(int argc, VALUE *argv)
{
VALUE pid = proc_wait(argc, argv
if (NIL_P(pid)) return Qnil;
return rb_assoc_new(pid, rb_last_status_get()
}