Code360 powered by Coding Ninjas X Naukri.com. Code360 powered by Coding Ninjas X Naukri.com
Table of contents
1.
Introduction
2.
Invoking OS Commands 
3.
Forking and Processes 
4.
Trapping Signals 
5.
Terminating Programs 
6.
Frequently Asked Questions
6.1.
What are ruby variables?  
6.2.
Explain in brief about the ruby module? 
6.3.
What are ruby strings?
6.4.
What Ruby does do when it concatenates strings. How many different ways are there to concatenate a string?   
6.5.
In Ruby, how to make a new time instance?  
7.
Conclusion 
Last Updated: Mar 27, 2024
Easy

Calling the OS

Introduction

For interfacing with the operating system to run programs, fork new processes, handle signals, and other tasks, Ruby includes a number of global functions. Many of these OS-related functions in Ruby were initially designed for Unix-like operating systems. These functions, by their very nature, are less portable than the majority of others, and some of them might not even work at all on Windows and other non-Unix platforms. The OS-dependent functions that are most frequently used are described in the subsections that follow. These do not cover especially low-level or platform-specific functions, like syscalls.

Index

Invoking OS Commands 

The Kernel.` method expects a single string argument representing an OS shell command. It launches a subshell and gives it the given text. The text that was printed to standard output is the return value. Typically, this technique uses specific syntax; it is called on string literals enclosed in backquotes or on string literals separated by the %x.

 

os = `uname` # String literal and method invocation in one
os = %x{uname} # Another quoting syntax
os = Kernel.`("uname") # Invoke the method explicitly
You can also try this code with Online Ruby Compiler
Run Code

 

This technique calls a shell rather than just the supplied executable, so shell capabilities like filename wildcard expansion are available:

files = `echo *.xml`
You can also try this code with Online Ruby Compiler
Run Code

 

With the Kernel.open function, a process can also be started, and its output can be read. The most popular way to open files is with this technique, a variation of File.open. It can also open HTTP and FTP URLs if you need 'open-uri' from the standard library. However, it opens a pipe to read from and/or write to the supplied shell command if the first character of the specified "filename" is the pipe character |.

pipe = open("|echo *.xml")
files = pipe.readline
pipe.close
You can also try this code with Online Ruby Compiler
Run Code

 

  • Use the Kernel.system function if you want to run a command in a shell but aren't interested in the results. When a single string is supplied, the function executes it in the shell, waits for it to finish, and returns true on success or false on failure. The first argument you send to the system when passing multiple arguments is the program name you want to run, and the subsequent arguments are its command-line parameters. In this instance, such arguments are not expanded by the shell.
     
  • You can run any program at a lower level with the exec function. This function never returns; instead, it just substitutes the provided executable for the running Ruby process. This might be helpful if you are building a Ruby script that serves as a simple launcher for another program.

Forking and Processes 

Using several Ruby processes is another strategy for attaining concurrency in Ruby. Use the fork() system call or its counterpart, Process. Fork, to accomplish this. Using a block is the simplest approach to using this function.

 

fork {
 puts "Hello from the child process: #$$"
}
puts "Hello from the parent process: #$$"
You can also try this code with Online Ruby Compiler
Run Code

 

When used this way, the code that follows the block is continued by the initial Ruby process, and the new Ruby process executes the code within the block.

Fork behaves differently when called without a block. An integer that represents the process ID of the newly generated child process is returned by the fork function in the parent process.

The identical call to fork returns nil in the child process. Therefore, the above code may alternatively be expressed as follows:

 

pid = fork
if (pid)
 puts "Hello from parent process: #$$"
 puts "Created child process #{pid}"
else
 puts Hello from child process: #$$"
end
You can also try this code with Online Ruby Compiler
Run Code

 

  • Processes and threads differ greatly in that they do not share memory. When you use the fork command, a new Ruby process is created that is an identical copy of the parent process. However, any modifications it makes to the state of the Process (by modifying or creating objects) take place in its own address space. Both the parent process and the child process are unable to change the data structures that are observed by the other.
  • Use open and pass "|-" as the first argument if you require communication between your parent and child processes. The pipe to the freshly forked Ruby process is now open. The open call yields the corresponding block for both the parent and the child. The block in the child receives nothing. However, the block gets an IO object from the parent.
     
  • Data written by the child is returned when reading from this IO object. Additionally, information written to the IO object is now accessible for reading via the child's standard input.
     

For Example

open("|-", "r+") do |child|
 if child
 # This is the parent process
 child.puts("Hello child") # Send to child
 response = child.gets # Read from child
 puts "Child said: #{response}"
 else
 # This is the child process
 from_parent = gets # Read from parent
 STDERR.puts "Parent said: #{from_parent}"
 puts("Hi Mom!") # Send to parent
 end
end
You can also try this code with Online Ruby Compiler
Run Code

 

Together with the fork or open methods, the Kernel.exec function is helpful. As we previously showed, you can send any command to the operating system shell using the system functions. Both of those techniques, however, are synchronous; they hold off on returning until the command has finished. Use a fork to establish a child process and then call exec in the child to perform the operating system command if you want to run it as a separate process. A call to exec creates a new process in lieu of the existing one and never returns. The arguments for system and exec are identical. It is handled as a shell command if there is just one. Any additional arguments become the "ARGV" for the executable if there are multiple arguments, and the first argument indicates the executable to invoke: 

 

