Process 모듈

Process 모듈

Process 모듈은 기본 운영체제의 프로세스를 나타내요. 이 모듈의 메서드들은 현재 프로세스와 그 자식 프로세스의 관리를 지원해요.

출처: Ruby 3.3 API

본문

프로세스 생성 (Process Creation)

아래 각 메서드는 새 프로세스나 하위 셸에서 주어진 명령을 실행하거나, 여러 명령을 새 프로세스/하위 셸에서 실행해요. 프로세스로 할지 하위 셸로 할지는 명령의 형태에 따라 달라져요 (Argument command_line or exe_path 참조).

  • Process.spawn, Kernel#spawn: 명령을 실행하고, 완료를 기다리지 않고 새 pid를 반환해요.
  • Process.exec: 명령을 실행해 현재 프로세스를 대체해요.

추가로:

  • Kernel#system은 주어진 명령줄(문자열)을 하위 셸에서 실행하고 true, false, 또는 nil을 반환해요.
  • Kernel#\``는 주어진 명령줄(문자열)을 하위 셸에서 실행하고 그 $stdout` 문자열을 반환해요.
  • Open3 모듈은 $stdin, $stdout, $stderr 스트림에 접근하면서 자식 프로세스를 만드는 것을 지원해요.

실행 환경 (Execution Environment)

선택적 앞 인자 env는 이름/값 쌍의 hash예요. 각 이름은 문자열, 각 값은 문자열 또는 nil이에요. 각 쌍은 새 프로세스의 ENV에 추가돼요.

Process.spawn(                'ruby -e "p ENV[\"Foo\"]"')
Process.spawn({'Foo' => '0'}, 'ruby -e "p ENV[\"Foo\"]"')

출력:

"0"

이 효과는 보통 ENV#updateenv로 호출하는 것과 비슷해요. 각 환경 변수가 (값이 nil이 아니면) 생성·갱신되거나 (값이 nil이면) 삭제돼요. 다만 새 프로세스가 실패하면 호출 프로세스에 대한 일부 변경이 남을 수 있어요 (예: 하드 리소스 제한은 복원되지 않아요).

인자 command_line 또는 exe_path

필수 문자열 인자는 다음 중 하나예요.

  • 셸 예약어나 특수 내장으로 시작하거나 메타문자를 하나 이상 포함하면 command_line.
  • 그 외에는 exe_path.

Argument command_line — 셸로 전달되는 명령줄 문자열이에요. 셸 예약어로 시작하거나 특수 내장으로 시작하거나 메타문자를 포함해야 해요:

system('if true; then echo "Foo"; fi')          # => true  # Shell reserved word.
system('echo')                                  # => true  # Built-in.
system('date > /tmp/date.tmp')                  # => true  # Contains meta character.
system('date > /nop/date.tmp')                  # => false
system('date > /nop/date.tmp', exception: true) # Raises RuntimeError.

명령줄은 명령의 인자와 옵션도 포함할 수 있어요:

system('echo "Foo"') # => true

Argument exe_path — 다음 중 하나예요: 호출할 실행 파일의 문자열 경로, 또는 실행 파일 경로와 실행 프로세스 이름으로 쓸 문자열의 2요소 배열.

system('/usr/bin/date') # => true # Path to date on Unix-style system.
system('foo')           # => nil  # Command failed.

실행 옵션 (Execution Options)

선택적 뒤 인자 options는 실행 옵션의 hash예요.

작업 디렉터리 (:chdir)

기본적으로 새 프로세스의 작업 디렉터리는 현재 프로세스와 같아요. :chdir 옵션으로 새 프로세스의 작업 디렉터리를 설정할 수 있어요:

Process.spawn('ruby -e "puts Dir.pwd"', {chdir: '/tmp'})
# 출력: /tmp

현재 프로세스의 작업 디렉터리는 바뀌지 않아요.

파일 재지향 (파일 디스크립터)

새 프로세스의 파일 재지향에 실행 옵션을 사용해요. 옵션의 키는 소스를 가리키는 정수 파일 디스크립터(fd) 또는 fd 배열일 수 있어요. fd의 약어 심볼:

  • :in: 파일 디스크립터 0 (STDIN)
  • :out: 파일 디스크립터 1 (STDOUT)
  • :err: 파일 디스크립터 2 (STDERR)

