Method: Kernel#system

Defined in:
process.c

#system([env, ], options = {}, exception: false) ⇒ true, ... #system([env, ], *args, options = {}, exception: false) ⇒ true, ...

Creates a new child process by doing one of the following in that process:

  • Passing string command_line to the shell.

  • Invoking the executable at exe_path.

This method has potential security vulnerabilities if called with untrusted input; see Command Injection.

Returns:

  • true if the command exits with status zero.

  • false if the exit status is a non-zero integer.

  • nil if the command could not execute.

Raises an exception (instead of returning false or nil) if keyword argument exception is set to true.

Assigns the command’s error status to $?.

The new process is created using the system system call; it may inherit some of its environment from the calling program (possibly including open file descriptors).

Argument env, if given, is a hash that affects ENV for the new process; see Execution Environment.

Argument options is a hash of options for the new process; see Execution Options.

The first required argument is one of the following:

  • command_line if it is a string, and if it begins with a shell reserved word or special built-in, or if it contains one or more meta characters.

  • exe_path otherwise.

Argument command_line

String argument command_line is a command line to be passed to a shell; it must begin with a shell reserved word, begin with a special built-in, or contain meta characters:

system('if true; then echo "Foo"; fi')          # => true  # Shell reserved word.
system('exit')                                  # => 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.

Assigns the command’s error status to $?:

system('exit')                             # => true  # Built-in.
$?                                         # => #<Process::Status: pid 640610 exit 0>
system('date > /nop/date.tmp')             # => false
$?                                         # => #<Process::Status: pid 640742 exit 2>

The command line may also contain arguments and options for the command:

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

Output:

Foo

See Execution Shell for details about the shell.

Raises an exception if the new process could not execute.

Argument exe_path

Argument exe_path is one of the following:

  • The string path to an executable to be called.

  • A 2-element array containing the path to an executable and the string to be used as the name of the executing process.

Example:

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

Output:

Mon Aug 28 11:43:10 AM CDT 2023

Assigns the command’s error status to $?:

system('/usr/bin/date') # => true
$?                      # => #<Process::Status: pid 645605 exit 0>
system('foo')           # => nil
$?                      # => #<Process::Status: pid 645608 exit 127>

Ruby invokes the executable directly. This form does not use the shell; see Arguments args for caveats.

system('doesnt_exist') # => nil

If one or more args is given, each is an argument or option to be passed to the executable:

system('echo', 'C*')             # => true
system('echo', 'hello', 'world') # => true

Output:

C*
hello world

Raises an exception if the new process could not execute.

Overloads:

  • #system([env, ], options = {}, exception: false) ⇒ true, ...

    Returns:

    • (true, false, nil)
  • #system([env, ], *args, options = {}, exception: false) ⇒ true, ...

    Returns:

    • (true, false, nil)


4845
4846
4847
4848
4849
4850
4851
4852
4853
4854
4855
4856
4857
4858
4859
4860
4861
4862
4863
4864
4865
4866
4867
4868
4869
4870
4871
4872
4873
4874
4875
4876
4877
4878
4879
4880
4881
4882
4883
4884
4885
4886
4887
4888
4889
4890
4891
4892
4893
4894
4895
4896
4897
4898
4899
4900
4901
4902
4903
4904
4905
# File 'process.c', line 4845

static VALUE
rb_f_system(int argc, VALUE *argv, VALUE _)
{
    rb_thread_t *th = GET_THREAD();
    VALUE execarg_obj = rb_execarg_new(argc, argv, TRUE, TRUE);
    struct rb_execarg *eargp = rb_execarg_get(execarg_obj);

    struct rb_process_status status = {0};
    eargp->status = &status;

    last_status_clear(th);

    // This function can set the thread's last status.
    // May be different from waitpid_state.pid on exec failure.
    rb_pid_t pid = rb_execarg_spawn(execarg_obj, 0, 0);

    if (pid > 0) {
        VALUE status = rb_process_status_wait(pid, 0);
        struct rb_process_status *data = rb_check_typeddata(status, &rb_process_status_type);
        // Set the last status:
        rb_obj_freeze(status);
        th->last_status = status;

        if (data->status == EXIT_SUCCESS) {
            return Qtrue;
        }

        if (data->error != 0) {
            if (eargp->exception) {
                VALUE command = eargp->invoke.sh.shell_script;
                RB_GC_GUARD(execarg_obj);
                rb_syserr_fail_str(data->error, command);
            }
            else {
                return Qnil;
            }
        }
        else if (eargp->exception) {
            VALUE command = eargp->invoke.sh.shell_script;
            VALUE str = rb_str_new_cstr("Command failed with");
            rb_str_cat_cstr(pst_message_status(str, data->status), ": ");
            rb_str_append(str, command);
            RB_GC_GUARD(execarg_obj);
            rb_exc_raise(rb_exc_new_str(rb_eRuntimeError, str));
        }
        else {
            return Qfalse;
        }

        RB_GC_GUARD(status);
    }

    if (eargp->exception) {
        VALUE command = eargp->invoke.sh.shell_script;
        RB_GC_GUARD(execarg_obj);
        rb_syserr_fail_str(errno, command);
    }
    else {
        return Qnil;
    }
}