open("|-", "r") do |child|
 if child
 # This is the parent process
 files = child.readlines # Read the output of our child
 child.close
 else
 # This is the child process
 exec("/bin/ls", "-l") # Run another executable
 end
end
You can also try this code with Online Ruby Compiler
Run Code

 

The specifics of dealing with processes, a low-level programming activity, are outside the purview of this book. If you're interested in learning more, start using ri to read about the other Process module methods. 

Trapping Signals 

Asynchronous signals can be transmitted to an active process in most operating systems.

For instance, when a user presses Ctrl-C to cancel a program, this happens.

In response to Ctrl-C, the majority of shell applications transmit a signal called "SIGINT" (for interrupt). Additionally, the program is typically aborted as the default reaction to this signal. Ruby enables programs to define their signal handlers and "trap" signals. The Kernel.trap technique (or its synonym Signal.trap) is used to do this. If you don't want the user to be able to use Ctrl-C to cancel, for instance:

 

trap "SIGINT" {
 puts "Ignoring SIGINT"
}
You can also try this code with Online Ruby Compiler
Run Code

 

  • You can pass a Proc object in place of a block when calling the trap method.
     
  • You can also supply the string "Disregard" as the second argument if all you want to do is silently ignore a signal. To make a signal behave as the OS would like it to, pass "DEFAULT" as the second argument.
     
  • It can be helpful to define signal handlers in long-running applications like servers so that they can, for example, enter debugging mode, reread their configuration files, or dump use data to the log. For similar purposes, SIGUSR1 and SIGUSR2 are frequently used on Unix-like operating systems.

Terminating Programs 

Several connected Kernel methods exist for ending programs or carrying out related tasks. The easiest to understand is the exit function. It causes the program to quit if the SystemExit exception is not handled. 

However, END blocks and any shutdown handlers started using Kernel.at the exit are executed prior to the exit.
 

  • Use exit! to end the sentence instantly. The process exit code communicated to the operating system is specified by an integer input that is accepted by both methods. The terms Process.exit and Process.exit! are interchangeable for these two Kernel functions.
     
  • The exit function is called after the abort function prints the provided error message to the standard output stream (1).
     
  • In situations where the exception raised is anticipated to cause the application to crash, fail is merely a synonym for raise. Similar to abort, failure also results in a message being shown when the application ends. 

    For instance:
fail "Unknown option #{switch}"
You can also try this code with Online Ruby Compiler
Run Code

 

  • The warn function is related to abort and fail: it prints a warning message to standard error (unless warnings have been explicitly disabled with -W0). Note, however, that this function does not raise an exception or cause the program to exit. 
     
  • Sleep is another related function that does not cause the program to exit. Instead, it simply causes the program (or at least the current thread of the program) to pause for the specified number of seconds.

Frequently Asked Questions

What are ruby variables?  

Data that can be used later in a program is stored in ruby variables. The names of each variable, which functions as memory, vary. There are four types of variables in Ruby i.e, local variable, class variable, instance variable, and global variable. 

Explain in brief about the ruby module? 

A Ruby module is a grouping of constants and methods. Module methods or instance methods can both be used in modules. Since they contain a collection of methods, class definitions, constants, and other modules, they are comparable to classes. They are described similarly to classes. Modules can not be used to construct objects or subclasses. There is no hierarchy of inheritance for modules. Modules primarily have two functions i.e. acting as namespace, they and they make it possible for classes to share functionality via the mixin facility.

What are ruby strings?

An arbitrarily ordered series of bytes that often represent characters can be stored and modified in a Ruby string object. They are produced by either using literals or String::new. 

What Ruby does do when it concatenates strings. How many different ways are there to concatenate a string?   

Ruby string concatenation refers to combining several strings into a single string. Concatenating strings allows you to connect multiple strings to create a single string. Ruby strings can be combined in one string using four different methods. They are using a plus sign, a single space, using << symbol, and using concat method. 

In Ruby, how to make a new time instance?  

With::new, a fresh instance of Time can be produced. This will consume time from your present system. Time can also be divided into units like a year, month, day, hour, minute, etc. You must wait at least a year before starting a new time instance. If only a year has passed, the system will set the time to 00:00:00 on January 1 of that year using the current time zone.

Conclusion 

In this article, we discussed the functions that Ruby allows for interfacing with the operating system to run programs, fork new processes, handle signals, and so on. If you want to study more, don’t worry, coding ninjas have got you covered. 

To study the ruby in detail, you can refer to these links: 

Ruby

Documentation

Official Ruby FAQ

Ruby Koans

Refer to our Guided Path on Coding Ninjas Studio to upskill yourself in Data Structures and algorithmsCompetitive ProgrammingJavaScriptSystem DesignMachine learning, and many more! If you want to test your competency in coding, you may check out the mock test series and participate in the contests hosted on Coding Ninjas Studio! But if you have just started your learning process and are looking for questions asked by tech giants like Amazon, Microsoft, Uber, etc., you must look at the problemsinterview experiences, and interview bundle for placement preparations.

Nevertheless, you may consider our paid courses to give your career an edge over others!

Do upvote our blogs if you find them helpful and engaging!

Happy Learning!!

coding ninjas logo

Live masterclass