소스에 주는 값은 다음 중 하나예요:

  • 정수 n: 부모 프로세스의 fd n으로 재지향해요.
  • filepath: open(filepath, mode, 0644)를 통해 파일로 재지향해요. mode는 소스 :in이면 'r', 소스 :out/:err이면 'w'예요.
  • [filepath], [filepath, mode], [filepath, mode, perm]: 각각 해당 mode/perm으로 open을 통해 파일로 재지향해요.
  • [:child, fd]: 재지향된 fd로 재지향해요.
  • :close: 자식 프로세스에서 파일 디스크립터를 닫아요.

환경 변수 (:unsetenv_others)

기본적으로 새 프로세스는 부모의 환경 변수를 상속해요. 값 true인 실행 옵션 키 :unsetenv_others를 쓰면 새 프로세스에서 환경 변수를 비워요.

파일 생성 접근 (:umask)

File.umask의 접근 모드를 보려면 실행 옵션 :umask를 써요:

command = 'ruby -e "puts sprintf(\"0%o\", File.umask)"'
options = {:umask => 0644}
Process.spawn(command, options)
# 출력: 0644

프로세스 그룹 (:pgroup, :new_pgroup)

기본적으로 새 프로세스는 부모와 같은 프로세스 그룹에 속해요. :pgroup 옵션으로 다른 그룹을 지정할 수 있어요:

  • true: 새 프로세스에 새 프로세스 그룹을 만들어요.
  • pgid: id가 pgid인 프로세스 그룹에 새 프로세스를 만들어요.

Windows에서만 :new_pgroup => true를 써서 새 프로세스 그룹을 만들 수 있어요.

리소스 제한

실행 옵션으로 리소스 제한을 설정할 수 있어요. 키는 :rlimit_resource_name 형태의 심볼이에요 (Process.setrlimit의 문자열 리소스 이름을 소문자로). 예를 들어 :rlimit_cpu는 리소스 제한 'CPU'에 해당해요. 값은 현재/최대 제한을 모두 지정하는 정수 하나이거나, 현재와 최대 제한을 지정하는 정수 2요소 배열이에요.

파일 디스크립터 상속

기본적으로 새 프로세스는 부모의 파일 디스크립터를 상속해요. 실행 옵션 :close_others => true를 쓰면 재지향되지 않은 비표준 fd(3 이상)를 닫아 상속을 수정할 수 있어요.

실행 셸 (Execution Shell)

Unix 계열에서는 /bin/sh를 호출해요. 그 외에는 ENV['RUBYSHELL'](정의된 경우) 또는 ENV['COMSPEC']가 셸을 결정해요. COMSPEC 경우를 제외하면, command_line 전체 문자열이 셸 옵션 -c의 인자로 전달돼요. 셸은 명령줄에 보통의 셸 확장을 수행해요:

spawn('echo C*') # => 799139
Process.wait     # => 799139

출력:

CONTRIBUTING.md COPYING COPYING.ja

여기 있는 것들 (What's Here)

현재 프로세스 getter: ::argv0(프로세스 이름을 frozen string으로), ::egid(유효 그룹 ID), ::euid(유효 사용자 ID), ::getpgrp(프로세스 그룹 ID), ::getrlimit(리소스 제한), ::gid(실제 그룹 ID), ::pid(프로세스 ID), ::ppid(부모 프로세스 ID), ::uid(실제 사용자 ID)

현재 프로세스 setter: ::egid=, ::euid=, ::gid=, ::setproctitle(프로세스 타이틀), ::setpgrp(프로세스 그룹 ID를 0으로), ::setrlimit, ::setsid(제어 tty 없는 새 세션/그룹 리더), ::uid=

현재 프로세스 실행: ::abort(즉시 종료), ::daemon(데몬화), ::exec(외부 명령으로 대체), ::exit(SystemExit 발생), ::exit!(즉시 종료), ::warmup(VM에 부트 시퀀스 완료 통지)

자식 프로세스: ::detach, ::fork, ::kill, ::spawn, ::wait/::waitpid, ::wait2/::waitpid2, ::waitall

프로세스 그룹: ::getpgid, ::getpriority, ::getsid, ::groups, ::groups=, ::initgroups, ::last_status, ::maxgroups, ::maxgroups=, ::setpgid, ::setpriority

타이밍: ::clock_getres(시계 해상도), ::clock_gettime(시계 시간), ::times(Process::Tms 리턴)

상수

CLOCK_BOOTTIME

공개 클래스 메서드

_fork → integer

fork를 위한 내부 API예요. 직접 호출하지 마세요. 현재 Kernel#fork, Process.fork, IO.popen("-" 사용 시)을 통해 호출돼요. 평범한 코드가 아니라 애플리케이션 모니터링 라이브러리를 위한 거예요. 이 메서드를 오버라이드해 fork 이벤트 전후에 커스텀 코드를 넣을 수 있어요.

abort

실행을 즉시 종료해요. 사실상 Kernel.exit(false)를 호출하는 것과 같아요. 문자열 인자 msg가 주어지면 종료 전에 STDERR로 써요. 그 외에는 예외가 발생했다면 그 메시지와 backtrace를 출력해요.

argv0 → frozen_string

실행 중인 스크립트의 이름을 반환해요. $0에 새 값을 할당해도 이 값은 바뀌지 않아요. Ruby 2.1에서 전역 변수 없이 스크립트 이름을 얻기 위해 처음 등장했어요.

clock_getres(clock_id, unit = :float_second) → number

POSIX 함수 clock_getres()로 결정된 시계 해상도를 반환해요:

Process.clock_getres(:CLOCK_REALTIME) # => 1.0e-09
Process.clock_getres(:CLOCK_PROCESS_CPUTIME_ID, :float_microsecond) # => 0.001
Process.clock_getres(:CLOCK_PROCESS_CPUTIME_ID, :float_millisecond) # => 1.0e-06
Process.clock_getres(:CLOCK_PROCESS_CPUTIME_ID, :float_second)      # => 1.0e-09
Process.clock_getres(:CLOCK_PROCESS_CPUTIME_ID, :microsecond)       # => 0
Process.clock_getres(:CLOCK_PROCESS_CPUTIME_ID, :millisecond)       # => 0
Process.clock_getres(:CLOCK_PROCESS_CPUTIME_ID, :nanosecond)        # => 1
Process.clock_getres(:CLOCK_PROCESS_CPUTIME_ID, :second)            # => 0

Process.clock_gettime가 지원하는 unit 값들 외에, 이 메서드는 :hertz(초당 클록 틱 정수, :float_second의 역수)도 지원해요:

Process.clock_getres(:TIMES_BASED_CLOCK_PROCESS_CPUTIME_ID, :hertz)        # => 100.0
Process.clock_getres(:TIMES_BASED_CLOCK_PROCESS_CPUTIME_ID, :float_second) # => 0.01

정확도: 일부 플랫폼의 기본 버그 때문에 반환된 해상도가 부정확할 수 있어요.

clock_gettime(clock_id, unit = :float_second) → number

POSIX 함수 clock_gettime()으로 결정된 시계 시간을 반환해요:

Process.clock_gettime(:CLOCK_PROCESS_CPUTIME_ID) # => 198.650379677

clock_id 인자는 시간을 반환할 시계를 지정하며, Process::CLOCK_REALTIME 같은 상수이거나 :CLOCK_REALTIME 같은 심볼 약어일 수 있어요. 지원되는 시계는 OS에 따라 달라요 (지원되지 않는 시계로 호출하면 Errno::EINVAL 발생): :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_TAI, :CLOCK_THREAD_CPUTIME_ID, :CLOCK_UPTIME, :CLOCK_UPTIME_FAST, :CLOCK_UPTIME_PRECISE, :CLOCK_UPTIME_RAW, :CLOCK_UPTIME_RAW_APPROX, :CLOCK_VIRTUAL. 각 시계가 어느 플랫폼/버전에서 지원되는지는 원본 문서의 표를 참고하세요.

지원되지 않는 clock_id에는 에뮬레이션을 써요 (예: :GETTIMEOFDAY_BASED_CLOCK_REALTIME, :TIME_BASED_CLOCK_REALTIME, :MACH_ABSOLUTE_TIME_BASED_CLOCK_MONOTONIC, :TIMES_BASED_CLOCK_MONOTONIC, :GETRUSAGE_BASED_CLOCK_PROCESS_CPUTIME_ID, :TIMES_BASED_CLOCK_PROCESS_CPUTIME_ID, :CLOCK_BASED_CLOCK_PROCESS_CPUTIME_ID).

선택적 unit 인자(기본 :float_second)는 반환 값의 단위를 지정해요: :float_microsecond, :float_millisecond, :float_second, :microsecond, :millisecond, :nanosecond, :second.

Process.clock_gettime(:CLOCK_PROCESS_CPUTIME_ID, :nanosecond) # => 204602286036
Process.clock_gettime(:CLOCK_PROCESS_CPUTIME_ID, :second)     # => 204

clock_gettime()은 나노초 단위 수를 반환하는데, Float(IEEE 754 double)는 :CLOCK_REALTIME의 반환 값을 정확히 표현하기에 부족해요. 정확한 나노초 값이 필요하면 unit으로 :nanosecond를 써요. 반환 값의 원점(시간 0)은 시스템에 따라 달라요. :CLOCK_REALTIME의 원점은 Epoch(1970-01-01 00:00:00 UTC)로 정의돼요.

daemon(nochdir = nil, noclose = nil) → 0

현재 프로세스를 제어 터미널에서 떼어내 백그라운드의 시스템 데몬으로 실행해요. 기본적으로는 작업 디렉터리를 루트로 바꾸고 $stdin/$stdout/$stderr를 null 장치로 재지향해요. nochdirtrue면 작업 디렉터리를 바꾸지 않고, noclosetrue면 재지향하지 않아요.

detach(pid) → thread

자식 프로세스가 좀비(zombie)가 되는 것을 방지해요. Process.detach는 프로세스 pid가 종료될 때 그 상태를 거둬들이는 전용 Ruby thread를 만들어 좀비를 막아요. 부모가 자식 프로세스를 절대 기다리지 않을 때만 필요해요.

pid = Process.spawn('ruby', '-e', 'exit 13') # => 313213
thread = Process.detach(pid)
sleep(1)
# => #<Process::Waiter:0x00007f038f48b838 run>
system("ps -ho pid,state -p #{pid}")        # Finds no zombies.
thread.join.pid                             # => 313262

egid → integer

현재 프로세스의 유효 그룹 ID를 반환해요. 모든 플랫폼에서 사용 가능하지 않아요.

egid = new_egid → new_egid

현재 프로세스의 유효 그룹 ID를 설정해요. 모든 플랫폼에서 사용 가능하지 않아요.

euid → integer

현재 프로세스의 유효 사용자 ID를 반환해요.

Process.euid # => 501

euid = new_euid → new_euid

현재 프로세스의 유효 사용자 ID를 설정해요.

exec([env, ] command_line, options = {})

문자열 command_line을 셸로 전달하거나 exe_path의 실행 파일을 호출해 현재 프로세스를 대체해요. 신뢰할 수 없는 입력으로 호출하면 보안 취약점이 있을 수 있어요. exec 시스템 콜로 새 프로세스가 만들어지고, 호출 프로그램의 환경을 일부 상속할 수 있어요.

exec('if true; then echo "Foo"; fi') # Shell reserved word.
exec('echo')                         # Built-in.
exec('date > date.tmp')              # Contains meta character.
exec('/usr/bin/date')                # exe_path
exec('doesnt_exist') # Raises Errno::ENOENT
exec('echo', 'C*')
exec('echo', 'hello', 'world')

exit(status = true)

SystemExit를 일으켜 Ruby 스크립트의 종료를 시작해요. 이 예외는 잡힐 수 있어요. status로 종료 상태를 OS에 반환해요. 최종 종료 직전에 Ruby는 at-exit 절차(Kernel::at_exit)와 객체 finalizer(ObjectSpace::define_finalizer)를 실행해요.

begin
  exit
  puts 'Never get here.'
rescue SystemExit
  puts 'Rescued a SystemExit exception.'
end
puts 'After begin block.'

exit!(status = false)

프로세스를 즉시 종료해요. exit 핸들러는 호출되지 않아요.

Process.exit!(true)

fork { ... } → integer or nil

자식 프로세스를 만들어요. 블록을 주면 자식 프로세스에서 블록을 실행하고, 블록 종료 시 자식은 상태 0으로 종료해요.

puts "Before the fork: #{Process.pid}"
fork do
  puts "In the child process: #{Process.pid}"
end                # => 382141
puts "After the fork: #{Process.pid}"

블록이 없으면 fork 호출은 두 번 반환해요. 부모 프로세스에서 자식의 pid를, 자식 프로세스에서 nil을 반환해요.

puts fork

좀비 프로세스를 피하려면 부모는 Process.wait(자식 상태 수집)나 Process.detach(상태에 무관심 등록)를 호출해야 해요. fork를 호출한 thread만 만들어진 자식 프로세스에 존재해요 (fork는 다른 thread를 복사하지 않아요). fork는 일부 플랫폼에서만 사용 가능해요:

Process.respond_to?(:fork) # => true # Would be false on some.

사용 불가라면 ::spawn을 쓸 수 있어요.

getpgid(pid) → integer

주어진 프로세스 ID pid의 프로세스 그룹 ID를 반환해요.

Process.getpgid(Process.ppid) # => 25527

getpgrp → integer

현재 프로세스의 프로세스 그룹 ID를 반환해요.

Process.getpgid(0) # => 25527
Process.getpgrp    # => 25527

getpriority(kind, id) → integer

지정한 프로세스, 프로세스 그룹, 또는 사용자의 스케줄링 우선순위를 반환해요. kindProcess::PRIO_PROCESS, Process::PRIO_PGRP, Process::PRIO_USER 중 하나예요. id는 프로세스/그룹/사용자 ID이며 0은 kind에 대한 현재 ID를 의미해요.

Process.getpriority(Process::PRIO_USER, 0)    # => 19
Process.getpriority(Process::PRIO_PROCESS, 0) # => 19

getrlimit(resource) → [cur_limit, max_limit]

주어진 resource의 현재(소프트) 제한과 최대(하드) 제한의 2요소 배열을 반환해요.

Process.getrlimit(:CORE) # => [0, 18446744073709551615]

getsid(pid = nil) → integer

주어진 프로세스 ID pid의 세션 ID를 반환해요. 주지 않으면 현재 프로세스의 세션 ID를 반환해요.

Process.getsid                # => 27422
Process.getsid(0)             # => 27422
Process.getsid(Process.pid()) # => 27422

gid → integer

현재 프로세스의 (실제) 그룹 ID를 반환해요.

Process.gid # => 1000

gid = new_gid → new_gid

현재 프로세스의 그룹 ID를 new_gid로 설정해요.

groups → array

현재 프로세스의 보조 그룹 접근 목록의 그룹 ID 배열을 반환해요.

Process.groups # => [4, 24, 27, 30, 46, 122, 135, 136, 1000]

정렬·유일한 배열을 얻으려면 Process.groups.uniq.sort를 쓰세요.

groups = new_groups → new_groups

보조 그룹 접근 목록을 주어진 그룹 ID 배열로 설정해요.

Process.groups                     # => [0, 1, 2, 3, 4, 6, 10, 11, 20, 26, 27]
Process.groups = [27, 6, 10, 11]   # => [27, 6, 10, 11]

initgroups(username, gid) → array

보조 그룹 접근 목록을 설정해요. 새 목록에는 username이 속한 그룹들의 그룹 ID와 그룹 ID gid가 포함돼요.

Process.initgroups('me', 30)  # => [30, 6, 10, 11]

kill(signal, *ids) → count

ids가 지정한 각 프로세스에 신호를 보내고, 보낸 신호의 수를 반환해요. id가 양수면 해당 프로세스 ID의 프로세스에, 0이면 현재 프로세스 그룹의 모든 프로세스에, 음수면 시스템 의존적인 프로세스 모음에 신호를 보내요. signal은 정수 신호 번호(-29, 0, 29)이거나, 'SIG' 접두어를 붙이거나 뺀 이름 문자열('SIGPOLL', 'POLL', '-SIGPOLL', '-POLL')이거나, 같은 형태의 심볼이에요. signal 앞의 '-'는 그룹에 신호를 보낸다는 뜻이에요. Signal.list로 현재 플랫폼이 지원하는 신호를 확인할 수 있어요. 신호 0은 프로세스 존재 여부 확인에 유용해요.

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

잘못된 정수 signal이면 Errno::EINVAL/RangeError, 잘못된 문자열·심볼이면 ArgumentError, 잘못된 idsErrno::ESRCH/RangeError, 권한이 부족하면 Errno::EPERM이 발생해요.

last_status → Process::Status or nil

현재 thread에서 가장 최근에 종료된 자식 프로세스를 나타내는 Process::Status 객체를 반환하고, 없으면 nil을 반환해요.

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

maxgroups → integer

보조 그룹 접근 목록에 허용된 최대 그룹 ID 수를 반환해요.

Process.maxgroups # => 32

maxgroups = new_max → new_max

보조 그룹 접근 목록에 허용된 최대 그룹 ID 수를 설정해요.

pid → integer

현재 프로세스의 프로세스 ID를 반환해요.

Process.pid # => 15668

ppid → integer

현재 프로세스의 부모 프로세스 ID를 반환해요.

puts "Pid is #{Process.pid}."
fork { puts "Parent pid is #{Process.ppid}." }
# 출력: Pid is 271290. / Parent pid is 271290.

setpgid(pid, pgid) → 0

프로세스 ID pid인 프로세스의 프로세스 그룹 ID를 pgid로 설정해요.

setpgrp → 0

setpgid(0, 0)과 동일해요.

setpriority(kind, integer, priority) → 0

Process.getpriority 참조. 예:

Process.setpriority(Process::PRIO_USER, 0, 19)    # => 0
Process.setpriority(Process::PRIO_PROCESS, 0, 19) # => 0

setproctitle(string) → string

ps(1) 명령에 나타나는 프로세스 타이틀을 설정해요. $0 값에는 영향을 주지 않아요.

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

setrlimit(resource, cur_limit, max_limit = cur_limit) → nil

주어진 resource에 대한 현재 프로세스의 제한을 cur_limit(소프트)과 max_limit(하드)으로 설정해요. resource는 심볼, 문자열, 또는 Process::RLIMIT_로 시작하는 상수(:CORE, 'CORE', Process::RLIMIT_CORE)로 줄 수 있어요. 사용 가능한 리소스는 시스템 의존적이며 다음을 포함할 수 있어요: :AS(총 메모리), :CORE(코어 크기), :CPU(CPU 시간), :DATA(데이터 세그먼트), :FSIZE(파일 크기), :MEMLOCK(mlock 크기), :MSGQUEUE, :NICE, :NOFILE(파일 디스크립터), :NPROC, :NPTS, :RSS(상주 메모리), :RTPRIO, :RTTIME, :SBSIZE, :SIGPENDING, :STACK(스택 크기). cur_limit/max_limit은 정수이거나 :SAVED_MAX, :SAVED_CUR, :INFINITY 심볼(또는 해당 문자열/상수)일 수 있어요.

Process.setrlimit(:CORE, Process.getrlimit(:CORE)[1])  # 코어 덤프 가능하게 하려는 예

setsid → integer

현재 프로세스를 제어 tty가 없는 새 세션·프로세스 그룹 리더로 확립하고, 세션 ID를 반환해요.

Process.setsid # => 27422

spawn([env, ] command_line, options = {}) → pid

새 자식 프로세스를 만들어요. 문자열 command_line을 셸로 전달하거나 exe_path의 실행 파일을 호출해요. 완료를 기다리지 않고 새 프로세스의 pid를 반환해요. 신뢰할 수 없는 입력으로 호출하면 보안 취약점이 있을 수 있어요. 좀비를 피하려면 Process.waitProcess.detach를 호출해야 해요.

spawn('if true; then echo "Foo"; fi') # => 798847 # Shell reserved word.
Process.wait                           # => 798847
spawn('echo')                         # => 798848 # Built-in.
Process.wait                           # => 798848
spawn('echo "Foo"') # => 799031
Process.wait        # => 799031

exe_path 예:

spawn('/usr/bin/date') # Path to date on Unix-style system.
Process.wait
pid = spawn(['sleep', 'Hello!'], '1') # 2-element array.
p `ps -p #{pid} -o command=`
# 출력: "Hello! 1\n"

args가 하나 이상 주어지면 각각 실행 파일에 전달될 인자나 옵션이에요.

spawn('echo', 'C*')             # => 799392
Process.wait                    # => 799392
spawn('echo', 'hello', 'world') # => 799393
Process.wait                    # => 799393

times → process_tms

현재 프로세스와 그 자식 프로세스의 사용자·시스템 CPU 시간을 담은 Process::Tms 구조체를 반환해요.

Process.times
# => #<struct Process::Tms utime=55.122118, stime=35.533068, cutime=0.0, cstime=0.002846>

uid → integer

현재 프로세스의 (실제) 사용자 ID를 반환해요.

Process.uid # => 1000

uid = new_uid → new_uid

현재 프로세스의 사용자 ID를 new_uid로 설정해요.

wait(pid = -1, flags = 0) → integer

적절한 자식 프로세스가 종료되길 기다리고, 그 프로세스 ID를 반환하며, $?에 그 프로세스에 대한 정보를 담은 Process::Status 객체를 설정해요. 기다릴 자식은 pid 값에 따라 달라져요:

  • 양의 정수: 프로세스 ID가 pid인 자식을 기다려요.
  • 0: 그룹 ID가 현재 프로세스와 같은 자식을 기다려요.
  • -1(기본): 아무 자식이나 기다려요.
  • -1보다 작음: 프로세스 그룹 ID가 -pid인 자식을 기다려요.

flagsProcess::WNOHANG(사용 가능한 자식이 없으면 블로킹하지 않음), Process::WUNTRACED(아직 보고되지 않은 중단된 자식도 반환할 수 있음) 중 하나 또는 둘의 논리 OR로 주면 돼요. 적절한 자식이 없으면 Errno::ECHILD가 발생해요. Process.waitpidProcess.wait의 별칭이에요.

pid0 = Process.spawn('ruby', '-e', 'exit 13') # => 230866
pid1 = Process.spawn('ruby', '-e', 'exit 14') # => 230891
Process.wait(pid0)                            # => 230866
$?                                            # => #<Process::Status: pid 230866 exit 13>
Process.wait(pid1)                            # => 230891
Process.wait(pid0)                            # Raises Errno::ECHILD

wait2(pid = -1, flags = 0) → [pid, status]

Process.waitpid와 같지만, 자식 프로세스 pidProcess::Status status를 담은 배열을 반환해요.

pid = Process.spawn('ruby', '-e', 'exit 13') # => 309581
Process.wait2(pid)
# => [309581, #<Process::Status: pid 309581 exit 13>]

Process.waitpid2Process.waitpid의 별칭이에요.

waitall → array

모든 자식을 기다리고, 2요소 배열들의 배열을 반환해요. 각 부분 배열은 거둬들인 자식 프로세스 하나의 정수 pid와 Process::Status status를 담아요.

pid0 = Process.spawn('ruby', '-e', 'exit 13') # => 325470
pid1 = Process.spawn('ruby', '-e', 'exit 14') # => 325495
Process.waitall
# => [[325470, #<Process::Status: pid 325470 exit 13>], [325495, #<Process::Status: pid 325495 exit 14>]]

warmup → true

Ruby 가상 머신에 애플리케이션의 부트 시퀀스가 완료됐다고 알려서, VM이 애플리케이션 최적화를 시작할 수 있게 해요.

더 알아보기

  • 프로세스 생성 시의 실행 환경(env)과 실행 옵션(options), 명령 주입 방지에 대한 자세한 내용은 원본 문서를 참고하세요.
  • CLOCK_* 시계별 지원 플랫폼 목록과 RLIMIT_* 리소스별 지원 플랫폼은 원본 문서의 상세 표를 확인하세요.